summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-07-18 07:55:44 +0300
committerAvi Kivity <avi@qumranet.com>2007-07-18 07:55:44 +0300
commit45dff1900d4c3eb81e0a1ea8611c172e4a736088 (patch)
treecc74c9ceef825dc254f4d0bd6205f716bbcc4407
parent0dfb860def58bfb2daa000af490ed1986373fea5 (diff)
parentcb32da0416b823b7f4b65e7e85d6cba16ca4d1e1 (diff)
KVM: Merge remote branch 'origin/master'kvm-30
Conflicts: drivers/kvm/kvm.h drivers/kvm/kvm_main.c drivers/kvm/mmu.c drivers/kvm/svm.c drivers/kvm/vmx.c drivers/kvm/x86_emulate.c
-rw-r--r--.gitignore3
-rw-r--r--Documentation/00-INDEX142
-rw-r--r--Documentation/CodingStyle39
-rw-r--r--Documentation/DocBook/kernel-api.tmpl4
-rw-r--r--Documentation/DocBook/procfs-guide.tmpl82
-rw-r--r--Documentation/RCU/checklist.txt10
-rw-r--r--Documentation/SubmitChecklist3
-rw-r--r--Documentation/SubmittingPatches20
-rw-r--r--Documentation/accounting/getdelays.c19
-rw-r--r--Documentation/accounting/taskstats-struct.txt6
-rw-r--r--Documentation/cachetlb.txt2
-rw-r--r--Documentation/cdrom/00-INDEX22
-rw-r--r--Documentation/cdrom/aztcd822
-rw-r--r--Documentation/cdrom/cdu31a196
-rw-r--r--Documentation/cdrom/cm206185
-rw-r--r--Documentation/cdrom/gscd60
-rw-r--r--Documentation/cdrom/isp16100
-rw-r--r--Documentation/cdrom/mcdx29
-rw-r--r--Documentation/cdrom/optcd57
-rw-r--r--Documentation/cdrom/sbpcd1061
-rw-r--r--Documentation/cdrom/sjcd60
-rw-r--r--Documentation/cdrom/sonycd535122
-rw-r--r--Documentation/fault-injection/failcmd.sh4
-rw-r--r--Documentation/fault-injection/failmodule.sh31
-rw-r--r--Documentation/fault-injection/fault-injection.txt110
-rw-r--r--Documentation/feature-removal-schedule.txt36
-rw-r--r--Documentation/filesystems/configfs/configfs.txt57
-rw-r--r--Documentation/filesystems/configfs/configfs_example.c2
-rw-r--r--Documentation/filesystems/ecryptfs.txt (renamed from Documentation/ecryptfs.txt)0
-rw-r--r--Documentation/filesystems/proc.txt80
-rw-r--r--Documentation/filesystems/vfs.txt51
-rw-r--r--Documentation/hrtimer/timer_stats.txt4
-rw-r--r--Documentation/ioctl-number.txt2
-rw-r--r--Documentation/kernel-parameters.txt143
-rw-r--r--Documentation/m68k/kernel-options.txt7
-rw-r--r--Documentation/networking/net-modules.txt6
-rw-r--r--Documentation/oops-tracing.txt16
-rw-r--r--Documentation/power/freezing-of-tasks.txt160
-rw-r--r--Documentation/power/kernel_threads.txt40
-rw-r--r--Documentation/power/swsusp.txt18
-rw-r--r--Documentation/powerpc/booting-without-of.txt40
-rw-r--r--Documentation/rtc.txt2
-rw-r--r--Documentation/sound/oss/AD181684
-rw-r--r--Documentation/sound/oss/NM256280
-rw-r--r--Documentation/sound/oss/OPL3-SA2210
-rw-r--r--Documentation/sound/oss/VIA-chipset43
-rw-r--r--Documentation/sound/oss/cs46xx138
-rw-r--r--Documentation/spi/spi-lm70llp69
-rw-r--r--Documentation/spinlocks.txt20
-rw-r--r--Documentation/sysctl/ctl_unnumbered.txt22
-rw-r--r--Documentation/sysctl/vm.txt48
-rw-r--r--Documentation/vm/hugetlbpage.txt10
-rw-r--r--Documentation/vm/slub.txt139
-rw-r--r--MAINTAINERS73
-rw-r--r--Makefile3
-rw-r--r--arch/alpha/kernel/ptrace.c4
-rw-r--r--arch/alpha/kernel/smp.c6
-rw-r--r--arch/alpha/kernel/srmcons.c2
-rw-r--r--arch/alpha/kernel/sys_marvel.c2
-rw-r--r--arch/alpha/kernel/time.c2
-rw-r--r--arch/alpha/kernel/traps.c1
-rw-r--r--arch/alpha/lib/checksum.c1
-rw-r--r--arch/arm/kernel/ptrace.c15
-rw-r--r--arch/arm/kernel/traps.c1
-rw-r--r--arch/arm/mach-at91/board-csb337.c10
-rw-r--r--arch/arm/mach-iop32x/n2100.c10
-rw-r--r--arch/arm26/Kconfig3
-rw-r--r--arch/arm26/defconfig1
-rw-r--r--arch/arm26/kernel/ptrace.c15
-rw-r--r--arch/arm26/kernel/traps.c1
-rw-r--r--arch/arm26/mm/init.c3
-rw-r--r--arch/avr32/kernel/ptrace.c13
-rw-r--r--arch/avr32/kernel/traps.c3
-rw-r--r--arch/cris/arch-v10/defconfig1
-rw-r--r--arch/cris/arch-v10/kernel/ptrace.c21
-rw-r--r--arch/cris/arch-v32/drivers/cryptocop.c8
-rw-r--r--arch/cris/arch-v32/drivers/i2c.c8
-rw-r--r--arch/cris/arch-v32/drivers/pcf8563.c8
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c7
-rw-r--r--arch/frv/kernel/entry.S4
-rw-r--r--arch/frv/kernel/gdb-stub.c12
-rw-r--r--arch/frv/kernel/ptrace.c16
-rw-r--r--arch/frv/kernel/setup.c16
-rw-r--r--arch/h8300/Kconfig3
-rw-r--r--arch/h8300/Makefile7
-rw-r--r--arch/h8300/boot/compressed/Makefile4
-rw-r--r--arch/h8300/boot/compressed/head.S2
-rw-r--r--arch/h8300/boot/compressed/vmlinux.lds32
-rw-r--r--arch/h8300/boot/compressed/vmlinux.scr9
-rw-r--r--arch/h8300/kernel/Makefile3
-rw-r--r--arch/h8300/kernel/entry.S (renamed from arch/h8300/platform/h8s/entry.S)302
-rw-r--r--arch/h8300/kernel/ints.c256
-rw-r--r--arch/h8300/kernel/ptrace.c7
-rw-r--r--arch/h8300/kernel/signal.c6
-rw-r--r--arch/h8300/platform/h8300h/Makefile2
-rw-r--r--arch/h8300/platform/h8300h/entry.S332
-rw-r--r--arch/h8300/platform/h8s/Makefile2
-rw-r--r--arch/i386/Kconfig13
-rw-r--r--arch/i386/Makefile1
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/kernel/efi.c2
-rw-r--r--arch/i386/kernel/head.S8
-rw-r--r--arch/i386/kernel/io_apic.c1
-rw-r--r--arch/i386/kernel/nmi.c8
-rw-r--r--arch/i386/kernel/process.c73
-rw-r--r--arch/i386/kernel/ptrace.c17
-rw-r--r--arch/i386/kernel/smpcommon.c8
-rw-r--r--arch/i386/kernel/traps.c3
-rw-r--r--arch/i386/video/Makefile1
-rw-r--r--arch/i386/video/fbdev.c32
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/hp/common/sba_iommu.c20
-rw-r--r--arch/ia64/hp/sim/boot/fw-emu.c5
-rw-r--r--arch/ia64/hp/sim/simserial.c4
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c2
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/kernel/efi.c1
-rw-r--r--arch/ia64/kernel/fsys.S4
-rw-r--r--arch/ia64/kernel/setup.c4
-rw-r--r--arch/ia64/kernel/traps.c1
-rw-r--r--arch/ia64/lib/checksum.c1
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c3
-rw-r--r--arch/m32r/Kconfig3
-rw-r--r--arch/m32r/kernel/ptrace.c19
-rw-r--r--arch/m68k/kernel/ptrace.c8
-rw-r--r--arch/m68k/kernel/traps.c1
-rw-r--r--arch/m68k/lib/checksum.c1
-rw-r--r--arch/m68knommu/kernel/process.c2
-rw-r--r--arch/m68knommu/kernel/ptrace.c17
-rw-r--r--arch/m68knommu/kernel/setup.c65
-rw-r--r--arch/m68knommu/kernel/traps.c1
-rw-r--r--arch/m68knommu/mm/memory.c80
-rw-r--r--arch/mips/kernel/ptrace.c18
-rw-r--r--arch/mips/kernel/traps.c1
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c1
-rw-r--r--arch/mips/sibyte/sb1250/setup.c1
-rw-r--r--arch/parisc/kernel/ptrace.c13
-rw-r--r--arch/parisc/kernel/traps.c3
-rw-r--r--arch/parisc/kernel/unwind.c2
-rw-r--r--arch/powerpc/Kconfig274
-rw-r--r--arch/powerpc/Makefile2
-rw-r--r--arch/powerpc/boot/44x.c45
-rw-r--r--arch/powerpc/boot/44x.h3
-rw-r--r--arch/powerpc/boot/Makefile81
-rw-r--r--arch/powerpc/boot/cuboot-83xx.c13
-rw-r--r--arch/powerpc/boot/cuboot-85xx.c13
-rw-r--r--arch/powerpc/boot/cuboot-ebony.c16
-rw-r--r--arch/powerpc/boot/cuboot.c35
-rw-r--r--arch/powerpc/boot/cuboot.h14
-rw-r--r--arch/powerpc/boot/dcr.h37
-rw-r--r--arch/powerpc/boot/dts/ebony.dts12
-rw-r--r--arch/powerpc/boot/dts/holly.dts52
-rw-r--r--arch/powerpc/boot/dts/mpc7448hpc2.dts33
-rw-r--r--arch/powerpc/boot/dts/mpc8272ads.dts42
-rw-r--r--arch/powerpc/boot/dts/mpc832x_mds.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc832x_rdb.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitx.dts10
-rw-r--r--arch/powerpc/boot/dts/mpc834x_mds.dts10
-rw-r--r--arch/powerpc/boot/dts/mpc836x_mds.dts16
-rw-r--r--arch/powerpc/boot/dts/mpc8540ads.dts147
-rw-r--r--arch/powerpc/boot/dts/mpc8541cds.dts90
-rw-r--r--arch/powerpc/boot/dts/mpc8544ds.dts18
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dts108
-rw-r--r--arch/powerpc/boot/dts/mpc8555cds.dts90
-rw-r--r--arch/powerpc/boot/dts/mpc8560ads.dts148
-rw-r--r--arch/powerpc/boot/dts/mpc8568mds.dts66
-rw-r--r--arch/powerpc/boot/dts/mpc8641_hpcn.dts147
-rw-r--r--arch/powerpc/boot/dts/mpc866ads.dts31
-rw-r--r--arch/powerpc/boot/dts/mpc885ads.dts54
-rw-r--r--arch/powerpc/boot/dts/prpmc2800.dts2
-rw-r--r--arch/powerpc/boot/dts/ps3.dts68
-rw-r--r--arch/powerpc/boot/ebony.c19
-rw-r--r--arch/powerpc/boot/main.c2
-rw-r--r--arch/powerpc/boot/of.c212
-rw-r--r--arch/powerpc/boot/of.h21
-rw-r--r--arch/powerpc/boot/ofconsole.c45
-rw-r--r--arch/powerpc/boot/oflib.c202
-rw-r--r--arch/powerpc/boot/ops.h4
-rw-r--r--arch/powerpc/boot/ps3-head.S80
-rw-r--r--arch/powerpc/boot/ps3-hvcall.S184
-rw-r--r--arch/powerpc/boot/ps3.c161
-rw-r--r--arch/powerpc/boot/serial.c2
-rw-r--r--arch/powerpc/boot/stdio.c10
-rw-r--r--arch/powerpc/boot/types.h4
-rwxr-xr-xarch/powerpc/boot/wrapper55
-rw-r--r--arch/powerpc/boot/zImage.ps3.lds.S50
-rw-r--r--arch/powerpc/configs/holly_defconfig6
-rw-r--r--arch/powerpc/configs/ps3_defconfig52
-rw-r--r--arch/powerpc/kernel/Makefile7
-rw-r--r--arch/powerpc/kernel/cputable.c35
-rw-r--r--arch/powerpc/kernel/head_32.S122
-rw-r--r--arch/powerpc/kernel/head_64.S4
-rw-r--r--arch/powerpc/kernel/io.c12
-rw-r--r--arch/powerpc/kernel/irq.c60
-rw-r--r--arch/powerpc/kernel/isa-bridge.c271
-rw-r--r--arch/powerpc/kernel/misc_32.S10
-rw-r--r--arch/powerpc/kernel/misc_64.S26
-rw-r--r--arch/powerpc/kernel/of_platform.c8
-rw-r--r--arch/powerpc/kernel/pci-common.c454
-rw-r--r--arch/powerpc/kernel/pci_32.c510
-rw-r--r--arch/powerpc/kernel/pci_64.c750
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c5
-rw-r--r--arch/powerpc/kernel/process.c14
-rw-r--r--arch/powerpc/kernel/prom.c29
-rw-r--r--arch/powerpc/kernel/prom_init.c4
-rw-r--r--arch/powerpc/kernel/ptrace-common.h161
-rw-r--r--arch/powerpc/kernel/ptrace.c343
-rw-r--r--arch/powerpc/kernel/ptrace32.c239
-rw-r--r--arch/powerpc/kernel/rtas_pci.c7
-rw-r--r--arch/powerpc/kernel/setup-common.c21
-rw-r--r--arch/powerpc/kernel/setup_32.c12
-rw-r--r--arch/powerpc/kernel/setup_64.c12
-rw-r--r--arch/powerpc/kernel/signal.c180
-rw-r--r--arch/powerpc/kernel/signal.h55
-rw-r--r--arch/powerpc/kernel/signal_32.c191
-rw-r--r--arch/powerpc/kernel/signal_64.c182
-rw-r--r--arch/powerpc/kernel/sysfs.c5
-rw-r--r--arch/powerpc/kernel/time.c65
-rw-r--r--arch/powerpc/kernel/traps.c3
-rw-r--r--arch/powerpc/kernel/vdso.c2
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S6
-rw-r--r--arch/powerpc/mm/44x_mmu.c1
-rw-r--r--arch/powerpc/mm/4xx_mmu.c1
-rw-r--r--arch/powerpc/mm/Makefile3
-rw-r--r--arch/powerpc/mm/fault.c2
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c1
-rw-r--r--arch/powerpc/mm/hash_native_64.c27
-rw-r--r--arch/powerpc/mm/hash_utils_64.c2
-rw-r--r--arch/powerpc/mm/imalloc.c313
-rw-r--r--arch/powerpc/mm/init_32.c1
-rw-r--r--arch/powerpc/mm/init_64.c1
-rw-r--r--arch/powerpc/mm/mem.c3
-rw-r--r--arch/powerpc/mm/mmu_context_32.c1
-rw-r--r--arch/powerpc/mm/mmu_decl.h17
-rw-r--r--arch/powerpc/mm/pgtable_32.c123
-rw-r--r--arch/powerpc/mm/pgtable_64.c206
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c7
-rw-r--r--arch/powerpc/mm/stab.c4
-rw-r--r--arch/powerpc/mm/tlb_32.c1
-rw-r--r--arch/powerpc/mm/tlb_64.c57
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c14
-rw-r--r--arch/powerpc/platforms/52xx/efika.c13
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c18
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pm.c8
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/82xx/mpc82xx_ads.c17
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/83xx/Makefile2
-rw-r--r--arch/powerpc/platforms/83xx/mpc8313_rdb.c8
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c7
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c7
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c9
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c56
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c7
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h34
-rw-r--r--arch/powerpc/platforms/83xx/pci.c18
-rw-r--r--arch/powerpc/platforms/83xx/usb.c181
-rw-r--r--arch/powerpc/platforms/85xx/misc.c32
-rw-r--r--arch/powerpc/platforms/85xx/mpc8544_ds.c15
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx.h2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c32
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c116
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c28
-rw-r--r--arch/powerpc/platforms/85xx/pci.c11
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx.h11
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c27
-rw-r--r--arch/powerpc/platforms/86xx/pci.c67
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c5
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c188
-rw-r--r--arch/powerpc/platforms/Kconfig29
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype221
-rw-r--r--arch/powerpc/platforms/apus/Kconfig130
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c74
-rw-r--r--arch/powerpc/platforms/cell/spu_manage.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c15
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c29
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c149
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c45
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c476
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_restore.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_save.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h84
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c18
-rw-r--r--arch/powerpc/platforms/chrp/Kconfig1
-rw-r--r--arch/powerpc/platforms/chrp/Makefile3
-rw-r--r--arch/powerpc/platforms/chrp/pci.c7
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/embedded6xx/holly.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c10
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c9
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h5
-rw-r--r--arch/powerpc/platforms/iseries/call_hpt.h9
-rw-r--r--arch/powerpc/platforms/iseries/htab.c8
-rw-r--r--arch/powerpc/platforms/iseries/pci.c7
-rw-r--r--arch/powerpc/platforms/iseries/setup.c6
-rw-r--r--arch/powerpc/platforms/maple/pci.c41
-rw-r--r--arch/powerpc/platforms/pasemi/Kconfig9
-rw-r--r--arch/powerpc/platforms/pasemi/Makefile1
-rw-r--r--arch/powerpc/platforms/pasemi/electra_ide.c96
-rw-r--r--arch/powerpc/platforms/pasemi/pci.c24
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c2
-rw-r--r--arch/powerpc/platforms/powermac/Kconfig1
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c23
-rw-r--r--arch/powerpc/platforms/powermac/pci.c46
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig26
-rw-r--r--arch/powerpc/platforms/ps3/Makefile1
-rw-r--r--arch/powerpc/platforms/ps3/device-init.c785
-rw-r--r--arch/powerpc/platforms/ps3/htab.c31
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c272
-rw-r--r--arch/powerpc/platforms/ps3/mm.c632
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c4
-rw-r--r--arch/powerpc/platforms/ps3/platform.h43
-rw-r--r--arch/powerpc/platforms/ps3/repository.c586
-rw-r--r--arch/powerpc/platforms/ps3/setup.c105
-rw-r--r--arch/powerpc/platforms/ps3/smp.c18
-rw-r--r--arch/powerpc/platforms/ps3/spu.c19
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c562
-rw-r--r--arch/powerpc/platforms/ps3/time.c2
-rw-r--r--arch/powerpc/platforms/pseries/Makefile2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c19
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c5
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c6
-rw-r--r--arch/powerpc/platforms/pseries/eeh_sysfs.c87
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c17
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c9
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h15
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h2
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/xics.c53
-rw-r--r--arch/powerpc/sysdev/Makefile6
-rw-r--r--arch/powerpc/sysdev/fsl_pcie.c171
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c13
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c44
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.h11
-rw-r--r--arch/powerpc/sysdev/mv64x60_dev.c28
-rw-r--r--arch/powerpc/sysdev/mv64x60_pci.c7
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc.c2
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c8
-rw-r--r--arch/powerpc/sysdev/rtc_cmos_setup.c49
-rw-r--r--arch/powerpc/sysdev/timer.c14
-rw-r--r--arch/powerpc/sysdev/tsi108_dev.c33
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c10
-rw-r--r--arch/powerpc/xmon/xmon.c2
-rw-r--r--arch/ppc/kernel/misc.S8
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c1
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--arch/ppc/kernel/traps.c3
-rw-r--r--arch/ppc/mm/tlb.c1
-rw-r--r--arch/ppc/platforms/prep_setup.c3
-rw-r--r--arch/ppc/syslib/Makefile1
-rw-r--r--arch/ppc/syslib/indirect_pci.c134
-rw-r--r--arch/ppc/syslib/virtex_devices.c38
-rw-r--r--arch/ppc/syslib/virtex_devices.h7
-rw-r--r--arch/s390/defconfig110
-rw-r--r--arch/s390/kernel/dis.c7
-rw-r--r--arch/s390/kernel/ptrace.c11
-rw-r--r--arch/s390/kernel/stacktrace.c26
-rw-r--r--arch/s390/kernel/traps.c3
-rw-r--r--arch/sh/Kconfig441
-rw-r--r--arch/sh/Kconfig.debug5
-rw-r--r--arch/sh/Makefile104
-rw-r--r--arch/sh/boards/dreamcast/setup.c3
-rw-r--r--arch/sh/boards/hp6xx/mach.c46
-rw-r--r--arch/sh/boards/hp6xx/setup.c3
-rw-r--r--arch/sh/boards/landisk/setup.c3
-rw-r--r--arch/sh/boards/lboxre2/setup.c3
-rw-r--r--arch/sh/boards/mpc1211/setup.c3
-rw-r--r--arch/sh/boards/renesas/edosk7705/setup.c3
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/setup.c3
-rw-r--r--arch/sh/boards/renesas/r7780rp/Kconfig6
-rw-r--r--arch/sh/boards/renesas/r7780rp/setup.c3
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/setup.c3
-rw-r--r--arch/sh/boards/renesas/sh7710voipgw/setup.c3
-rw-r--r--arch/sh/boards/renesas/systemh/setup.c3
-rw-r--r--arch/sh/boards/saturn/Makefile8
-rw-r--r--arch/sh/boards/saturn/io.c26
-rw-r--r--arch/sh/boards/saturn/irq.c118
-rw-r--r--arch/sh/boards/saturn/setup.c31
-rw-r--r--arch/sh/boards/saturn/smp.c68
-rw-r--r--arch/sh/boards/se/7206/setup.c3
-rw-r--r--arch/sh/boards/se/7300/setup.c3
-rw-r--r--arch/sh/boards/se/73180/setup.c3
-rw-r--r--arch/sh/boards/se/7343/setup.c3
-rw-r--r--arch/sh/boards/se/7619/setup.c3
-rw-r--r--arch/sh/boards/se/770x/irq.c124
-rw-r--r--arch/sh/boards/se/770x/setup.c3
-rw-r--r--arch/sh/boards/se/7722/irq.c15
-rw-r--r--arch/sh/boards/se/7722/setup.c3
-rw-r--r--arch/sh/boards/se/7751/irq.c59
-rw-r--r--arch/sh/boards/se/7751/setup.c3
-rw-r--r--arch/sh/boards/se/7780/irq.c45
-rw-r--r--arch/sh/boards/se/7780/setup.c3
-rw-r--r--arch/sh/boards/sh03/setup.c31
-rw-r--r--arch/sh/boards/shmin/setup.c33
-rw-r--r--arch/sh/boards/snapgear/setup.c31
-rw-r--r--arch/sh/boards/superh/microdev/setup.c3
-rw-r--r--arch/sh/boards/titan/setup.c25
-rw-r--r--arch/sh/boards/unknown/Makefile6
-rw-r--r--arch/sh/boards/unknown/setup.c21
-rw-r--r--arch/sh/cchips/Kconfig6
-rw-r--r--arch/sh/configs/dreamcast_defconfig338
-rw-r--r--arch/sh/configs/r7780mp_defconfig1223
-rw-r--r--arch/sh/configs/r7785rp_defconfig296
-rw-r--r--arch/sh/configs/se7206_defconfig272
-rw-r--r--arch/sh/configs/se7619_defconfig215
-rw-r--r--arch/sh/configs/se7722_defconfig287
-rw-r--r--arch/sh/configs/shx3_defconfig756
-rw-r--r--arch/sh/drivers/dma/Kconfig17
-rw-r--r--arch/sh/drivers/pci/Kconfig1
-rw-r--r--arch/sh/kernel/Makefile9
-rw-r--r--arch/sh/kernel/cf-enabler.c6
-rw-r--r--arch/sh/kernel/cpu/init.c15
-rw-r--r--arch/sh/kernel/cpu/irq/intc2.c63
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c59
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S1
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c13
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c24
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c24
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S19
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7705.c40
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7709.c112
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7710.c42
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile4
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c8
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c58
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c45
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-shx3.c135
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c29
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c15
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7785.c16
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-shx3.c85
-rw-r--r--arch/sh/kernel/irq.c8
-rw-r--r--arch/sh/kernel/machvec.c130
-rw-r--r--arch/sh/kernel/process.c18
-rw-r--r--arch/sh/kernel/ptrace.c24
-rw-r--r--arch/sh/kernel/setup.c210
-rw-r--r--arch/sh/kernel/sh_ksyms.c10
-rw-r--r--arch/sh/kernel/signal.c3
-rw-r--r--arch/sh/kernel/syscalls.S6
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c7
-rw-r--r--arch/sh/kernel/topology.c49
-rw-r--r--arch/sh/kernel/traps.c8
-rw-r--r--arch/sh/kernel/vmlinux.lds.S20
-rw-r--r--arch/sh/lib/div64-generic.c9
-rw-r--r--arch/sh/lib/div64.S6
-rw-r--r--arch/sh/math-emu/math.c18
-rw-r--r--arch/sh/mm/Kconfig87
-rw-r--r--arch/sh/mm/Makefile5
-rw-r--r--arch/sh/mm/fault.c45
-rw-r--r--arch/sh/mm/init.c107
-rw-r--r--arch/sh/mm/numa.c92
-rw-r--r--arch/sh/mm/pg-dma.c95
-rw-r--r--arch/sh/tools/Makefile1
-rw-r--r--arch/sh/tools/mach-types2
-rw-r--r--arch/sh64/kernel/ptrace.c17
-rw-r--r--arch/sh64/lib/c-checksum.c1
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/kernel/traps.c1
-rw-r--r--arch/sparc/mm/srmmu.c4
-rw-r--r--arch/sparc/mm/sun4c.c6
-rw-r--r--arch/sparc64/Kconfig15
-rw-r--r--arch/sparc64/defconfig155
-rw-r--r--arch/sparc64/kernel/Makefile3
-rw-r--r--arch/sparc64/kernel/ds.c1168
-rw-r--r--arch/sparc64/kernel/hvtramp.S140
-rw-r--r--arch/sparc64/kernel/irq.c84
-rw-r--r--arch/sparc64/kernel/ldc.c2373
-rw-r--r--arch/sparc64/kernel/mdesc.c690
-rw-r--r--arch/sparc64/kernel/power.c54
-rw-r--r--arch/sparc64/kernel/process.c21
-rw-r--r--arch/sparc64/kernel/prom.c2
-rw-r--r--arch/sparc64/kernel/setup.c5
-rw-r--r--arch/sparc64/kernel/signal.c15
-rw-r--r--arch/sparc64/kernel/smp.c251
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c16
-rw-r--r--arch/sparc64/kernel/sysfs.c2
-rw-r--r--arch/sparc64/kernel/time.c28
-rw-r--r--arch/sparc64/kernel/traps.c1
-rw-r--r--arch/sparc64/kernel/vio.c395
-rw-r--r--arch/sparc64/kernel/viohs.c792
-rw-r--r--arch/sparc64/lib/Makefile2
-rw-r--r--arch/sparc64/lib/delay.c46
-rw-r--r--arch/sparc64/prom/misc.c13
-rw-r--r--arch/sparc64/prom/p1275.c1
-rw-r--r--arch/sparc64/prom/tree.c13
-rw-r--r--arch/um/Kconfig.debug9
-rw-r--r--arch/um/config.release333
-rw-r--r--arch/um/defconfig3
-rw-r--r--arch/um/drivers/chan_kern.c23
-rw-r--r--arch/um/drivers/chan_user.c78
-rw-r--r--arch/um/drivers/cow_sys.h2
-rw-r--r--arch/um/drivers/daemon_user.c4
-rw-r--r--arch/um/drivers/fd.c2
-rw-r--r--arch/um/drivers/harddog_user.c2
-rw-r--r--arch/um/drivers/line.c65
-rw-r--r--arch/um/drivers/mcast_user.c2
-rw-r--r--arch/um/drivers/mconsole_user.c5
-rw-r--r--arch/um/drivers/net_user.c4
-rw-r--r--arch/um/drivers/pcap_user.c2
-rw-r--r--arch/um/drivers/port_user.c4
-rw-r--r--arch/um/drivers/pty.c78
-rw-r--r--arch/um/drivers/slip_user.c4
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c10
-rw-r--r--arch/um/drivers/stdio_console.c9
-rw-r--r--arch/um/drivers/tty.c2
-rw-r--r--arch/um/drivers/ubd_kern.c8
-rw-r--r--arch/um/drivers/ubd_user.c6
-rw-r--r--arch/um/drivers/xterm.c174
-rw-r--r--arch/um/drivers/xterm_kern.c49
-rw-r--r--arch/um/include/chan_kern.h2
-rw-r--r--arch/um/include/chan_user.h5
-rw-r--r--arch/um/include/common-offsets.h3
-rw-r--r--arch/um/include/os.h6
-rw-r--r--arch/um/include/um_malloc.h12
-rw-r--r--arch/um/kernel/irq.c1
-rw-r--r--arch/um/kernel/process.c16
-rw-r--r--arch/um/kernel/ptrace.c18
-rw-r--r--arch/um/os-Linux/aio.c11
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c6
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/helper.c23
-rw-r--r--arch/um/os-Linux/main.c4
-rw-r--r--arch/um/os-Linux/sigio.c23
-rw-r--r--arch/um/os-Linux/skas/process.c2
-rw-r--r--arch/um/os-Linux/user_syms.c20
-rw-r--r--arch/v850/kernel/ptrace.c14
-rw-r--r--arch/x86_64/Kconfig4
-rw-r--r--arch/x86_64/ia32/ia32entry.S2
-rw-r--r--arch/x86_64/kernel/head.S15
-rw-r--r--arch/x86_64/kernel/nmi.c8
-rw-r--r--arch/x86_64/kernel/ptrace.c17
-rw-r--r--arch/x86_64/kernel/smp.c12
-rw-r--r--arch/x86_64/kernel/traps.c4
-rw-r--r--arch/xtensa/kernel/ptrace.c17
-rw-r--r--arch/xtensa/kernel/traps.c1
-rw-r--r--block/Kconfig13
-rw-r--r--block/Makefile1
-rw-r--r--block/as-iosched.c3
-rw-r--r--block/bsg.c1095
-rw-r--r--block/cfq-iosched.c18
-rw-r--r--block/deadline-iosched.c3
-rw-r--r--block/elevator.c3
-rw-r--r--block/genhd.c20
-rw-r--r--block/ll_rw_blk.c5
-rw-r--r--block/scsi_ioctl.c163
-rw-r--r--crypto/proc.c17
-rw-r--r--drivers/ata/sata_mv.c2
-rw-r--r--drivers/atm/Kconfig8
-rw-r--r--drivers/atm/ambassador.c4
-rw-r--r--drivers/atm/zatm.c4
-rw-r--r--drivers/auxdisplay/Kconfig8
-rw-r--r--drivers/base/dmapool.c2
-rw-r--r--drivers/block/Kconfig26
-rw-r--r--drivers/block/Makefile3
-rw-r--r--drivers/block/acsi_slm.c1032
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/loop.c11
-rw-r--r--drivers/block/nbd.c22
-rw-r--r--drivers/block/pktcdvd.c4
-rw-r--r--drivers/block/sunvdc.c972
-rw-r--r--drivers/block/ub.c2
-rw-r--r--drivers/block/umem.c58
-rw-r--r--drivers/block/viodasd.c4
-rw-r--r--drivers/block/xsysace.c1164
-rw-r--r--drivers/block/z2ram.c7
-rw-r--r--drivers/cdrom/cdrom.c3
-rw-r--r--drivers/char/Kconfig19
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/amiserial.c7
-rw-r--r--drivers/char/apm-emulation.c12
-rw-r--r--drivers/char/briq_panel.c10
-rw-r--r--drivers/char/consolemap.c78
-rw-r--r--drivers/char/cyclades.c371
-rw-r--r--drivers/char/drm/ati_pcigart.c8
-rw-r--r--drivers/char/drm/drm.h329
-rw-r--r--drivers/char/drm/drmP.h356
-rw-r--r--drivers/char/drm/drm_agpsupport.c116
-rw-r--r--drivers/char/drm/drm_auth.c40
-rw-r--r--drivers/char/drm/drm_bufs.c209
-rw-r--r--drivers/char/drm/drm_context.c226
-rw-r--r--drivers/char/drm/drm_dma.c12
-rw-r--r--drivers/char/drm/drm_drawable.c270
-rw-r--r--drivers/char/drm/drm_drv.c87
-rw-r--r--drivers/char/drm/drm_fops.c68
-rw-r--r--drivers/char/drm/drm_hashtab.c34
-rw-r--r--drivers/char/drm/drm_hashtab.h24
-rw-r--r--drivers/char/drm/drm_ioc32.c82
-rw-r--r--drivers/char/drm/drm_ioctl.c68
-rw-r--r--drivers/char/drm/drm_irq.c58
-rw-r--r--drivers/char/drm/drm_lock.c28
-rw-r--r--drivers/char/drm/drm_memory.c8
-rw-r--r--drivers/char/drm/drm_mm.c66
-rw-r--r--drivers/char/drm/drm_os_linux.h22
-rw-r--r--drivers/char/drm/drm_pci.c6
-rw-r--r--drivers/char/drm/drm_proc.c50
-rw-r--r--drivers/char/drm/drm_sarea.h26
-rw-r--r--drivers/char/drm/drm_scatter.c22
-rw-r--r--drivers/char/drm/drm_sman.c93
-rw-r--r--drivers/char/drm/drm_sman.h50
-rw-r--r--drivers/char/drm/drm_stub.c32
-rw-r--r--drivers/char/drm/drm_sysfs.c4
-rw-r--r--drivers/char/drm/drm_vm.c106
-rw-r--r--drivers/char/drm/i810_dma.c164
-rw-r--r--drivers/char/drm/i810_drm.h2
-rw-r--r--drivers/char/drm/i810_drv.h18
-rw-r--r--drivers/char/drm/i830_dma.c157
-rw-r--r--drivers/char/drm/i830_drm.h2
-rw-r--r--drivers/char/drm/i830_drv.h24
-rw-r--r--drivers/char/drm/i830_irq.c20
-rw-r--r--drivers/char/drm/i915_dma.c44
-rw-r--r--drivers/char/drm/i915_drm.h8
-rw-r--r--drivers/char/drm/i915_drv.h22
-rw-r--r--drivers/char/drm/i915_irq.c28
-rw-r--r--drivers/char/drm/i915_mem.c6
-rw-r--r--drivers/char/drm/mga_dma.c79
-rw-r--r--drivers/char/drm/mga_drm.h6
-rw-r--r--drivers/char/drm/mga_drv.c4
-rw-r--r--drivers/char/drm/mga_drv.h22
-rw-r--r--drivers/char/drm/mga_irq.c12
-rw-r--r--drivers/char/drm/mga_state.c36
-rw-r--r--drivers/char/drm/r128_cce.c41
-rw-r--r--drivers/char/drm/r128_drm.h4
-rw-r--r--drivers/char/drm/r128_drv.h20
-rw-r--r--drivers/char/drm/r128_irq.c10
-rw-r--r--drivers/char/drm/r128_state.c60
-rw-r--r--drivers/char/drm/r300_cmdbuf.c53
-rw-r--r--drivers/char/drm/r300_reg.h1163
-rw-r--r--drivers/char/drm/radeon_cp.c54
-rw-r--r--drivers/char/drm/radeon_drm.h12
-rw-r--r--drivers/char/drm/radeon_drv.c3
-rw-r--r--drivers/char/drm/radeon_drv.h45
-rw-r--r--drivers/char/drm/radeon_irq.c118
-rw-r--r--drivers/char/drm/radeon_state.c108
-rw-r--r--drivers/char/drm/savage_bci.c44
-rw-r--r--drivers/char/drm/savage_drm.h4
-rw-r--r--drivers/char/drm/savage_drv.h20
-rw-r--r--drivers/char/drm/savage_state.c28
-rw-r--r--drivers/char/drm/sis_drv.c4
-rw-r--r--drivers/char/drm/sis_drv.h9
-rw-r--r--drivers/char/drm/sis_mm.c18
-rw-r--r--drivers/char/drm/via_dma.c10
-rw-r--r--drivers/char/drm/via_dmablit.c20
-rw-r--r--drivers/char/drm/via_dmablit.h2
-rw-r--r--drivers/char/drm/via_drm.h4
-rw-r--r--drivers/char/drm/via_drv.h32
-rw-r--r--drivers/char/drm/via_irq.c12
-rw-r--r--drivers/char/drm/via_map.c10
-rw-r--r--drivers/char/drm/via_mm.c6
-rw-r--r--drivers/char/drm/via_verifier.c12
-rw-r--r--drivers/char/drm/via_verifier.h6
-rw-r--r--drivers/char/esp.c7
-rw-r--r--drivers/char/generic_serial.c120
-rw-r--r--drivers/char/genrtc.c22
-rw-r--r--drivers/char/hvc_console.c3
-rw-r--r--drivers/char/hw_random/intel-rng.c10
-rw-r--r--drivers/char/ip2/i2ellis.c44
-rw-r--r--drivers/char/ipmi/Kconfig15
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/isicom.c93
-rw-r--r--drivers/char/istallion.c12
-rw-r--r--drivers/char/keyboard.c26
-rw-r--r--drivers/char/misc.c18
-rw-r--r--drivers/char/moxa.c37
-rw-r--r--drivers/char/mspec.c2
-rw-r--r--drivers/char/mxser.c16
-rw-r--r--drivers/char/mxser_new.c22
-rw-r--r--drivers/char/n_hdlc.c16
-rw-r--r--drivers/char/n_r3964.c14
-rw-r--r--drivers/char/n_tty.c23
-rw-r--r--drivers/char/nvram.c192
-rw-r--r--drivers/char/riscom8.c12
-rw-r--r--drivers/char/rocket.c3
-rw-r--r--drivers/char/rtc.c3
-rw-r--r--drivers/char/selection.c48
-rw-r--r--drivers/char/sonypi.c47
-rw-r--r--drivers/char/specialix.c16
-rw-r--r--drivers/char/stallion.c5
-rw-r--r--drivers/char/synclink.c8
-rw-r--r--drivers/char/synclink_gt.c8
-rw-r--r--drivers/char/synclinkmp.c8
-rw-r--r--drivers/char/tpm/Kconfig18
-rw-r--r--drivers/char/tty_audit.c345
-rw-r--r--drivers/char/tty_io.c65
-rw-r--r--drivers/char/tty_ioctl.c32
-rw-r--r--drivers/char/viotape.c12
-rw-r--r--drivers/char/vt.c35
-rw-r--r--drivers/char/watchdog/Kconfig9
-rw-r--r--drivers/char/watchdog/Makefile3
-rw-r--r--drivers/char/watchdog/at32ap700x_wdt.c386
-rw-r--r--drivers/char/watchdog/ep93xx_wdt.c4
-rw-r--r--drivers/char/watchdog/mixcomwd.c127
-rw-r--r--drivers/char/watchdog/pnx4008_wdt.c4
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c41
-rw-r--r--drivers/connector/Kconfig7
-rw-r--r--drivers/crypto/Kconfig9
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/edac/Kconfig14
-rw-r--r--drivers/edac/edac_mc.c1
-rw-r--r--drivers/firmware/edd.c7
-rw-r--r--drivers/firmware/pcdp.c6
-rw-r--r--drivers/hwmon/lm70.c4
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c2
-rw-r--r--drivers/i2c/chips/Kconfig10
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/menelaus.c1281
-rw-r--r--drivers/ide/ide-floppy.c29
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide.c2
-rw-r--r--drivers/ieee1394/ieee1394_core.c3
-rw-r--r--drivers/ieee1394/nodemgr.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c4
-rw-r--r--drivers/input/gameport/gameport.c1
-rw-r--r--drivers/input/serio/serio.c1
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c1
-rw-r--r--drivers/isdn/Kconfig15
-rw-r--r--drivers/isdn/capi/Kconfig7
-rw-r--r--drivers/isdn/capi/capi.c2
-rw-r--r--drivers/isdn/capi/kcapi.c6
-rw-r--r--drivers/isdn/capi/kcapi_proc.c28
-rw-r--r--drivers/isdn/hardware/Kconfig1
-rw-r--r--drivers/isdn/hardware/avm/Kconfig23
-rw-r--r--drivers/isdn/hardware/eicon/Kconfig22
-rw-r--r--drivers/isdn/hardware/eicon/idifunc.c1
-rw-r--r--drivers/isdn/hisax/bkm_a4t.c108
-rw-r--r--drivers/isdn/hisax/config.c243
-rw-r--r--drivers/isdn/hisax/enternow_pci.c165
-rw-r--r--drivers/isdn/hisax/hfc_pci.c191
-rw-r--r--drivers/isdn/hisax/nj_s.c194
-rw-r--r--drivers/isdn/hisax/nj_u.c167
-rw-r--r--drivers/isdn/hisax/sedlbauer.c8
-rw-r--r--drivers/isdn/i4l/Kconfig7
-rw-r--r--drivers/kvm/kvm_main.c4
-rw-r--r--drivers/macintosh/adb.c10
-rw-r--r--drivers/macintosh/therm_adt746x.c1
-rw-r--r--drivers/macintosh/windfarm_core.c1
-rw-r--r--drivers/md/Kconfig15
-rw-r--r--drivers/md/bitmap.c169
-rw-r--r--drivers/md/dm.c4
-rw-r--r--drivers/md/md.c71
-rw-r--r--drivers/md/raid1.c3
-rw-r--r--drivers/md/raid10.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c1
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c1
-rw-r--r--drivers/media/video/msp3400-kthreads.c6
-rw-r--r--drivers/media/video/tvaudio.c2
-rw-r--r--drivers/media/video/video-buf-dvb.c1
-rw-r--r--drivers/media/video/vivi.c1
-rw-r--r--drivers/message/i2o/Kconfig22
-rw-r--r--drivers/message/i2o/debug.c134
-rw-r--r--drivers/message/i2o/device.c16
-rw-r--r--drivers/message/i2o/exec-osm.c10
-rw-r--r--drivers/message/i2o/i2o_block.c2
-rw-r--r--drivers/message/i2o/i2o_config.c62
-rw-r--r--drivers/message/i2o/iop.c2
-rw-r--r--drivers/mfd/ucb1x00-ts.c1
-rw-r--r--drivers/misc/Kconfig10
-rw-r--r--drivers/misc/ibmasm/command.c14
-rw-r--r--drivers/misc/ibmasm/dot_command.c10
-rw-r--r--drivers/misc/ibmasm/dot_command.h2
-rw-r--r--drivers/misc/ibmasm/event.c8
-rw-r--r--drivers/misc/ibmasm/heartbeat.c2
-rw-r--r--drivers/misc/ibmasm/i2o.h10
-rw-r--r--drivers/misc/ibmasm/ibmasm.h70
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c24
-rw-r--r--drivers/misc/ibmasm/lowlevel.c2
-rw-r--r--drivers/misc/ibmasm/lowlevel.h16
-rw-r--r--drivers/misc/ibmasm/module.c10
-rw-r--r--drivers/misc/ibmasm/r_heartbeat.c10
-rw-r--r--drivers/misc/ibmasm/remote.c37
-rw-r--r--drivers/misc/ibmasm/remote.h8
-rw-r--r--drivers/misc/ibmasm/uart.c2
-rw-r--r--drivers/misc/sony-laptop.c3
-rw-r--r--drivers/mmc/card/queue.c7
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
-rw-r--r--drivers/mtd/ubi/eba.c4
-rw-r--r--drivers/mtd/ubi/wl.c1
-rw-r--r--drivers/net/8139cp.c27
-rw-r--r--drivers/net/Kconfig24
-rw-r--r--drivers/net/Makefile3
-rw-r--r--drivers/net/Space.c8
-rw-r--r--drivers/net/arm/Kconfig1
-rw-r--r--drivers/net/atari_bionet.c675
-rw-r--r--drivers/net/atari_pamsnet.c878
-rw-r--r--drivers/net/atl1/atl1.h156
-rw-r--r--drivers/net/atl1/atl1_main.c2177
-rw-r--r--drivers/net/eepro100.c7
-rw-r--r--drivers/net/ehea/ehea.h23
-rw-r--r--drivers/net/ehea/ehea_main.c144
-rw-r--r--drivers/net/ehea/ehea_phyp.h3
-rw-r--r--drivers/net/ehea/ehea_qmr.c156
-rw-r--r--drivers/net/ehea/ehea_qmr.h14
-rw-r--r--drivers/net/forcedeth.c162
-rw-r--r--drivers/net/gianfar_mii.c1
-rw-r--r--drivers/net/macb.c563
-rw-r--r--drivers/net/macb.h10
-rw-r--r--drivers/net/myri10ge/myri10ge.c6
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/ne2k-pci.c7
-rw-r--r--drivers/net/r8169.c2
-rw-r--r--drivers/net/s2io.c4
-rw-r--r--drivers/net/sunvnet.c1164
-rw-r--r--drivers/net/sunvnet.h70
-rw-r--r--drivers/net/tokenring/smctr.c6
-rw-r--r--drivers/net/usb/cdc_subset.c3
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--drivers/net/wan/pc300_drv.c2
-rw-r--r--drivers/net/wan/sbni.c7
-rw-r--r--drivers/net/wireless/airo.c211
-rw-r--r--drivers/net/wireless/ipw2100.c11
-rw-r--r--drivers/net/wireless/ipw2200.c5
-rw-r--r--drivers/net/wireless/libertas/cmd.c2
-rw-r--r--drivers/net/wireless/libertas/main.c1
-rw-r--r--drivers/net/wireless/libertas/rx.c1
-rw-r--r--drivers/net/wireless/libertas/version.h1
-rw-r--r--drivers/net/wireless/libertas/wext.c3
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c22
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c88
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h13
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c59
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c12
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al7230b.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_rf2959.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c98
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h3
-rw-r--r--drivers/parisc/hppb.c1
-rw-r--r--drivers/parport/Kconfig26
-rw-r--r--drivers/parport/parport_pc.c5
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c6
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/probe.c12
-rw-r--r--drivers/pci/proc.c2
-rw-r--r--drivers/pci/search.c4
-rw-r--r--drivers/pcmcia/Kconfig17
-rw-r--r--drivers/pcmcia/cs.c1
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c829
-rw-r--r--drivers/pnp/Kconfig13
-rw-r--r--drivers/pnp/isapnp/Kconfig2
-rw-r--r--drivers/pnp/isapnp/core.c2
-rw-r--r--drivers/pnp/pnpbios/Kconfig2
-rw-r--r--drivers/pnp/pnpbios/core.c1
-rw-r--r--drivers/ps3/Makefile5
-rw-r--r--drivers/ps3/ps3av.c372
-rw-r--r--drivers/ps3/ps3av_cmd.c51
-rw-r--r--drivers/ps3/ps3stor_lib.c302
-rw-r--r--drivers/ps3/sys-manager-core.c68
-rw-r--r--drivers/ps3/sys-manager.c290
-rw-r--r--drivers/ps3/vuart.c817
-rw-r--r--drivers/ps3/vuart.h71
-rw-r--r--drivers/rtc/Kconfig66
-rw-r--r--drivers/rtc/Makefile4
-rw-r--r--drivers/rtc/rtc-at32ap700x.c317
-rw-r--r--drivers/rtc/rtc-dev.c2
-rw-r--r--drivers/rtc/rtc-ds1216.c226
-rw-r--r--drivers/rtc/rtc-ds1307.c300
-rw-r--r--drivers/rtc/rtc-m41t80.c917
-rw-r--r--drivers/rtc/rtc-m48t59.c491
-rw-r--r--drivers/rtc/rtc-rs5c372.c95
-rw-r--r--drivers/s390/block/dcssblk.c7
-rw-r--r--drivers/s390/char/Kconfig7
-rw-r--r--drivers/s390/char/Makefile1
-rw-r--r--drivers/s390/char/vmcp.c89
-rw-r--r--drivers/s390/char/vmcp.h4
-rw-r--r--drivers/s390/char/vmur.c906
-rw-r--r--drivers/s390/char/vmur.h104
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/qdio.c16
-rw-r--r--drivers/s390/net/qeth.h9
-rw-r--r--drivers/s390/net/qeth_main.c183
-rw-r--r--drivers/s390/net/qeth_proc.c6
-rw-r--r--drivers/sbus/char/cpwatchdog.c1
-rw-r--r--drivers/sbus/char/jsflash.c3
-rw-r--r--drivers/scsi/Kconfig2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c3
-rw-r--r--drivers/scsi/scsi_error.c3
-rw-r--r--drivers/scsi/sd.c2
-rw-r--r--drivers/scsi/st.c3
-rw-r--r--drivers/serial/68360serial.c7
-rw-r--r--drivers/serial/8250.c28
-rw-r--r--drivers/serial/8250_early.c117
-rw-r--r--drivers/serial/Kconfig42
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/atmel_serial.c32
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c2
-rw-r--r--drivers/serial/ip22zilog.c3
-rw-r--r--drivers/serial/of_serial.c33
-rw-r--r--drivers/serial/sb1250-duart.c972
-rw-r--r--drivers/serial/serial_core.c6
-rw-r--r--drivers/serial/sh-sci.c4
-rw-r--r--drivers/serial/sh-sci.h50
-rw-r--r--drivers/serial/sn_console.c4
-rw-r--r--drivers/serial/sunhv.c42
-rw-r--r--drivers/serial/sunsab.c19
-rw-r--r--drivers/serial/sunsu.c14
-rw-r--r--drivers/serial/sunzilog.c17
-rw-r--r--drivers/spi/Kconfig45
-rw-r--r--drivers/spi/Makefile5
-rw-r--r--drivers/spi/atmel_spi.c185
-rw-r--r--drivers/spi/au1550_spi.c9
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c9
-rw-r--r--drivers/spi/omap2_mcspi.c1081
-rw-r--r--drivers/spi/omap_uwire.c9
-rw-r--r--drivers/spi/pxa2xx_spi.c9
-rw-r--r--drivers/spi/spi.c11
-rw-r--r--drivers/spi/spi_bitbang.c8
-rw-r--r--drivers/spi/spi_imx.c24
-rw-r--r--drivers/spi/spi_lm70llp.c361
-rw-r--r--drivers/spi/spi_mpc83xx.c47
-rw-r--r--drivers/spi/spi_s3c24xx.c8
-rw-r--r--drivers/spi/spi_txx9.c474
-rw-r--r--drivers/spi/spidev.c6
-rw-r--r--drivers/spi/tle62x0.c328
-rw-r--r--drivers/spi/xilinx_spi.c434
-rw-r--r--drivers/telephony/Kconfig13
-rw-r--r--drivers/telephony/ixj.c7
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/atm/ueagle-atm.c1
-rw-r--r--drivers/usb/core/hub.c1
-rw-r--r--drivers/usb/gadget/file_storage.c3
-rw-r--r--drivers/usb/misc/auerswald.c4
-rw-r--r--drivers/usb/storage/usb.c3
-rw-r--r--drivers/video/68328fb.c2
-rw-r--r--drivers/video/Kconfig10
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/aty/ati_ids.h1
-rw-r--r--drivers/video/aty/atyfb_base.c2
-rw-r--r--drivers/video/aty/radeon_base.c2
-rw-r--r--drivers/video/aty/radeonfb.h2
-rw-r--r--drivers/video/console/Kconfig16
-rw-r--r--drivers/video/console/fbcon.c366
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/cyblafb.c21
-rw-r--r--drivers/video/epson1355fb.c21
-rw-r--r--drivers/video/fbmem.c299
-rw-r--r--drivers/video/fm2fb.c16
-rw-r--r--drivers/video/gbefb.c41
-rw-r--r--drivers/video/i810/i810.h2
-rw-r--r--drivers/video/intelfb/intelfb.h2
-rw-r--r--drivers/video/logo/Kconfig5
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/logo/logo_spe_clut224.ppm283
-rw-r--r--drivers/video/macfb.c93
-rw-r--r--drivers/video/macmodes.c5
-rw-r--r--drivers/video/macmodes.h8
-rw-r--r--drivers/video/matrox/matroxfb_accel.c11
-rw-r--r--drivers/video/matrox/matroxfb_base.c4
-rw-r--r--drivers/video/matrox/matroxfb_base.h2
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c6
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.h2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c9
-rw-r--r--drivers/video/nvidia/nv_hw.c62
-rw-r--r--drivers/video/nvidia/nv_setup.c12
-rw-r--r--drivers/video/nvidia/nv_type.h1
-rw-r--r--drivers/video/nvidia/nvidia.c9
-rw-r--r--drivers/video/offb.c2
-rw-r--r--drivers/video/omap/Kconfig58
-rw-r--r--drivers/video/omap/Makefile29
-rw-r--r--drivers/video/omap/blizzard.c1568
-rw-r--r--drivers/video/omap/dispc.c1502
-rw-r--r--drivers/video/omap/dispc.h43
-rw-r--r--drivers/video/omap/hwa742.c1077
-rw-r--r--drivers/video/omap/lcd_h3.c141
-rw-r--r--drivers/video/omap/lcd_h4.c117
-rw-r--r--drivers/video/omap/lcd_inn1510.c124
-rw-r--r--drivers/video/omap/lcd_inn1610.c150
-rw-r--r--drivers/video/omap/lcd_osk.c144
-rw-r--r--drivers/video/omap/lcd_palmte.c123
-rw-r--r--drivers/video/omap/lcd_palmtt.c127
-rw-r--r--drivers/video/omap/lcd_palmz71.c123
-rw-r--r--drivers/video/omap/lcd_sx1.c334
-rw-r--r--drivers/video/omap/lcdc.c893
-rw-r--r--drivers/video/omap/lcdc.h7
-rw-r--r--drivers/video/omap/omapfb_main.c1941
-rw-r--r--drivers/video/omap/rfbi.c588
-rw-r--r--drivers/video/omap/sossi.c686
-rw-r--r--drivers/video/platinumfb.c2
-rw-r--r--drivers/video/pm2fb.c202
-rw-r--r--drivers/video/pm3fb.c270
-rw-r--r--drivers/video/ps3fb.c291
-rw-r--r--drivers/video/pvr2fb.c108
-rw-r--r--drivers/video/q40fb.c2
-rw-r--r--drivers/video/riva/riva_hw.c7
-rw-r--r--drivers/video/sgivwfb.c2
-rw-r--r--drivers/video/sis/sis.h2
-rw-r--r--drivers/video/sis/sis_main.c6
-rw-r--r--drivers/video/tgafb.c2
-rw-r--r--drivers/video/tridentfb.c30
-rw-r--r--drivers/video/tx3912fb.c2
-rw-r--r--drivers/video/vt8623fb.c42
-rw-r--r--drivers/w1/Kconfig12
-rw-r--r--drivers/w1/masters/Kconfig7
-rw-r--r--drivers/w1/slaves/Kconfig4
-rw-r--r--drivers/w1/w1.c1
-rw-r--r--fs/9p/v9fs.c2
-rw-r--r--fs/Kconfig3
-rw-r--r--fs/afs/Makefile1
-rw-r--r--fs/afs/afs.h8
-rw-r--r--fs/afs/afs_fs.h3
-rw-r--r--fs/afs/callback.c3
-rw-r--r--fs/afs/dir.c1
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/afs/flock.c558
-rw-r--r--fs/afs/fsclient.c155
-rw-r--r--fs/afs/internal.h30
-rw-r--r--fs/afs/main.c1
-rw-r--r--fs/afs/misc.c1
-rw-r--r--fs/afs/proc.c81
-rw-r--r--fs/afs/super.c3
-rw-r--r--fs/afs/vnode.c132
-rw-r--r--fs/anon_inodes.c10
-rw-r--r--fs/attr.c4
-rw-r--r--fs/binfmt_elf.c109
-rw-r--r--fs/block_dev.c63
-rw-r--r--fs/buffer.c63
-rw-r--r--fs/cifs/cifsfs.c1
-rw-r--r--fs/cifs/connect.c1
-rw-r--r--fs/cifs/export.c1
-rw-r--r--fs/compat_ioctl.c4
-rw-r--r--fs/configfs/configfs_internal.h7
-rw-r--r--fs/configfs/dir.c289
-rw-r--r--fs/configfs/file.c28
-rw-r--r--fs/configfs/item.c29
-rw-r--r--fs/dcache.c7
-rw-r--r--fs/dlm/config.c20
-rw-r--r--fs/dquot.c7
-rw-r--r--fs/drop_caches.c2
-rw-r--r--fs/ecryptfs/inode.c4
-rw-r--r--fs/efs/namei.c32
-rw-r--r--fs/efs/super.c2
-rw-r--r--fs/exportfs/expfs.c439
-rw-r--r--fs/ext2/acl.c2
-rw-r--r--fs/ext2/file.c6
-rw-r--r--fs/ext2/ioctl.c4
-rw-r--r--fs/ext2/super.c21
-rw-r--r--fs/ext3/acl.c2
-rw-r--r--fs/ext3/inode.c2
-rw-r--r--fs/ext3/ioctl.c6
-rw-r--r--fs/ext3/namei.c10
-rw-r--r--fs/ext3/super.c52
-rw-r--r--fs/ext4/acl.c2
-rw-r--r--fs/ext4/balloc.c2
-rw-r--r--fs/ext4/ioctl.c6
-rw-r--r--fs/ext4/namei.c10
-rw-r--r--fs/ext4/super.c49
-rw-r--r--fs/fat/dir.c31
-rw-r--r--fs/fat/fatent.c7
-rw-r--r--fs/fat/inode.c4
-rw-r--r--fs/fcntl.c2
-rw-r--r--fs/freevxfs/vxfs_dir.h2
-rw-r--r--fs/generic_acl.c2
-rw-r--r--fs/gfs2/acl.c2
-rw-r--r--fs/gfs2/eaops.c1
-rw-r--r--fs/gfs2/ops_export.c1
-rw-r--r--fs/hfsplus/btree.c4
-rw-r--r--fs/hfsplus/dir.c2
-rw-r--r--fs/hfsplus/hfsplus_fs.h4
-rw-r--r--fs/hfsplus/inode.c5
-rw-r--r--fs/hfsplus/ioctl.c2
-rw-r--r--fs/hfsplus/super.c4
-rw-r--r--fs/hfsplus/unicode.c230
-rw-r--r--fs/hugetlbfs/inode.c96
-rw-r--r--fs/inode.c17
-rw-r--r--fs/ioctl.c22
-rw-r--r--fs/isofs/dir.c87
-rw-r--r--fs/isofs/inode.c417
-rw-r--r--fs/isofs/isofs.h1
-rw-r--r--fs/isofs/joliet.c10
-rw-r--r--fs/isofs/namei.c26
-rw-r--r--fs/jbd/commit.c3
-rw-r--r--fs/jbd/revoke.c5
-rw-r--r--fs/jbd2/commit.c3
-rw-r--r--fs/jbd2/revoke.c5
-rw-r--r--fs/jffs2/acl.c2
-rw-r--r--fs/jffs2/background.c1
-rw-r--r--fs/jfs/ioctl.c2
-rw-r--r--fs/jfs/jfs_inode.h1
-rw-r--r--fs/jfs/namei.c32
-rw-r--r--fs/jfs/super.c2
-rw-r--r--fs/jfs/xattr.c2
-rw-r--r--fs/lockd/svc.c29
-rw-r--r--fs/mbcache.c9
-rw-r--r--fs/namei.c2
-rw-r--r--fs/namespace.c23
-rw-r--r--fs/ncpfs/file.c2
-rw-r--r--fs/nfs/callback.c2
-rw-r--r--fs/nfs/client.c54
-rw-r--r--fs/nfs/super.c10
-rw-r--r--fs/nfsd/auth.c18
-rw-r--r--fs/nfsd/export.c289
-rw-r--r--fs/nfsd/lockd.c1
-rw-r--r--fs/nfsd/nfs4acl.c12
-rw-r--r--fs/nfsd/nfs4callback.c2
-rw-r--r--fs/nfsd/nfs4idmap.c13
-rw-r--r--fs/nfsd/nfs4proc.c35
-rw-r--r--fs/nfsd/nfs4state.c46
-rw-r--r--fs/nfsd/nfs4xdr.c101
-rw-r--r--fs/nfsd/nfsctl.c3
-rw-r--r--fs/nfsd/nfsfh.c51
-rw-r--r--fs/nfsd/nfsproc.c3
-rw-r--r--fs/nfsd/nfssvc.c12
-rw-r--r--fs/nfsd/vfs.c110
-rw-r--r--fs/nls/Makefile2
-rw-r--r--fs/ntfs/namei.c1
-rw-r--r--fs/ocfs2/alloc.c2676
-rw-r--r--fs/ocfs2/alloc.h43
-rw-r--r--fs/ocfs2/aops.c1015
-rw-r--r--fs/ocfs2/aops.h61
-rw-r--r--fs/ocfs2/cluster/heartbeat.c96
-rw-r--r--fs/ocfs2/cluster/heartbeat.h6
-rw-r--r--fs/ocfs2/cluster/nodemanager.c42
-rw-r--r--fs/ocfs2/cluster/nodemanager.h5
-rw-r--r--fs/ocfs2/cluster/tcp.c21
-rw-r--r--fs/ocfs2/dir.c2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c8
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c40
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c79
-rw-r--r--fs/ocfs2/dlmglue.c6
-rw-r--r--fs/ocfs2/endian.h5
-rw-r--r--fs/ocfs2/export.h2
-rw-r--r--fs/ocfs2/extent_map.c41
-rw-r--r--fs/ocfs2/file.c703
-rw-r--r--fs/ocfs2/file.h10
-rw-r--r--fs/ocfs2/heartbeat.c10
-rw-r--r--fs/ocfs2/ioctl.c17
-rw-r--r--fs/ocfs2/journal.c6
-rw-r--r--fs/ocfs2/journal.h2
-rw-r--r--fs/ocfs2/mmap.c167
-rw-r--r--fs/ocfs2/namei.c2
-rw-r--r--fs/ocfs2/ocfs2.h14
-rw-r--r--fs/ocfs2/ocfs2_fs.h33
-rw-r--r--fs/ocfs2/slot_map.c12
-rw-r--r--fs/ocfs2/suballoc.c46
-rw-r--r--fs/ocfs2/suballoc.h17
-rw-r--r--fs/ocfs2/super.c27
-rw-r--r--fs/ocfs2/super.h2
-rw-r--r--fs/open.c14
-rw-r--r--fs/partitions/acorn.c9
-rw-r--r--fs/partitions/ldm.c137
-rw-r--r--fs/partitions/ldm.h2
-rw-r--r--fs/proc/array.c68
-rw-r--r--fs/proc/base.c85
-rw-r--r--fs/proc/generic.c52
-rw-r--r--fs/proc/inode.c254
-rw-r--r--fs/proc/proc_misc.c7
-rw-r--r--fs/proc/proc_tty.c15
-rw-r--r--fs/quota.c118
-rw-r--r--fs/ramfs/inode.c1
-rw-r--r--fs/reiserfs/file.c1
-rw-r--r--fs/reiserfs/inode.c1
-rw-r--r--fs/reiserfs/ioctl.c5
-rw-r--r--fs/reiserfs/super.c1
-rw-r--r--fs/reiserfs/xattr_acl.c2
-rw-r--r--fs/seq_file.c18
-rw-r--r--fs/splice.c4
-rw-r--r--fs/super.c1
-rw-r--r--fs/udf/crc.c4
-rw-r--r--fs/udf/ialloc.c9
-rw-r--r--fs/udf/inode.c51
-rw-r--r--fs/udf/super.c2
-rw-r--r--fs/ufs/super.c5
-rw-r--r--fs/utimes.c2
-rw-r--r--fs/xattr.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c14
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h2
-rw-r--r--fs/xfs/quota/xfs_qm.c10
-rw-r--r--include/asm-alpha/fb.h13
-rw-r--r--include/asm-alpha/io.h13
-rw-r--r--include/asm-alpha/page.h3
-rw-r--r--include/asm-alpha/pgtable.h6
-rw-r--r--include/asm-alpha/termios.h4
-rw-r--r--include/asm-arm/arch-at91/board.h1
-rw-r--r--include/asm-arm/fb.h19
-rw-r--r--include/asm-arm/pgtable.h12
-rw-r--r--include/asm-arm26/dma-mapping.h2
-rw-r--r--include/asm-arm26/fb.h12
-rw-r--r--include/asm-arm26/ioctls.h4
-rw-r--r--include/asm-arm26/pgtable.h4
-rw-r--r--include/asm-arm26/termbits.h5
-rw-r--r--include/asm-arm26/termios.h6
-rw-r--r--include/asm-avr32/arch-at32ap/board.h1
-rw-r--r--include/asm-avr32/fb.h21
-rw-r--r--include/asm-avr32/pgtable.h28
-rw-r--r--include/asm-blackfin/fb.h12
-rw-r--r--include/asm-cris/fb.h12
-rw-r--r--include/asm-cris/ioctls.h4
-rw-r--r--include/asm-cris/page.h3
-rw-r--r--include/asm-cris/pgtable.h30
-rw-r--r--include/asm-cris/termbits.h1
-rw-r--r--include/asm-cris/termios.h6
-rw-r--r--include/asm-frv/fb.h12
-rw-r--r--include/asm-frv/pgtable.h14
-rw-r--r--include/asm-frv/unistd.h6
-rw-r--r--include/asm-generic/bug.h2
-rw-r--r--include/asm-generic/dma-mapping-broken.h82
-rw-r--r--include/asm-generic/fcntl.h3
-rw-r--r--include/asm-generic/pgtable.h44
-rw-r--r--include/asm-generic/unaligned.h16
-rw-r--r--include/asm-h8300/dma-mapping.h1
-rw-r--r--include/asm-h8300/fb.h12
-rw-r--r--include/asm-h8300/ioctls.h4
-rw-r--r--include/asm-h8300/page.h3
-rw-r--r--include/asm-h8300/termbits.h5
-rw-r--r--include/asm-h8300/termios.h6
-rw-r--r--include/asm-h8300/thread_info.h2
-rw-r--r--include/asm-i386/fb.h17
-rw-r--r--include/asm-i386/fixmap.h2
-rw-r--r--include/asm-i386/ide.h4
-rw-r--r--include/asm-i386/io.h1
-rw-r--r--include/asm-i386/page.h3
-rw-r--r--include/asm-i386/pgtable-2level.h8
-rw-r--r--include/asm-i386/pgtable-3level.h17
-rw-r--r--include/asm-i386/pgtable.h40
-rw-r--r--include/asm-i386/processor.h4
-rw-r--r--include/asm-i386/thread_info.h5
-rw-r--r--include/asm-ia64/compat.h2
-rw-r--r--include/asm-ia64/fb.h23
-rw-r--r--include/asm-ia64/ioctls.h4
-rw-r--r--include/asm-ia64/page.h13
-rw-r--r--include/asm-ia64/pgtable.h26
-rw-r--r--include/asm-ia64/termbits.h5
-rw-r--r--include/asm-ia64/termios.h6
-rw-r--r--include/asm-m32r/dma-mapping.h6
-rw-r--r--include/asm-m32r/fb.h19
-rw-r--r--include/asm-m32r/ioctls.h4
-rw-r--r--include/asm-m32r/page.h3
-rw-r--r--include/asm-m32r/pgtable.h40
-rw-r--r--include/asm-m32r/termbits.h5
-rw-r--r--include/asm-m32r/termios.h6
-rw-r--r--include/asm-m68k/atari_SLM.h28
-rw-r--r--include/asm-m68k/atari_acsi.h37
-rw-r--r--include/asm-m68k/fb.h34
-rw-r--r--include/asm-m68k/motorola_pgtable.h6
-rw-r--r--include/asm-m68k/sun3_pgtable.h6
-rw-r--r--include/asm-m68knommu/fb.h12
-rw-r--r--include/asm-m68knommu/page.h3
-rw-r--r--include/asm-mips/compat.h2
-rw-r--r--include/asm-mips/fb.h19
-rw-r--r--include/asm-mips/pgtable.h34
-rw-r--r--include/asm-mips/sibyte/bcm1480_regs.h30
-rw-r--r--include/asm-mips/sibyte/sb1250_regs.h76
-rw-r--r--include/asm-mips/sibyte/sb1250_uart.h7
-rw-r--r--include/asm-parisc/compat.h2
-rw-r--r--include/asm-parisc/fb.h19
-rw-r--r--include/asm-parisc/fcntl.h29
-rw-r--r--include/asm-parisc/pgtable.h20
-rw-r--r--include/asm-powerpc/cache.h4
-rw-r--r--include/asm-powerpc/compat.h2
-rw-r--r--include/asm-powerpc/cputable.h111
-rw-r--r--include/asm-powerpc/fb.h21
-rw-r--r--include/asm-powerpc/floppy.h6
-rw-r--r--include/asm-powerpc/hvcall.h1
-rw-r--r--include/asm-powerpc/io.h26
-rw-r--r--include/asm-powerpc/irq.h9
-rw-r--r--include/asm-powerpc/kprobes.h4
-rw-r--r--include/asm-powerpc/lppaca.h2
-rw-r--r--include/asm-powerpc/lv1call.h3
-rw-r--r--include/asm-powerpc/machdep.h2
-rw-r--r--include/asm-powerpc/mmu-8xx.h147
-rw-r--r--include/asm-powerpc/mmu-fsl-booke.h88
-rw-r--r--include/asm-powerpc/mmu-hash32.h91
-rw-r--r--include/asm-powerpc/mmu-hash64.h9
-rw-r--r--include/asm-powerpc/mmu.h13
-rw-r--r--include/asm-powerpc/mmu_context.h202
-rw-r--r--include/asm-powerpc/mpc86xx.h6
-rw-r--r--include/asm-powerpc/mpc8xx.h4
-rw-r--r--include/asm-powerpc/pci-bridge.h148
-rw-r--r--include/asm-powerpc/pci.h11
-rw-r--r--include/asm-powerpc/pgtable-ppc32.h67
-rw-r--r--include/asm-powerpc/pgtable-ppc64.h91
-rw-r--r--include/asm-powerpc/pgtable.h28
-rw-r--r--include/asm-powerpc/ppc-pci.h9
-rw-r--r--include/asm-powerpc/processor.h8
-rw-r--r--include/asm-powerpc/prom.h18
-rw-r--r--include/asm-powerpc/ps3.h182
-rw-r--r--include/asm-powerpc/ps3av.h48
-rw-r--r--include/asm-powerpc/ps3fb.h12
-rw-r--r--include/asm-powerpc/ps3stor.h71
-rw-r--r--include/asm-powerpc/ptrace.h22
-rw-r--r--include/asm-powerpc/reg.h2
-rw-r--r--include/asm-powerpc/spu.h24
-rw-r--r--include/asm-powerpc/syscalls.h7
-rw-r--r--include/asm-powerpc/system.h4
-rw-r--r--include/asm-powerpc/termbits.h4
-rw-r--r--include/asm-powerpc/thread_info.h12
-rw-r--r--include/asm-powerpc/time.h4
-rw-r--r--include/asm-powerpc/tlbflush.h5
-rw-r--r--include/asm-ppc/pgtable.h17
-rw-r--r--include/asm-s390/compat.h2
-rw-r--r--include/asm-s390/dma-mapping.h12
-rw-r--r--include/asm-s390/fb.h12
-rw-r--r--include/asm-s390/page.h3
-rw-r--r--include/asm-s390/pgtable.h66
-rw-r--r--include/asm-sh/bugs.h4
-rw-r--r--include/asm-sh/cache.h4
-rw-r--r--include/asm-sh/cpu-sh2/cache.h20
-rw-r--r--include/asm-sh/cpu-sh3/timer.h4
-rw-r--r--include/asm-sh/cpu-sh4/freq.h2
-rw-r--r--include/asm-sh/cpu-sh4/timer.h57
-rw-r--r--include/asm-sh/fb.h19
-rw-r--r--include/asm-sh/futex-irq.h111
-rw-r--r--include/asm-sh/futex.h79
-rw-r--r--include/asm-sh/hd64461.h397
-rw-r--r--include/asm-sh/hw_irq.h42
-rw-r--r--include/asm-sh/irq.h40
-rw-r--r--include/asm-sh/machvec.h4
-rw-r--r--include/asm-sh/machvec_init.h53
-rw-r--r--include/asm-sh/mmzone.h46
-rw-r--r--include/asm-sh/page.h10
-rw-r--r--include/asm-sh/parport.h16
-rw-r--r--include/asm-sh/pgtable.h12
-rw-r--r--include/asm-sh/processor.h8
-rw-r--r--include/asm-sh/rwsem.h6
-rw-r--r--include/asm-sh/saturn/io.h19
-rw-r--r--include/asm-sh/saturn/smpc.h34
-rw-r--r--include/asm-sh/sections.h2
-rw-r--r--include/asm-sh/setup.h1
-rw-r--r--include/asm-sh/sh03/io.h4
-rw-r--r--include/asm-sh/smp.h2
-rw-r--r--include/asm-sh/snapgear.h4
-rw-r--r--include/asm-sh/sparsemem.h16
-rw-r--r--include/asm-sh/system.h16
-rw-r--r--include/asm-sh/topology.h30
-rw-r--r--include/asm-sh/uaccess.h40
-rw-r--r--include/asm-sh/ubc.h9
-rw-r--r--include/asm-sh64/fb.h19
-rw-r--r--include/asm-sh64/pgtable.h7
-rw-r--r--include/asm-sparc/fb.h12
-rw-r--r--include/asm-sparc/pgtable.h2
-rw-r--r--include/asm-sparc64/bugs.h5
-rw-r--r--include/asm-sparc64/compat.h2
-rw-r--r--include/asm-sparc64/cpudata.h5
-rw-r--r--include/asm-sparc64/delay.h32
-rw-r--r--include/asm-sparc64/fb.h18
-rw-r--r--include/asm-sparc64/hvtramp.h37
-rw-r--r--include/asm-sparc64/hypervisor.h2
-rw-r--r--include/asm-sparc64/irq.h2
-rw-r--r--include/asm-sparc64/ldc.h138
-rw-r--r--include/asm-sparc64/mdesc.h88
-rw-r--r--include/asm-sparc64/mmu_context.h3
-rw-r--r--include/asm-sparc64/pgtable.h18
-rw-r--r--include/asm-sparc64/power.h7
-rw-r--r--include/asm-sparc64/smp.h11
-rw-r--r--include/asm-sparc64/vio.h404
-rw-r--r--include/asm-um/pgtable.h18
-rw-r--r--include/asm-um/thread_info.h15
-rw-r--r--include/asm-v850/fb.h12
-rw-r--r--include/asm-v850/ioctls.h4
-rw-r--r--include/asm-v850/termbits.h5
-rw-r--r--include/asm-v850/termios.h6
-rw-r--r--include/asm-x86_64/compat.h2
-rw-r--r--include/asm-x86_64/fb.h19
-rw-r--r--include/asm-x86_64/fixmap.h4
-rw-r--r--include/asm-x86_64/io.h1
-rw-r--r--include/asm-x86_64/page.h3
-rw-r--r--include/asm-x86_64/pgtable.h14
-rw-r--r--include/asm-xtensa/fb.h12
-rw-r--r--include/asm-xtensa/pgtable.h15
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/attribute_container.h1
-rw-r--r--include/linux/audit.h11
-rw-r--r--include/linux/backing-dev.h1
-rw-r--r--include/linux/blkdev.h28
-rw-r--r--include/linux/bsg.h69
-rw-r--r--include/linux/bug.h7
-rw-r--r--include/linux/capability.h1
-rw-r--r--include/linux/cdrom.h4
-rw-r--r--include/linux/cobalt-nvram.h109
-rw-r--r--include/linux/configfs.h34
-rw-r--r--include/linux/console.h3
-rw-r--r--include/linux/consolemap.h5
-rw-r--r--include/linux/cpu.h1
-rw-r--r--include/linux/crc7.h14
-rw-r--r--include/linux/dma-mapping.h4
-rw-r--r--include/linux/ds17287rtc.h1
-rw-r--r--include/linux/efs_fs.h1
-rw-r--r--include/linux/exportfs.h126
-rw-r--r--include/linux/ext2_fs_sb.h2
-rw-r--r--include/linux/ext3_fs_sb.h2
-rw-r--r--include/linux/ext4_fs_sb.h2
-rw-r--r--include/linux/fb.h3
-rw-r--r--include/linux/file.h1
-rw-r--r--include/linux/freezer.h14
-rw-r--r--include/linux/fs.h134
-rw-r--r--include/linux/fsl_devices.h7
-rw-r--r--include/linux/fuse.h2
-rw-r--r--include/linux/gfp.h19
-rw-r--r--include/linux/highmem.h51
-rw-r--r--include/linux/hrtimer.h5
-rw-r--r--include/linux/hugetlb.h2
-rw-r--r--include/linux/i2o.h5
-rw-r--r--include/linux/idr.h3
-rw-r--r--include/linux/init.h4
-rw-r--r--include/linux/init_task.h2
-rw-r--r--include/linux/io.h29
-rw-r--r--include/linux/ipc.h12
-rw-r--r--include/linux/irq.h1
-rw-r--r--include/linux/kallsyms.h6
-rw-r--r--include/linux/kernel.h1
-rw-r--r--include/linux/kernelcapi.h2
-rw-r--r--include/linux/leds.h1
-rw-r--r--include/linux/limits.h2
-rw-r--r--include/linux/linux_logo.h8
-rw-r--r--include/linux/lockd/bind.h9
-rw-r--r--include/linux/lzo.h2
-rw-r--r--include/linux/mempolicy.h6
-rw-r--r--include/linux/mm.h45
-rw-r--r--include/linux/mmzone.h33
-rw-r--r--include/linux/mnt_namespace.h2
-rw-r--r--include/linux/module.h1
-rw-r--r--include/linux/msdos_fs.h2
-rw-r--r--include/linux/ncp_fs.h2
-rw-r--r--include/linux/netdevice.h10
-rw-r--r--include/linux/nfsd/export.h41
-rw-r--r--include/linux/nfsd/interface.h13
-rw-r--r--include/linux/nfsd/nfsd.h9
-rw-r--r--include/linux/nfsd/state.h3
-rw-r--r--include/linux/nfsd/xdr4.h7
-rw-r--r--include/linux/nsproxy.h3
-rw-r--r--include/linux/pci.h3
-rw-r--r--include/linux/percpu.h2
-rw-r--r--include/linux/percpu_counter.h18
-rw-r--r--include/linux/pid_namespace.h2
-rw-r--r--include/linux/prctl.h4
-rw-r--r--include/linux/prefetch.h2
-rw-r--r--include/linux/proc_fs.h13
-rw-r--r--include/linux/ptrace.h2
-rw-r--r--include/linux/raid/bitmap.h6
-rw-r--r--include/linux/raid/md_k.h2
-rw-r--r--include/linux/rtc/m48t59.h57
-rw-r--r--include/linux/sched.h11
-rw-r--r--include/linux/scx200_gpio.h2
-rw-r--r--include/linux/seccomp.h19
-rw-r--r--include/linux/serial.h6
-rw-r--r--include/linux/serial_8250.h4
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/signal.h1
-rw-r--r--include/linux/slab.h150
-rw-r--r--include/linux/slab_def.h38
-rw-r--r--include/linux/slob_def.h36
-rw-r--r--include/linux/slub_def.h33
-rw-r--r--include/linux/smp.h29
-rw-r--r--include/linux/smp_lock.h1
-rw-r--r--include/linux/socket.h3
-rw-r--r--include/linux/sonypi.h2
-rw-r--r--include/linux/spi/spi.h1
-rw-r--r--include/linux/spi/spi_bitbang.h1
-rw-r--r--include/linux/spi/tle62x0.h24
-rw-r--r--include/linux/spinlock.h7
-rw-r--r--include/linux/sunrpc/gss_api.h1
-rw-r--r--include/linux/sunrpc/svc.h2
-rw-r--r--include/linux/sunrpc/svcauth.h1
-rw-r--r--include/linux/sunrpc/svcauth_gss.h1
-rw-r--r--include/linux/swap.h3
-rw-r--r--include/linux/taskstats.h5
-rw-r--r--include/linux/time.h5
-rw-r--r--include/linux/timer.h16
-rw-r--r--include/linux/tty.h39
-rw-r--r--include/linux/uio.h9
-rw-r--r--include/linux/user_namespace.h61
-rw-r--r--include/linux/utsname.h16
-rw-r--r--include/linux/vmalloc.h3
-rw-r--r--include/linux/vmstat.h5
-rw-r--r--include/linux/vt_kern.h2
-rw-r--r--include/linux/workqueue.h15
-rw-r--r--include/net/scm.h2
-rw-r--r--include/video/tgafb.h1
-rw-r--r--init/Kconfig29
-rw-r--r--init/do_mounts.c24
-rw-r--r--init/do_mounts_initrd.c7
-rw-r--r--init/main.c59
-rw-r--r--ipc/msg.c8
-rw-r--r--ipc/sem.c6
-rw-r--r--ipc/shm.c4
-rw-r--r--ipc/util.c11
-rw-r--r--ipc/util.h8
-rw-r--r--kernel/Makefile6
-rw-r--r--kernel/audit.c97
-rw-r--r--kernel/audit.h1
-rw-r--r--kernel/auditfilter.c12
-rw-r--r--kernel/auditsc.c5
-rw-r--r--kernel/cpuset.c6
-rw-r--r--kernel/exit.c37
-rw-r--r--kernel/fork.c11
-rw-r--r--kernel/futex.c138
-rw-r--r--kernel/hrtimer.c2
-rw-r--r--kernel/irq/spurious.c12
-rw-r--r--kernel/kallsyms.c27
-rw-r--r--kernel/kfifo.c3
-rw-r--r--kernel/kthread.c2
-rw-r--r--kernel/lockdep.c4
-rw-r--r--kernel/module.c63
-rw-r--r--kernel/nsproxy.c72
-rw-r--r--kernel/panic.c5
-rw-r--r--kernel/pid.c2
-rw-r--r--kernel/printk.c55
-rw-r--r--kernel/ptrace.c26
-rw-r--r--kernel/rcutorture.c4
-rw-r--r--kernel/rtmutex-debug.c6
-rw-r--r--kernel/rtmutex-tester.c1
-rw-r--r--kernel/rtmutex.c6
-rw-r--r--kernel/rtmutex_common.h9
-rw-r--r--kernel/sched.c30
-rw-r--r--kernel/seccomp.c29
-rw-r--r--kernel/signal.c33
-rw-r--r--kernel/softirq.c33
-rw-r--r--kernel/softlockup.c2
-rw-r--r--kernel/stop_machine.c8
-rw-r--r--kernel/sys.c13
-rw-r--r--kernel/sys_ni.c1
-rw-r--r--kernel/sysctl.c45
-rw-r--r--kernel/taskstats.c4
-rw-r--r--kernel/time.c32
-rw-r--r--kernel/time/clockevents.c41
-rw-r--r--kernel/time/ntp.c2
-rw-r--r--kernel/time/timekeeping.c37
-rw-r--r--kernel/time/timer_list.c2
-rw-r--r--kernel/time/timer_stats.c16
-rw-r--r--kernel/timer.c19
-rw-r--r--kernel/user.c18
-rw-r--r--kernel/user_namespace.c87
-rw-r--r--kernel/utsname.c12
-rw-r--r--kernel/utsname_sysctl.c5
-rw-r--r--kernel/workqueue.c60
-rw-r--r--lib/Kconfig8
-rw-r--r--lib/Kconfig.debug13
-rw-r--r--lib/Makefile3
-rw-r--r--lib/bug.c5
-rw-r--r--lib/check_signature.c26
-rw-r--r--lib/crc7.c68
-rw-r--r--lib/genalloc.c3
-rw-r--r--lib/idr.c102
-rw-r--r--lib/percpu_counter.c68
-rw-r--r--lib/vsprintf.c173
-rw-r--r--mm/Kconfig10
-rw-r--r--mm/Makefile4
-rw-r--r--mm/allocpercpu.c9
-rw-r--r--mm/backing-dev.c16
-rw-r--r--mm/filemap.c77
-rw-r--r--mm/highmem.c7
-rw-r--r--mm/hugetlb.c40
-rw-r--r--mm/madvise.c6
-rw-r--r--mm/memory.c21
-rw-r--r--mm/mempolicy.c61
-rw-r--r--mm/mempool.c6
-rw-r--r--mm/migrate.c3
-rw-r--r--mm/mlock.c5
-rw-r--r--mm/mmap.c25
-rw-r--r--mm/nommu.c5
-rw-r--r--mm/page-writeback.c11
-rw-r--r--mm/page_alloc.c622
-rw-r--r--mm/pdflush.c1
-rw-r--r--mm/shmem.c8
-rw-r--r--mm/slab.c118
-rw-r--r--mm/slob.c586
-rw-r--r--mm/slub.c747
-rw-r--r--mm/swap_state.c5
-rw-r--r--mm/swapfile.c2
-rw-r--r--mm/truncate.c44
-rw-r--r--mm/util.c48
-rw-r--r--mm/vmalloc.c19
-rw-r--r--mm/vmscan.c212
-rw-r--r--mm/vmstat.c2
-rw-r--r--net/bluetooth/bnep/core.c2
-rw-r--r--net/bluetooth/cmtp/core.c2
-rw-r--r--net/bluetooth/hidp/core.c2
-rw-r--r--net/bluetooth/rfcomm/core.c2
-rw-r--r--net/compat.c3
-rw-r--r--net/core/netpoll.c8
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/core/scm.c3
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c5
-rw-r--r--net/netlabel/netlabel_user.c4
-rw-r--r--net/socket.c4
-rw-r--r--net/sunrpc/auth.c11
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c1
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c14
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c1
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c32
-rw-r--r--net/sunrpc/svcauth_unix.c7
-rwxr-xr-xscripts/checkpatch.pl374
-rw-r--r--scripts/decodecode51
-rw-r--r--scripts/kallsyms.c4
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--security/selinux/nlmsgtab.c2
-rw-r--r--sound/oss/Kconfig80
-rw-r--r--sound/oss/Makefile13
-rw-r--r--sound/oss/ac97.c432
-rw-r--r--sound/oss/ac97.h201
-rw-r--r--sound/oss/aci.c712
-rw-r--r--sound/oss/aci.h57
-rw-r--r--sound/oss/ad1816.c1368
-rw-r--r--sound/oss/ad1889.c1101
-rw-r--r--sound/oss/ad1889.h135
-rw-r--r--sound/oss/adlib_card.c73
-rw-r--r--sound/oss/cs461x.h1691
-rw-r--r--sound/oss/cs461x_image.h322
-rw-r--r--sound/oss/cs46xx.c5444
-rw-r--r--sound/oss/cs46xx_wrapper-24.h56
-rw-r--r--sound/oss/cs46xxpm.h70
-rw-r--r--sound/oss/emu10k1/8010.h737
-rw-r--r--sound/oss/emu10k1/Makefile17
-rw-r--r--sound/oss/emu10k1/audio.c1595
-rw-r--r--sound/oss/emu10k1/audio.h44
-rw-r--r--sound/oss/emu10k1/cardmi.c832
-rw-r--r--sound/oss/emu10k1/cardmi.h97
-rw-r--r--sound/oss/emu10k1/cardmo.c229
-rw-r--r--sound/oss/emu10k1/cardmo.h62
-rw-r--r--sound/oss/emu10k1/cardwi.c384
-rw-r--r--sound/oss/emu10k1/cardwi.h91
-rw-r--r--sound/oss/emu10k1/cardwo.c643
-rw-r--r--sound/oss/emu10k1/cardwo.h90
-rw-r--r--sound/oss/emu10k1/ecard.c157
-rw-r--r--sound/oss/emu10k1/ecard.h113
-rw-r--r--sound/oss/emu10k1/efxmgr.c220
-rw-r--r--sound/oss/emu10k1/efxmgr.h270
-rw-r--r--sound/oss/emu10k1/emuadxmg.c104
-rw-r--r--sound/oss/emu10k1/hwaccess.c507
-rw-r--r--sound/oss/emu10k1/hwaccess.h247
-rw-r--r--sound/oss/emu10k1/icardmid.h163
-rw-r--r--sound/oss/emu10k1/icardwav.h53
-rw-r--r--sound/oss/emu10k1/irqmgr.c113
-rw-r--r--sound/oss/emu10k1/irqmgr.h52
-rw-r--r--sound/oss/emu10k1/main.c1471
-rw-r--r--sound/oss/emu10k1/midi.c614
-rw-r--r--sound/oss/emu10k1/midi.h78
-rw-r--r--sound/oss/emu10k1/mixer.c690
-rw-r--r--sound/oss/emu10k1/passthrough.c240
-rw-r--r--sound/oss/emu10k1/passthrough.h99
-rw-r--r--sound/oss/emu10k1/recmgr.c147
-rw-r--r--sound/oss/emu10k1/recmgr.h48
-rw-r--r--sound/oss/emu10k1/timer.c176
-rw-r--r--sound/oss/emu10k1/timer.h54
-rw-r--r--sound/oss/emu10k1/voicemgr.c398
-rw-r--r--sound/oss/emu10k1/voicemgr.h103
-rw-r--r--sound/oss/mpu401.c7
-rw-r--r--sound/oss/nm256.h292
-rw-r--r--sound/oss/nm256_audio.c1662
-rw-r--r--sound/oss/nm256_coeff.h4697
-rw-r--r--sound/oss/opl3.c14
-rw-r--r--sound/oss/opl3.h5
-rw-r--r--sound/oss/opl3sa2.c1020
-rw-r--r--sound/oss/trident.c367
-rw-r--r--sound/pci/mixart/mixart_hwdep.c1
-rw-r--r--usr/.gitignore1
1659 files changed, 70174 insertions, 62442 deletions
diff --git a/.gitignore b/.gitignore
index 060a71d41ad7..8d15830b883d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,6 @@ series
# cscope files
cscope.*
+
+*.orig
+*.rej
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index f08ca9535733..8b0563633442 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -12,6 +12,8 @@ Following translations are available on the WWW:
00-INDEX
- this file.
+ABI/
+ - info on kernel <-> userspace ABI and relative interface stability.
BUG-HUNTING
- brute force method of doing binary search of patches to find bug.
Changes
@@ -25,37 +27,57 @@ DMA-mapping.txt
DocBook/
- directory with DocBook templates etc. for kernel documentation.
HOWTO
- - The process and procedures of how to do Linux kernel development.
+ - the process and procedures of how to do Linux kernel development.
IO-mapping.txt
- how to access I/O mapped memory from within device drivers.
IPMI.txt
- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
IRQ-affinity.txt
- how to select which CPU(s) handle which interrupt events on SMP.
+IRQ.txt
+ - description of what an IRQ is.
ManagementStyle
- how to (attempt to) manage kernel hackers.
MSI-HOWTO.txt
- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+PCIEBUS-HOWTO.txt
+ - a guide describing the PCI Express Port Bus driver.
RCU/
- directory with info on RCU (read-copy update).
README.DAC960
- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
+README.cycladesZ
+ - info on Cyclades-Z firmware loading.
SAK.txt
- info on Secure Attention Keys.
+SecurityBugs
+ - procedure for reporting security bugs found in the kernel.
+SubmitChecklist
+ - Linux kernel patch submission checklist.
SubmittingDrivers
- procedure to get a new driver source included into the kernel tree.
SubmittingPatches
- procedure to get a source patch included into the kernel tree.
VGA-softcursor.txt
- how to change your VGA cursor from a blinking underscore.
+accounting/
+ - documentation on accounting and taskstats.
+aoe/
+ - description of AoE (ATA over Ethernet) along with config examples.
applying-patches.txt
- description of various trees and how to apply their patches.
arm/
- directory with info about Linux on the ARM architecture.
+atomic_ops.txt
+ - semantics and behavior of atomic and bitmask operations.
+auxdisplay/
+ - misc. LCD driver documentation (cfag12864b, ks0108).
basic_profiling.txt
- basic instructions for those who wants to profile Linux kernel.
binfmt_misc.txt
- info on the kernel support for extra binary formats.
+blackfin/
+ - directory with documentation for the Blackfin arch.
block/
- info on the Block I/O (BIO) layer.
cachetlb.txt
@@ -68,16 +90,32 @@ cli-sti-removal.txt
- cli()/sti() removal guide.
computone.txt
- info on Computone Intelliport II/Plus Multiport Serial Driver.
+connector/
+ - docs on the netlink based userspace<->kernel space communication mod.
+console/
+ - documentation on Linux console drivers.
cpqarray.txt
- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
cpu-freq/
- info on CPU frequency and voltage scaling.
+cpu-hotplug.txt
+ - document describing CPU hotplug support in the Linux kernel.
+cpu-load.txt
+ - document describing how CPU load statistics are collected.
+cpusets.txt
+ - documents the cpusets feature; assign CPUs and Mem to a set of tasks.
+cputopology.txt
+ - documentation on how CPU topology info is exported via sysfs.
cris/
- directory with info about Linux on CRIS architecture.
crypto/
- directory with info on the Crypto API.
+dcdbas.txt
+ - information on the Dell Systems Management Base Driver.
debugging-modules.txt
- some notes on debugging modules after Linux 2.6.3.
+dell_rbu.txt
+ - document demonstrating the use of the Dell Remote BIOS Update driver.
device-mapper/
- directory with info on Device Mapper.
devices.txt
@@ -86,32 +124,52 @@ digiepca.txt
- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
dnotify.txt
- info about directory notification in Linux.
+dontdiff
+ - file containing a list of files that should never be diff'ed.
driver-model/
- directory with info about Linux driver model.
+drivers/
+ - directory with driver documentation (currently only EDAC).
dvb/
- info on Linux Digital Video Broadcast (DVB) subsystem.
early-userspace/
- info about initramfs, klibc, and userspace early during boot.
+ecryptfs.txt
+ - docs on eCryptfs: stacked cryptographic filesystem for Linux.
eisa.txt
- info on EISA bus support.
exception.txt
- how Linux v2.2 handles exceptions without verify_area etc.
+fault-injection/
+ - dir with docs about the fault injection capabilities infrastructure.
fb/
- directory with info on the frame buffer graphics abstraction layer.
+feature-removal-schedule.txt
+ - list of files and features that are going to be removed.
filesystems/
- directory with info on the various filesystems that Linux supports.
firmware_class/
- request_firmware() hotplug interface info.
floppy.txt
- notes and driver options for the floppy disk driver.
+fujitsu/
+ - Fujitsu FR-V Linux documentation.
+gpio.txt
+ - overview of GPIO (General Purpose Input/Output) access conventions.
hayes-esp.txt
- info on using the Hayes ESP serial driver.
highuid.txt
- notes on the change from 16 bit to 32 bit user/group IDs.
hpet.txt
- High Precision Event Timer Driver for Linux.
+hrtimer/
+ - info on the timer_stats debugging facility for timer (ab)use.
+hrtimers/
+ - info on the hrtimers subsystem for high-resolution kernel timers.
hw_random.txt
- info on Linux support for random number generator in i8xx chipsets.
+hwmon/
+ - directory with docs on various hardware monitoring drivers.
i2c/
- directory with info about the I2C bus/protocol (2 wire, kHz speed).
i2o/
@@ -122,16 +180,22 @@ ia64/
- directory with info about Linux on Intel 64 bit architecture.
ide.txt
- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS).
+infiniband/
+ - directory with documents concerning Linux InfiniBand support.
initrd.txt
- how to use the RAM disk as an initial/temporary root filesystem.
input/
- info on Linux input device support.
io_ordering.txt
- info on ordering I/O writes to memory-mapped addresses.
+ioctl/
+ - directory with documents describing various IOCTL calls.
ioctl-number.txt
- how to implement and register device/driver ioctl calls.
iostats.txt
- info on I/O statistics Linux kernel provides.
+irqflags-tracing.txt
+ - how to use the irq-flags tracing feature.
isapnp.txt
- info on Linux ISA Plug & Play support.
isdn/
@@ -140,26 +204,40 @@ java.txt
- info on the in-kernel binary support for Java(tm).
kbuild/
- directory with info about the kernel build process.
-kdumpt.txt
- - mini HowTo on getting the crash dump code to work.
+kdump/
+ - directory with mini HowTo on getting the crash dump code to work.
kernel-doc-nano-HOWTO.txt
- mini HowTo on generation and location of kernel documentation files.
kernel-docs.txt
- listing of various WWW + books that document kernel internals.
kernel-parameters.txt
- summary listing of command line / boot prompt args for the kernel.
+keys-request-key.txt
+ - description of the kernel key request service.
+keys.txt
+ - description of the kernel key retention service.
kobject.txt
- info of the kobject infrastructure of the Linux kernel.
+kprobes.txt
+ - documents the kernel probes debugging feature.
+kref.txt
+ - docs on adding reference counters (krefs) to kernel objects.
laptop-mode.txt
- - How to conserve battery power using laptop-mode.
+ - how to conserve battery power using laptop-mode.
ldm.txt
- a brief description of LDM (Windows Dynamic Disks).
+leds-class.txt
+ - documents LED handling under Linux.
+local_ops.txt
+ - semantics and behavior of local atomic operations.
+lockdep-design.txt
+ - documentation on the runtime locking correctness validator.
locks.txt
- info on file locking implementations, flock() vs. fcntl(), etc.
logo.gif
- - Full colour GIF image of Linux logo (penguin).
+ - full colour GIF image of Linux logo (penguin - Tux).
logo.txt
- - Info on creator of above logo & site to get additional images from.
+ - info on creator of above logo & site to get additional images from.
m68k/
- directory with info about Linux on Motorola 68k architecture.
magic-number.txt
@@ -170,6 +248,8 @@ mca.txt
- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
md.txt
- info on boot arguments for the multiple devices driver.
+memory-barriers.txt
+ - info on Linux kernel memory barriers.
memory.txt
- info on typical Linux memory problems.
mips/
@@ -177,9 +257,11 @@ mips/
mono.txt
- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
moxa-smartio
- - info on installing/using Moxa multiport serial driver.
+ - file with info on installing/using Moxa multiport serial driver.
mtrr.txt
- how to use PPro Memory Type Range Registers to increase performance.
+mutex-design.txt
+ - info on the generic mutex subsystem.
nbd.txt
- info on a TCP implementation of a network block device.
netlabel/
@@ -190,6 +272,8 @@ nfsroot.txt
- short guide on setting up a diskless box with NFS root filesystem.
nmi_watchdog.txt
- info on NMI watchdog for SMP systems.
+nommu-mmap.txt
+ - documentation about no-mmu memory mapping support.
numastat.txt
- info on how to read Numa policy hit/miss statistics in sysfs.
oops-tracing.txt
@@ -202,8 +286,16 @@ parport.txt
- how to use the parallel-port driver.
parport-lowlevel.txt
- description and usage of the low level parallel port functions.
+pci-error-recovery.txt
+ - info on PCI error recovery.
pci.txt
- info on the PCI subsystem for device driver authors.
+pcieaer-howto.txt
+ - the PCI Express Advanced Error Reporting Driver Guide HOWTO.
+pcmcia/
+ - info on the Linux PCMCIA driver.
+pi-futex.txt
+ - documentation on lightweight PI-futexes.
pm.txt
- info on Linux power management support.
pnp.txt
@@ -214,18 +306,32 @@ powerpc/
- directory with info on using Linux with the PowerPC.
preempt-locking.txt
- info on locking under a preemptive kernel.
+prio_tree.txt
+ - info on radix-priority-search-tree use for indexing vmas.
ramdisk.txt
- short guide on how to set up and use the RAM disk.
+rbtree.txt
+ - info on what red-black trees are and what they are for.
riscom8.txt
- notes on using the RISCom/8 multi-port serial driver.
+robust-futex-ABI.txt
+ - documentation of the robust futex ABI.
+robust-futexes.txt
+ - a description of what robust futexes are.
rocket.txt
- info on the Comtrol RocketPort multiport serial driver.
rpc-cache.txt
- introduction to the caching mechanisms in the sunrpc layer.
+rt-mutex-design.txt
+ - description of the RealTime mutex implementation design.
+rt-mutex.txt
+ - desc. of RT-mutex subsystem with PI (Priority Inheritance) support.
rtc.txt
- notes on how to use the Real Time Clock (aka CMOS clock) driver.
s390/
- directory with info on using Linux on the IBM S390.
+sched-arch.txt
+ - CPU Scheduler implementation hints for architecture specific code.
sched-coding.txt
- reference for various scheduler-related methods in the O(1) scheduler.
sched-design.txt
@@ -240,22 +346,32 @@ serial/
- directory with info on the low level serial API.
serial-console.txt
- how to set up Linux with a serial line console as the default.
+sgi-ioc4.txt
+ - description of the SGI IOC4 PCI (multi function) device.
sgi-visws.txt
- short blurb on the SGI Visual Workstations.
sh/
- directory with info on porting Linux to a new architecture.
+sharedsubtree.txt
+ - a description of shared subtrees for namespaces.
smart-config.txt
- description of the Smart Config makefile feature.
smp.txt
- a few notes on symmetric multi-processing.
+sony-laptop.txt
+ - Sony Notebook Control Driver (SNC) Readme.
sonypi.txt
- info on Linux Sony Programmable I/O Device support.
sound/
- directory with info on sound card support.
sparc/
- directory with info on using Linux on Sparc architecture.
+sparse.txt
+ - info on how to obtain and use the sparse tool for typechecking.
specialix.txt
- info on hardware/driver for specialix IO8+ multiport serial card.
+spi/
+ - overview of Linux kernel Serial Peripheral Interface (SPI) support.
spinlocks.txt
- info on using spinlocks to provide exclusive access in kernel.
stable_api_nonsense.txt
@@ -274,24 +390,32 @@ sysrq.txt
- info on the magic SysRq key.
telephony/
- directory with info on telephony (e.g. voice over IP) support.
+thinkpad-acpi.txt
+ - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
time_interpolators.txt
- info on time interpolators.
tipar.txt
- information about Parallel link cable for Texas Instruments handhelds.
tty.txt
- guide to the locking policies of the tty layer.
-unicode.txt
- - info on the Unicode character/font mapping used in Linux.
uml/
- directory with information about User Mode Linux.
+unicode.txt
+ - info on the Unicode character/font mapping used in Linux.
+unshare.txt
+ - description of the Linux unshare system call.
usb/
- directory with info regarding the Universal Serial Bus.
+video-output.txt
+ - sysfs class driver interface to enable/disable a video output device.
video4linux/
- directory with info regarding video/TV/radio cards and linux.
vm/
- directory with info on the Linux vm code.
voyager.txt
- guide to running Linux on the Voyager architecture.
+w1/
+ - directory with documents regarding the 1-wire (w1) subsystem.
watchdog/
- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
x86_64/
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index b49b92edb396..a667eb1fc26e 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -218,6 +218,18 @@ no space after the prefix increment & decrement unary operators:
and no space around the '.' and "->" structure member operators.
+Do not leave trailing whitespace at the ends of lines. Some editors with
+"smart" indentation will insert whitespace at the beginning of new lines as
+appropriate, so you can start typing the next line of code right away.
+However, some such editors do not remove the whitespace if you end up not
+putting a line of code there, such as if you leave a blank line. As a result,
+you end up with lines containing trailing whitespace.
+
+Git will warn you about patches that introduce trailing whitespace, and can
+optionally strip the trailing whitespace for you; however, if applying a series
+of patches, this may make later patches in the series fail by changing their
+context lines.
+
Chapter 4: Naming
@@ -726,6 +738,33 @@ need them. Feel free to peruse that header file to see what else is already
defined that you shouldn't reproduce in your code.
+ Chapter 18: Editor modelines and other cruft
+
+Some editors can interpret configuration information embedded in source files,
+indicated with special markers. For example, emacs interprets lines marked
+like this:
+
+-*- mode: c -*-
+
+Or like this:
+
+/*
+Local Variables:
+compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+End:
+*/
+
+Vim interprets markers that look like this:
+
+/* vim:set sw=8 noet */
+
+Do not include any of these in source files. People have their own personal
+editor configurations, and your source files should not override them. This
+includes markers for indentation and mode configuration. People may use their
+own custom mode, or may have some other magic method for making indentation
+work correctly.
+
+
Appendix I: References
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 46bcff2849bd..fd2ef4d29b6d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -139,8 +139,10 @@ X!Ilib/string.c
!Elib/cmdline.c
</sect1>
- <sect1><title>CRC Functions</title>
+ <sect1 id="crc"><title>CRC Functions</title>
+!Elib/crc7.c
!Elib/crc16.c
+!Elib/crc-itu-t.c
!Elib/crc32.c
!Elib/crc-ccitt.c
</sect1>
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
index 45cad23efefa..2de84dc195a8 100644
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ b/Documentation/DocBook/procfs-guide.tmpl
@@ -352,49 +352,93 @@ entry->write_proc = write_proc_foo;
<funcsynopsis>
<funcprototype>
<funcdef>int <function>read_func</function></funcdef>
- <paramdef>char* <parameter>page</parameter></paramdef>
+ <paramdef>char* <parameter>buffer</parameter></paramdef>
<paramdef>char** <parameter>start</parameter></paramdef>
<paramdef>off_t <parameter>off</parameter></paramdef>
<paramdef>int <parameter>count</parameter></paramdef>
- <paramdef>int* <parameter>eof</parameter></paramdef>
+ <paramdef>int* <parameter>peof</parameter></paramdef>
<paramdef>void* <parameter>data</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
The read function should write its information into the
- <parameter>page</parameter>. For proper use, the function
- should start writing at an offset of
- <parameter>off</parameter> in <parameter>page</parameter> and
- write at most <parameter>count</parameter> bytes, but because
- most read functions are quite simple and only return a small
- amount of information, these two parameters are usually
- ignored (it breaks pagers like <literal>more</literal> and
- <literal>less</literal>, but <literal>cat</literal> still
- works).
+ <parameter>buffer</parameter>, which will be exactly
+ <literal>PAGE_SIZE</literal> bytes long.
</para>
<para>
- If the <parameter>off</parameter> and
- <parameter>count</parameter> parameters are properly used,
- <parameter>eof</parameter> should be used to signal that the
+ The parameter
+ <parameter>peof</parameter> should be used to signal that the
end of the file has been reached by writing
<literal>1</literal> to the memory location
- <parameter>eof</parameter> points to.
+ <parameter>peof</parameter> points to.
</para>
<para>
- The parameter <parameter>start</parameter> doesn't seem to be
- used anywhere in the kernel. The <parameter>data</parameter>
+ The <parameter>data</parameter>
parameter can be used to create a single call back function for
several files, see <xref linkend="usingdata"/>.
</para>
<para>
- The <function>read_func</function> function must return the
- number of bytes written into the <parameter>page</parameter>.
+ The rest of the parameters and the return value are described
+ by a comment in <filename>fs/proc/generic.c</filename> as follows:
</para>
+ <blockquote>
+ <para>
+ You have three ways to return data:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Leave <literal>*start = NULL</literal>. (This is the default.)
+ Put the data of the requested offset at that
+ offset within the buffer. Return the number (<literal>n</literal>)
+ of bytes there are from the beginning of the
+ buffer up to the last byte of data. If the
+ number of supplied bytes (<literal>= n - offset</literal>) is
+ greater than zero and you didn't signal eof
+ and the reader is prepared to take more data
+ you will be called again with the requested
+ offset advanced by the number of bytes
+ absorbed. This interface is useful for files
+ no larger than the buffer.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Set <literal>*start</literal> to an unsigned long value less than
+ the buffer address but greater than zero.
+ Put the data of the requested offset at the
+ beginning of the buffer. Return the number of
+ bytes of data placed there. If this number is
+ greater than zero and you didn't signal eof
+ and the reader is prepared to take more data
+ you will be called again with the requested
+ offset advanced by <literal>*start</literal>. This interface is
+ useful when you have a large file consisting
+ of a series of blocks which you want to count
+ and return as wholes.
+ (Hack by Paul.Russell@rustcorp.com.au)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Set <literal>*start</literal> to an address within the buffer.
+ Put the data of the requested offset at <literal>*start</literal>.
+ Return the number of bytes of data placed there.
+ If this number is greater than zero and you
+ didn't signal eof and the reader is prepared to
+ take more data you will be called again with the
+ requested offset advanced by the number of bytes
+ absorbed.
+ </para>
+ </listitem>
+ </orderedlist>
+ </blockquote>
+
<para>
<xref linkend="example"/> shows how to use a read call back
function.
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index f4dffadbcb00..42b01bc2e1b4 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -222,7 +222,15 @@ over a rather long period of time, but improvements are always welcome!
deadlock as soon as the RCU callback happens to interrupt that
acquisition's critical section.
-13. SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
+13. RCU callbacks can be and are executed in parallel. In many cases,
+ the callback code simply wrappers around kfree(), so that this
+ is not an issue (or, more accurately, to the extent that it is
+ an issue, the memory-allocator locking handles it). However,
+ if the callbacks do manipulate a shared data structure, they
+ must use whatever locking or other synchronization is required
+ to safely access and/or modify that data structure.
+
+14. SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
may only be invoked from process context. Unlike other forms of
RCU, it -is- permissible to block in an SRCU read-side critical
section (demarked by srcu_read_lock() and srcu_read_unlock()),
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 6ebffb57e3db..19e7f65c269f 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -1,4 +1,4 @@
-Linux Kernel patch sumbittal checklist
+Linux Kernel patch submission checklist
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here are some basic things that developers should do if they want to see their
@@ -9,7 +9,6 @@ Documentation/SubmittingPatches and elsewhere regarding submitting Linux
kernel patches.
-
1: Builds cleanly with applicable or modified CONFIG options =y, =m, and
=n. No gcc warnings/errors, no linker warnings/errors.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 0958e97d4bf4..3f9a7912e69b 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -464,9 +464,25 @@ section Linus Computer Science 101.
Nuff said. If your code deviates too much from this, it is likely
to be rejected without further review, and without comment.
+Once significant exception is when moving code from one file to
+another in this case you should not modify the moved code at all in
+the same patch which moves it. This clearly delineates the act of
+moving the code and your changes. This greatly aids review of the
+actual differences and allows tools to better track the history of
+the code itself.
+
Check your patches with the patch style checker prior to submission
-(scripts/checkpatch.pl). You should be able to justify all
-violations that remain in your patch.
+(scripts/checkpatch.pl). The style checker should be viewed as
+a guide not as the final word. If your code looks better with
+a violation then its probably best left alone.
+
+The checker reports at three levels:
+ - ERROR: things that are very likely to be wrong
+ - WARNING: things requiring careful review
+ - CHECK: things requiring thought
+
+You should be able to justify all violations that remain in your
+patch.
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index 71acc28ed0d1..24c5aade8998 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -49,6 +49,7 @@ char name[100];
int dbg;
int print_delays;
int print_io_accounting;
+int print_task_context_switch_counts;
__u64 stime, utime;
#define PRINTF(fmt, arg...) { \
@@ -195,7 +196,7 @@ void print_delayacct(struct taskstats *t)
"IO %15s%15s\n"
" %15llu%15llu\n"
"MEM %15s%15s\n"
- " %15llu%15llu\n\n",
+ " %15llu%15llu\n"
"count", "real total", "virtual total", "delay total",
t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
t->cpu_delay_total,
@@ -204,6 +205,14 @@ void print_delayacct(struct taskstats *t)
"count", "delay total", t->swapin_count, t->swapin_delay_total);
}
+void task_context_switch_counts(struct taskstats *t)
+{
+ printf("\n\nTask %15s%15s\n"
+ " %15lu%15lu\n",
+ "voluntary", "nonvoluntary",
+ t->nvcsw, t->nivcsw);
+}
+
void print_ioacct(struct taskstats *t)
{
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
@@ -235,7 +244,7 @@ int main(int argc, char *argv[])
struct msgtemplate msg;
while (1) {
- c = getopt(argc, argv, "diw:r:m:t:p:vl");
+ c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
if (c < 0)
break;
@@ -248,6 +257,10 @@ int main(int argc, char *argv[])
printf("printing IO accounting\n");
print_io_accounting = 1;
break;
+ case 'q':
+ printf("printing task/process context switch rates\n");
+ print_task_context_switch_counts = 1;
+ break;
case 'w':
logfile = strdup(optarg);
printf("write to file %s\n", logfile);
@@ -389,6 +402,8 @@ int main(int argc, char *argv[])
print_delayacct((struct taskstats *) NLA_DATA(na));
if (print_io_accounting)
print_ioacct((struct taskstats *) NLA_DATA(na));
+ if (print_task_context_switch_counts)
+ task_context_switch_counts((struct taskstats *) NLA_DATA(na));
if (fd) {
if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
err(1,"write error\n");
diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt
index 661c797eaf79..8aa7529f8258 100644
--- a/Documentation/accounting/taskstats-struct.txt
+++ b/Documentation/accounting/taskstats-struct.txt
@@ -22,6 +22,8 @@ There are three different groups of fields in the struct taskstats:
/* Extended accounting fields end */
Their values are collected if CONFIG_TASK_XACCT is set.
+4) Per-task and per-thread context switch count statistics
+
Future extension should add fields to the end of the taskstats struct, and
should not change the relative position of each field within the struct.
@@ -158,4 +160,8 @@ struct taskstats {
/* Extended accounting fields end */
+4) Per-task and per-thread statistics
+ __u64 nvcsw; /* Context voluntary switch counter */
+ __u64 nivcsw; /* Context involuntary switch counter */
+
}
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index debf6813934a..866b76139420 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -253,7 +253,7 @@ Here are the routines, one by one:
The first of these two routines is invoked after map_vm_area()
has installed the page table entries. The second is invoked
- before unmap_vm_area() deletes the page table entries.
+ before unmap_kernel_range() deletes the page table entries.
There exists another whole class of cpu cache issues which currently
require a whole different set of interfaces to handle properly.
diff --git a/Documentation/cdrom/00-INDEX b/Documentation/cdrom/00-INDEX
index 916dafe29d3f..433edf23dc49 100644
--- a/Documentation/cdrom/00-INDEX
+++ b/Documentation/cdrom/00-INDEX
@@ -2,32 +2,10 @@
- this file (info on CD-ROMs and Linux)
Makefile
- only used to generate TeX output from the documentation.
-aztcd
- - info on Aztech/Orchid/Okano/Wearnes/Conrad/CyCDROM driver.
cdrom-standard.tex
- LaTeX document on standardizing the CD-ROM programming interface.
-cdu31a
- - info on the Sony CDU31A/CDU33A CD-ROM driver.
-cm206
- - info on the Philips/LMS cm206/cm260 CD-ROM driver.
-gscd
- - info on the Goldstar R420 CD-ROM driver.
ide-cd
- info on setting up and using ATAPI (aka IDE) CD-ROMs.
-isp16
- - info on the CD-ROM interface on ISP16, MAD16 or Mozart sound card.
-mcd
- - info on limitations of standard Mitsumi CD-ROM driver.
-mcdx
- - info on improved Mitsumi CD-ROM driver.
-optcd
- - info on the Optics Storage 8000 AT CD-ROM driver
packet-writing.txt
- Info on the CDRW packet writing module
-sbpcd
- - info on the SoundBlaster/Panasonic CD-ROM interface driver.
-sjcd
- - info on the SANYO CDR-H94A CD-ROM interface driver.
-sonycd535
- - info on the Sony CDU-535 (and 531) CD-ROM driver.
diff --git a/Documentation/cdrom/aztcd b/Documentation/cdrom/aztcd
deleted file mode 100644
index 6bf0290ef7ce..000000000000
--- a/Documentation/cdrom/aztcd
+++ /dev/null
@@ -1,822 +0,0 @@
-$Id: README.aztcd,v 2.60 1997/11/29 09:51:25 root Exp root $
- Readme-File Documentation/cdrom/aztcd
- for
- AZTECH CD-ROM CDA268-01A, ORCHID CD-3110,
- OKANO/WEARNES CDD110, CONRAD TXC, CyCDROM CR520, CR540
- CD-ROM Drives
- Version 2.6 and newer
- (for other drives see 6.-8.)
-
-NOTE: THIS DRIVER WILL WORK WITH THE CD-ROM DRIVES LISTED, WHICH HAVE
- A PROPRIETARY INTERFACE (implemented on a sound card or on an
- ISA-AT-bus card).
- IT WILL DEFINITELY NOT WORK WITH CD-ROM DRIVES WITH *IDE*-INTERFACE,
- such as the Aztech CDA269-031SE !!! (The only known exceptions are
- 'faked' IDE drives like the CyCDROM CR520ie which work with aztcd
- under certain conditions, see 7.). IF YOU'RE USING A CD-ROM DRIVE
- WITH IDE-INTERFACE, SOMETIMES ALSO CALLED ATAPI-COMPATIBLE, PLEASE
- USE THE ide-cd.c DRIVER, WRITTEN BY MARK LORD AND SCOTT SNYDER !
- THE STANDARD-KERNEL 1.2.x NOW ALSO SUPPORTS IDE-CDROM-DRIVES, SEE THE
- HARDDISK (!) SECTION OF make config, WHEN COMPILING A NEW KERNEL!!!
-----------------------------------------------------------------------------
-
-Contents of this file:
- 1. NOTE
- 2. INSTALLATION
- 3. CONFIGURING YOUR KERNEL
- 4. RECOMPILING YOUR KERNEL
- 4.1 AZTCD AS A RUN-TIME LOADABLE MODULE
- 4.2 CDROM CONNECTED TO A SOUNDCARD
- 5. KNOWN PROBLEMS, FUTURE DEVELOPMENTS
- 5.1 MULTISESSION SUPPORT
- 5.2 STATUS RECOGNITION
- 5.3 DOSEMU's CDROM SUPPORT
- 6. BUG REPORTS
- 7. OTHER DRIVES
- 8. IF YOU DON'T SUCCEED ... DEBUGGING
- 9. TECHNICAL HISTORY OF THE DRIVER
- 10. ACKNOWLEDGMENTS
- 11. PROGRAMMING ADD ONS: CDPLAY.C
- APPENDIX: Source code of cdplay.c
-----------------------------------------------------------------------------
-
-1. NOTE
-This software has been successfully in alpha and beta test and is part of
-the standard kernel since kernel 1.1.8x since December 1994. It works with
-AZTECH CDA268-01A, ORCHID CDS-3110, ORCHID/WEARNES CDD110 and CONRAD TXC
-(Nr.99 31 23 -series 04) and has proven to be stable with kernel
-versions 1.0.9 and newer. But with any software there still may be bugs in it.
-So if you encounter problems, you are invited to help us improve this software.
-Please send me a detailed bug report (see chapter BUG REPORTS). You are also
-invited in helping us to increase the number of drives, which are supported.
-
-Please read the README-files carefully and always keep a backup copy of your
-old kernel, in order to reboot if something goes wrong!
-
-2. INSTALLATION
-The driver consists of a header file 'aztcd.h', which normally should reside
-in /usr/src/linux/drivers/cdrom and the source code 'aztcd.c', which normally
-resides in the same place. It uses /dev/aztcd (/dev/aztcd0 in some distri-
-butions), which must be a valid block device with major number 29 and reside
-in directory /dev. To mount a CD-ROM, your kernel needs to have the ISO9660-
-filesystem support included.
-
-PLEASE NOTE: aztcd.c has been developed in parallel to the linux kernel,
-which had and is having many major and minor changes which are not backward
-compatible. Quite definitely aztcd.c version 1.80 and newer will NOT work
-in kernels older than 1.3.33. So please always use the most recent version
-of aztcd.c with the appropriate linux-kernel.
-
-3. CONFIGURING YOUR KERNEL
-If your kernel is already configured for using the AZTECH driver you will
-see the following message while Linux boots:
- Aztech CD-ROM Init: DriverVersion=<version number> BaseAddress=<baseaddress>
- Aztech CD-ROM Init: FirmwareVersion=<firmware version id of your I/O-card>>>
- Aztech CD-ROM Init: <drive type> detected
- Aztech CD-ROM Init: End
-If the message looks different and you are sure to have a supported drive,
-it may have a different base address. The Aztech driver does look for the
-CD-ROM drive at the base address specified in aztcd.h at compile time. This
-address can be overwritten by boot parameter aztcd=....You should reboot and
-start Linux with boot parameter aztcd=<base address>, e.g. aztcd=0x320. If
-you do not know the base address, start your PC with DOS and look at the boot
-message of your CD-ROM's DOS driver. If that still does not help, use boot
-parameter aztcd=<base address>,0x79 , this tells aztcd to try a little harder.
-aztcd may be configured to use autoprobing the base address by recompiling
-it (see chapter 4.).
-
-If the message looks correct, as user 'root' you should be able to mount the
-drive by
- mount -t iso9660 -r /dev/aztcd0 /mnt
-and use it as any other filesystem. (If this does not work, check if
-/dev/aztcd0 and /mnt do exist and create them, if necessary by doing
- mknod /dev/aztcd0 b 29 0
- mkdir /mnt
-
-If you still get a different message while Linux boots or when you get the
-message, that the ISO9660-filesystem is not supported by your kernel, when
-you try to mount the CD-ROM drive, you have to recompile your kernel.
-
-If you do *not* have an Aztech/Orchid/Okano/Wearnes/TXC drive and want to
-bypass drive detection during Linux boot up, start with boot parameter aztcd=0.
-
-Most distributions nowadays do contain a boot disk image containing aztcd.
-Please note, that this driver will not work with IDE/ATAPI drives! With these
-you must use ide-cd.c instead.
-
-4. RECOMPILING YOUR KERNEL
-If your kernel is not yet configured for the AZTECH driver and the ISO9660-
-filesystem, you have to recompile your kernel:
-
-- Edit aztcd.h to set the I/O-address to your I/O-Base address (AZT_BASE_ADDR),
- the driver does not use interrupts or DMA, so if you are using an AZTECH
- CD268, an ORCHID CD-3110 or ORCHID/WEARNES CDD110 that's the only item you
- have to set up. If you have a soundcard, read chapter 4.2.
- Users of other drives should read chapter OTHER DRIVES of this file.
- You also can configure that address by kernel boot parameter aztcd=...
-- aztcd may be configured to use autoprobing the base address by setting
- AZT_BASE_ADDR to '-1'. In that case aztcd probes the addresses listed
- under AZT_BASE_AUTO. But please remember, that autoprobing always may
- incorrectly influence other hardware components too!
-- There are some other points, which may be configured, e.g. auto-eject the
- CD when unmounting a drive, tray locking etc., see aztcd.h for details.
-- If you're using a linux kernel version prior to 2.1.0, in aztcd.h
- uncomment the line '#define AZT_KERNEL_PRIOR_2_1'
-- Build a new kernel, configure it for 'Aztech/Orchid/Okano/Wearnes support'
- (if you want aztcd to be part of the kernel). Do not configure it for
- 'Aztech... support', if you want to use aztcd as a run time loadable module.
- But in any case you must have the ISO9660-filesystem included in your
- kernel.
-- Activate the new kernel, normally this is done by running LILO (don't for-
- get to configure it before and to keep a copy of your old kernel in case
- something goes wrong!).
-- Reboot
-- If you've included aztcd in your kernel, you now should see during boot
- some messages like
- Aztech CD-ROM Init: DriverVersion=<version number> BaseAddress=<baseaddress>
- Aztech CD-ROM Init: FirmwareVersion=<firmware version id of your I/O-card>
- Aztech CD-ROM Init: <drive type> detected
- Aztech CD-ROM Init: End
-- If you have not included aztcd in your kernel, but want to load aztcd as a
- run time loadable module see 4.1.
-- If the message looks correct, as user 'root' you should be able to mount
- the drive by
- mount -t iso9660 -r /dev/aztcd0 /mnt
- and use it as any other filesystem. (If this does not work, check if
- /dev/aztcd0 and /mnt do exist and create them, if necessary by doing
- mknod /dev/aztcd0 b 29 0
- mkdir /mnt
-- If this still does not help, see chapters OTHER DRIVES and DEBUGGING.
-
-4.1 AZTCD AS A RUN-TIME LOADABLE MODULE
-If you do not need aztcd permanently, you can also load and remove the driver
-during runtime via insmod and rmmod. To build aztcd as a loadable module you
-must configure your kernel for AZTECH module support (answer 'm' when con-
-figuring the kernel). Anyhow, you may run into problems, if the version of
-your boot kernel is not the same than the source kernel version, from which
-you create the modules. So rebuild your kernel, if necessary.
-
-Now edit the base address of your AZTECH interface card in
-/usr/src/linux/drivers/cdrom/aztcd.h to the appropriate value.
-aztcd may be configured to use autoprobing the base address by setting
-AZT_BASE_ADDR to '-1'. In that case aztcd probes the addresses listed
-under AZT_BASE_AUTO. But please remember, that autoprobing always may
-incorrectly influence other hardware components too!
-There are also some special features which may be configured, e.g.
-auto-eject a CD when unmounting the drive etc; see aztcd.h for details.
-Then change to /usr/src/linux and do a
- make modules
- make modules_install
-After that you can run-time load the driver via
- insmod /lib/modules/X.X.X/misc/aztcd.o
-and remove it via rmmod aztcd.
-If you did not set the correct base address in aztcd.h, you can also supply the
-base address when loading the driver via
- insmod /lib/modules/X.X.X/misc/aztcd.o aztcd=<base address>
-Again specifying aztcd=-1 will cause autoprobing.
-If you do not have the iso9660-filesystem in your boot kernel, you also have
-to load it before you can mount the CDROM:
- insmod /lib/modules/X.X.X/fs/isofs.o
-The mount procedure works as described in 4. above.
-(In all commands 'X.X.X' is the current linux kernel version number)
-
-4.2 CDROM CONNECTED TO A SOUNDCARD
-Most soundcards do have a bus interface to the CDROM-drive. In many cases
-this soundcard needs to be configured, before the CDROM can be used. This
-configuration procedure consists of writing some kind of initialization
-data to the soundcard registers. The AZTECH-CDROM driver in the moment does
-only support one type of soundcard (SoundWave32). Users of other soundcards
-should try to boot DOS first and let their DOS drivers initialize the
-soundcard and CDROM, then warm boot (or use loadlin) their PC to start
-Linux.
-Support for the CDROM-interface of SoundWave32-soundcards is directly
-implemented in the AZTECH driver. Please edit linux/drivers/cdrom/aztdc.h,
-uncomment line '#define AZT_SW32' and set the appropriate value for
-AZT_BASE_ADDR and AZT_SW32_BASE_ADDR. This support was tested with an Orchid
-CDS-3110 connected to a SoundWave32.
-If you want your soundcard to be supported, find out, how it needs to be
-configured and mail me (see 6.) the appropriate information.
-
-5. KNOWN PROBLEMS, FUTURE DEVELOPMENTS
-5.1 MULTISESSION SUPPORT
-Multisession support for CD's still is a myth. I implemented and tested a basic
-support for multisession and XA CDs, but I still have not enough CDs and appli-
-cations to test it rigorously. So if you'd like to help me, please contact me
-(Email address see below). As of version 1.4 and newer you can enable the
-multisession support in aztcd.h by setting AZT_MULTISESSION to 1. Doing so
-will cause the ISO9660-filesystem to deal with multisession CDs, ie. redirect
-requests to the Table of Contents (TOC) information from the last session,
-which contains the info of all previous sessions etc.. If you do set
-AZT_MULTISESSION to 0, you can use multisession CDs anyway. In that case the
-drive's firmware will do automatic redirection. For the ISO9660-filesystem any
-multisession CD will then look like a 'normal' single session CD. But never-
-theless the data of all sessions are viewable and accessible. So with practical-
-ly all real world applications you won't notice the difference. But as future
-applications may make use of advanced multisession features, I've started to
-implement the interface for the ISO9660 multisession interface via ioctl
-CDROMMULTISESSION.
-
-5.2 STATUS RECOGNITION
-The drive status recognition does not work correctly in all cases. Changing
-a disk or having the door open, when a drive is already mounted, is detected
-by the Aztech driver itself, but nevertheless causes multiple read attempts
-by the different layers of the ISO9660-filesystem driver, which finally timeout,
-so you have to wait quite a little... But isn't it bad style to change a disk
-in a mounted drive, anyhow ?!
-
-The driver uses busy wait in most cases for the drive handshake (macros
-STEN_LOW and DTEN_LOW). I tested with a 486/DX2 at 66MHz and a Pentium at
-60MHz and 90MHz. Whenever you use a much faster machine you are likely to get
-timeout messages. In that case edit aztcd.h and increase the timeout value
-AZT_TIMEOUT.
-
-For some 'slow' drive commands I implemented waiting with a timer waitqueue
-(macro STEN_LOW_WAIT). If you get this timeout message, you may also edit
-aztcd.h and increase the timeout value AZT_STATUS_DELAY. The waitqueue has
-shown to be a little critical. If you get kernel panic messages, edit aztcd.c
-and substitute STEN_LOW_WAIT by STEN_LOW. Busy waiting with STEN_LOW is more
-stable, but also causes CPU overhead.
-
-5.3 DOSEMU's CD-ROM SUPPORT
-With release 1.20 aztcd was modified to allow access to CD-ROMS when running
-under dosemu-0.60.0 aztcd-versions before 1.20 are most likely to crash
-Linux, when a CD-ROM is accessed under dosemu. This problem has partly been
-fixed, but still when accessing a directory for the first time the system
-might hang for some 30sec. So be patient, when using dosemu's CD-ROM support
-in combination with aztcd :-) !
-This problem has now (July 1995) been fixed by a modification to dosemu's
-CD-ROM driver. The new version came with dosemu-0.60.2, see dosemu's
-README.CDROM.
-
-6. BUG REPORTS
-Please send detailed bug reports and bug fixes via EMail to
-
- Werner.Zimmermann@fht-esslingen.de
-
-Please include a description of your CD-ROM drive type and interface card,
-the exact firmware message during Linux bootup, the version number of the
-AZTECH-CDROM-driver and the Linux kernel version. Also a description of your
-system's other hardware could be of interest, especially microprocessor type,
-clock frequency, other interface cards such as soundcards, ethernet adapter,
-game cards etc..
-
-I will try to collect the reports and make the necessary modifications from
-time to time. I may also come back to you directly with some bug fixes and
-ask you to do further testing and debugging.
-
-Editors of CD-ROMs are invited to send a 'cooperation' copy of their
-CD-ROMs to the volunteers, who provided the CD-ROM support for Linux. My
-snail mail address for such 'stuff' is
- Prof. Dr. W. Zimmermann
- Fachhochschule fuer Technik Esslingen
- Fachbereich IT
- Flandernstrasse 101
- D-73732 Esslingen
- Germany
-
-
-7. OTHER DRIVES
-The following drives ORCHID CDS3110, OKANO CDD110, WEARNES CDD110 and Conrad
-TXC Nr. 993123-series 04 nearly look the same as AZTECH CDA268-01A, especially
-they seem to use the same command codes. So it was quite simple to make the
-AZTECH driver work with these drives.
-
-Unfortunately I do not have any of these drives available, so I couldn't test
-it myself. In some installations, it seems necessary to initialize the drive
-with the DOS driver before (especially if combined with a sound card) and then
-do a warm boot (CTRL-ALT-RESET) or start Linux from DOS, e.g. with 'loadlin'.
-
-If you do not succeed, read chapter DEBUGGING. Thanks in advance!
-
-Sorry for the inconvenience, but it is difficult to develop for hardware,
-which you don't have available for testing. So if you like, please help us.
-
-If you do have a CyCDROM CR520ie thanks to Hilmar Berger's help your chances
-are good, that it will work with aztcd. The CR520ie is sold as an IDE-drive
-and really is connected to the IDE interface (primary at 0x1F0 or secondary
-at 0x170, configured as slave, not as master). Nevertheless it is not ATAPI
-compatible but still uses Aztech's command codes.
-
-
-8. DEBUGGING : IF YOU DON'T SUCCEED, TRY THE FOLLOWING
--reread the complete README file
--make sure, that your drive is hardware configured for
- transfer mode: polled
- IRQ: not used
- DMA: not used
- Base Address: something like 300, 320 ...
- You can check this, when you start the DOS driver, which came with your
- drive. By appropriately configuring the drive and the DOS driver you can
- check, whether your drive does operate in this mode correctly under DOS. If
- it does not operate under DOS, it won't under Linux.
- If your drive's base address is something like 0x170 or 0x1F0 (and it is
- not a CyCDROM CR520ie or CR 940ie) you most likely are having an IDE/ATAPI-
- compatible drive, which is not supported by aztcd.c, use ide-cd.c instead.
- Make sure the Base Address is configured correctly in aztcd.h, also make
- sure, that /dev/aztcd0 exists with the correct major number (compare it with
- the entry in file /usr/include/linux/major.h for the Aztech drive).
--insert a CD-ROM and close the tray
--cold boot your PC (i.e. via the power on switch or the reset button)
--if you start Linux via DOS, e.g. using loadlin, make sure, that the DOS
- driver for the CD-ROM drive is not loaded (comment out the calling lines
- in DOS' config.sys!)
--look for the aztcd: init message during Linux init and note them exactly
--log in as root and do a mount -t iso9660 /dev/aztcd0 /mnt
--if you don't succeed in the first time, try several times. Try also to open
- and close the tray, then mount again. Please note carefully all commands
- you typed in and the aztcd-messages, which you get.
--if you get an 'Aztech CD-ROM init: aborted' message, read the remarks about
- the version string below.
-
-If this does not help, do the same with the following differences
--start DOS before; make now sure, that the DOS driver for the CD-ROM is
- loaded under DOS (i.e. uncomment it again in config.sys)
--warm boot your PC (i.e. via CTRL-ALT-DEL)
- if you have it, you can also start via loadlin (try both).
- ...
- Again note all commands and the aztcd-messages.
-
-If you see STEN_LOW or STEN_LOW_WAIT error messages, increase the timeout
-values.
-
-If this still does not help,
--look in aztcd.c for the lines #if 0
- #define AZT_TEST1
- ...
- #endif
- and substitute '#if 0' by '#if 1'.
--recompile your kernel and repeat the above two procedures. You will now get
- a bundle of debugging messages from the driver. Again note your commands
- and the appropriate messages. If you have syslogd running, these messages
- may also be found in syslogd's kernel log file. Nevertheless in some
- installations syslogd does not yet run, when init() is called, thus look for
- the aztcd-messages during init, before the login-prompt appears.
- Then look in aztcd.c, to find out, what happened. The normal calling sequence
- is: aztcd_init() during Linux bootup procedure init()
- after doing a 'mount -t iso9660 /dev/aztcd0 /mnt' the normal calling sequence is
- aztcd_open() -> Status 2c after cold reboot with CDROM or audio CD inserted
- -> Status 8 after warm reboot with CDROM inserted
- -> Status 2e after cold reboot with no disk, closed tray
- -> Status 6e after cold reboot, mount with door open
- aztUpdateToc()
- aztGetDiskInfo()
- aztGetQChannelInfo() repeated several times
- aztGetToc()
- aztGetQChannelInfo() repeated several times
- a list of track information
- do_aztcd_request() }
- azt_transfer() } repeated several times
- azt_poll }
- Check, if there is a difference in the calling sequence or the status flags!
-
- There are a lot of other messages, eg. the ACMD-command code (defined in
- aztcd.h), status info from the getAztStatus-command and the state sequence of
- the finite state machine in azt_poll(). The most important are the status
- messages, look how they are defined and try to understand, if they make
- sense in the context where they appear. With a CD-ROM inserted the status
- should always be 8, except in aztcd_open(). Try to open the tray, insert an
- audio disk, insert no disk or reinsert the CD-ROM and check, if the status
- bits change accordingly. The status bits are the most likely point, where
- the drive manufacturers may implement changes.
-
-If you still don't succeed, a good point to start is to look in aztcd.c in
-function aztcd_init, where the drive should be detected during init. Do the
-following:
--reboot the system with boot parameter 'aztcd=<your base address>,0x79'. With
- parameter 0x79 most of the drive version detection is bypassed. After that
- you should see the complete version string including leading and trailing
- blanks during init.
- Now adapt the statement
- if ((result[1]=='A')&&(result[2]=='Z' ...)
- in aztcd_init() to exactly match the first 3 or 4 letters you have seen.
--Another point is the 'smart' card detection feature in aztcd_init(). Normally
- the CD-ROM drive is ready, when aztcd_init is trying to read the version
- string and a time consuming ACMD_SOFT_RESET command can be avoided. This is
- detected by looking, if AFL_OP_OK can be read correctly. If the CD-ROM drive
- hangs in some unknown state, e.g. because of an error before a warm start or
- because you first operated under DOS, even the version string may be correct,
- but the following commands will not. Then change the code in such a way,
- that the ACMD_SOFT_RESET is issued in any case, by substituting the
- if-statement 'if ( ...=AFL_OP_OK)' by 'if (1)'.
-
-If you succeed, please mail me the exact version string of your drive and
-the code modifications, you have made together with a short explanation.
-If you don't succeed, you may mail me the output of the debugging messages.
-But remember, they are only useful, if they are exact and complete and you
-describe in detail your hardware setup and what you did (cold/warm reboot,
-with/without DOS, DOS-driver started/not started, which Linux-commands etc.)
-
-
-9. TECHNICAL HISTORY OF THE DRIVER
-The AZTECH-Driver is a rework of the Mitsumi-Driver. Four major items had to
-be reworked:
-
-a) The Mitsumi drive does issue complete status information acknowledging
-each command, the Aztech drive does only signal that the command was
-processed. So whenever the complete status information is needed, an extra
-ACMD_GET_STATUS command is issued. The handshake procedure for the drive
-can be found in the functions aztSendCmd(), sendAztCmd() and getAztStatus().
-
-b) The Aztech Drive does not have a ACMD_GET_DISK_INFO command, so the
-necessary info about the number of tracks (firstTrack, lastTrack), disk
-length etc. has to be read from the TOC in the lead in track (see function
-aztGetDiskInfo()).
-
-c) Whenever data is read from the drive, the Mitsumi drive is started with a
-command to read an indefinite (0xffffff) number of sectors. When the appropriate
-number of sectors is read, the drive is stopped by a ACDM_STOP command. This
-does not work with the Aztech drive. I did not find a way to stop it. The
-stop and pause commands do only work in AUDIO mode but not in DATA mode.
-Therefore I had to modify the 'finite state machine' in function azt_poll to
-only read a certain number of sectors and then start a new read on demand. As I
-have not completely understood, how the buffer/caching scheme of the Mitsumi
-driver was implemented, I am not sure, if I have covered all cases correctly,
-whenever you get timeout messages, the bug is most likely to be in that
-function azt_poll() around switch(cmd) .... case ACD_S_DATA.
-
-d) I did not get information about changing drive mode. So I doubt, that the
-code around function azt_poll() case AZT_S_MODE does work. In my test I have
-not been able to switch to reading in raw mode. For reading raw mode, Aztech
-uses a different command than for cooked mode, which I only have implemen-
-ted in the ioctl-section but not in the section which is used by the ISO9660.
-
-The driver was developed on an AST PC with Intel 486/DX2, 8MB RAM, 340MB IDE
-hard disk and on an AST PC with Intel Pentium 60MHz, 16MB RAM, 520MB IDE
-running Linux kernel version 1.0.9 from the LST 1.8 Distribution. The kernel
-was compiled with gcc.2.5.8. My CD-ROM drive is an Aztech CDA268-01A. My
-drive says, that it has Firmware Version AZT26801A1.3. It came with an ISA-bus
-interface card and works with polled I/O without DMA and without interrupts.
-The code for all other drives was 'remote' tested and debugged by a number of
-volunteers on the Internet.
-
-Points, where I feel that possible problems might be and all points where I
-did not completely understand the drive's behaviour or trust my own code are
-marked with /*???*/ in the source code. There are also some parts in the
-Mitsumi driver, where I did not completely understand their code.
-
-
-10. ACKNOWLEDGMENTS
-Without the help of P.Bush, Aztech, who delivered technical information
-about the Aztech Drive and without the help of E.Moenkeberg, GWDG, who did a
-great job in analyzing the command structure of various CD-ROM drives, this
-work would not have been possible. E.Moenkeberg was also a great help in
-making the software 'kernel ready' and in answering many of the CDROM-related
-questions in the newsgroups. He really is *the* Linux CD-ROM guru. Thanks
-also to all the guys on the Internet, who collected valuable technical
-information about CDROMs.
-
-Joe Nardone (joe@access.digex.net) was a patient tester even for my first
-trial, which was more than slow, and made suggestions for code improvement.
-Especially the 'finite state machine' azt_poll() was rewritten by Joe to get
-clean C code and avoid the ugly 'gotos', which I copied from mcd.c.
-
-Robby Schirmer (schirmer@fmi.uni-passau.de) tested the audio stuff (ioctls)
-and suggested a lot of patches for them.
-
-Joseph Piskor and Peter Nugent were the first users with the ORCHID CD3110
-and also were very patient with the problems which occurred.
-
-Reinhard Max delivered the information for the CDROM-interface of the
-SoundWave32 soundcards.
-
-Jochen Kunz and Olaf Kaluza delivered the information for supporting Conrad's
-TXC drive.
-
-Hilmar Berger delivered the patches for supporting CyCDROM CR520ie.
-
-Anybody, who is interested in these items should have a look at 'ftp.gwdg.de',
-directory 'pub/linux/cdrom' and at 'ftp.cdrom.com', directory 'pub/cdrom'.
-
-11. PROGRAMMING ADD ONs: cdplay.c
-You can use the ioctl-functions included in aztcd.c in your own programs. As
-an example on how to do this, you will find a tiny CD Player for audio CDs
-named 'cdplay.c'. It allows you to play audio CDs. You can play a specified
-track, pause and resume or skip tracks forward and backwards. If you quit the
-program without stopping the drive, playing is continued. You can also
-(mis)use cdplay to read and hexdump data disks. You can find the code in the
-APPENDIX of this file, which you should cut out with an editor and store in a
-separate file 'cdplay.c'. To compile it and make it executable, do
- gcc -s -Wall -O2 -L/usr/lib cdplay.c -o /usr/local/bin/cdplay # compiles it
- chmod +755 /usr/local/bin/cdplay # makes it executable
- ln -s /dev/aztcd0 /dev/cdrom # creates a link
- (for /usr/lib substitute the top level directory, where your include files
- reside, and for /usr/local/bin the directory, where you want the executable
- binary to reside )
-
-You have to set the correct permissions for cdplay *and* for /dev/mcd0 or
-/dev/aztcd0 in order to use it. Remember, that you should not have /dev/cdrom
-mounted, when you're playing audio CDs.
-
-This program is just a hack for testing the ioctl-functions in aztcd.c. I will
-not maintain it, so if you run into problems, discard it or have a look into
-the source code 'cdplay.c'. The program does only contain a minimum of user
-protection and input error detection. If you use the commands in the wrong
-order or if you try to read a CD at wrong addresses, you may get error messages
-or even hang your machine. If you get STEN_LOW, STEN_LOW_WAIT or segment violation
-error messages when using cdplay, after that, the system might not be stable
-any more, so you'd better reboot. As the ioctl-functions run in kernel mode,
-most normal Linux-multitasking protection features do not work. By using
-uninitialized 'wild' pointers etc., it is easy to write to other users' data
-and program areas, destroy kernel tables etc.. So if you experiment with ioctls
-as always when you are doing systems programming and kernel hacking, you
-should have a backup copy of your system in a safe place (and you also
-should try restoring from a backup copy first)!
-
-A reworked and improved version called 'cdtester.c', which has yet more
-features for testing CDROM-drives can be found in
-Documentation/cdrom/sbpcd, written by E.Moenkeberg.
-
-Werner Zimmermann
-Fachhochschule fuer Technik Esslingen
-(EMail: Werner.Zimmermann@fht-esslingen.de)
-October, 1997
-
----------------------------------------------------------------------------
-APPENDIX: Source code of cdplay.c
-
-/* Tiny Audio CD Player
-
- Copyright 1994, 1995, 1996 Werner Zimmermann (Werner.Zimmermann@fht-esslingen.de)
-
-This program originally was written to test the audio functions of the
-AZTECH.CDROM-driver, but it should work with every CD-ROM drive. Before
-using it, you should set a symlink from /dev/cdrom to your real CDROM
-device.
-
-The GNU General Public License applies to this program.
-
-History: V0.1 W.Zimmermann: First release. Nov. 8, 1994
- V0.2 W.Zimmermann: Enhanced functionality. Nov. 9, 1994
- V0.3 W.Zimmermann: Additional functions. Nov. 28, 1994
- V0.4 W.Zimmermann: fixed some bugs. Dec. 17, 1994
- V0.5 W.Zimmermann: clean 'scanf' commands without compiler warnings
- Jan. 6, 1995
- V0.6 W.Zimmermann: volume control (still experimental). Jan. 24, 1995
- V0.7 W.Zimmermann: read raw modified. July 26, 95
-*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <linux/cdrom.h>
-#include <linux/../../drivers/cdrom/aztcd.h>
-
-void help(void)
-{ printf("Available Commands: STOP s EJECT/CLOSE e QUIT q\n");
- printf(" PLAY TRACK t PAUSE p RESUME r\n");
- printf(" NEXT TRACK n REPEAT LAST l HELP h\n");
- printf(" SUB CHANNEL c TRACK INFO i PLAY AT a\n");
- printf(" READ d READ RAW w VOLUME v\n");
-}
-
-int main(void)
-{ int handle;
- unsigned char command=' ', ini=0, first=1, last=1;
- unsigned int cmd, i,j,k, arg1,arg2,arg3;
- struct cdrom_ti ti;
- struct cdrom_tochdr tocHdr;
- struct cdrom_subchnl subchnl;
- struct cdrom_tocentry entry;
- struct cdrom_msf msf;
- union { struct cdrom_msf msf;
- unsigned char buf[CD_FRAMESIZE_RAW];
- } azt;
- struct cdrom_volctrl volctrl;
-
- printf("\nMini-Audio CD-Player V0.72 (C) 1994,1995,1996 W.Zimmermann\n");
- handle=open("/dev/cdrom",O_RDWR);
- ioctl(handle,CDROMRESUME);
-
- if (handle<=0)
- { printf("Drive Error: already playing, no audio disk, door open\n");
- printf(" or no permission (you must be ROOT in order to use this program)\n");
- }
- else
- { help();
- while (1)
- { printf("Type command (h = help): ");
- scanf("%s",&command);
- switch (command)
- { case 'e': cmd=CDROMEJECT;
- ioctl(handle,cmd);
- break;
- case 'p': if (!ini)
- { printf("Command not allowed - play track first\n");
- }
- else
- { cmd=CDROMPAUSE;
- if (ioctl(handle,cmd)) printf("Drive Error\n");
- }
- break;
- case 'r': if (!ini)
- { printf("Command not allowed - play track first\n");
- }
- else
- { cmd=CDROMRESUME;
- if (ioctl(handle,cmd)) printf("Drive Error\n");
- }
- break;
- case 's': cmd=CDROMPAUSE;
- if (ioctl(handle,cmd)) printf("Drive error or already stopped\n");
- cmd=CDROMSTOP;
- if (ioctl(handle,cmd)) printf("Drive error\n");
- break;
- case 't': cmd=CDROMREADTOCHDR;
- if (ioctl(handle,cmd,&tocHdr)) printf("Drive Error\n");
- first=tocHdr.cdth_trk0;
- last= tocHdr.cdth_trk1;
- if ((first==0)||(first>last))
- { printf ("--could not read TOC\n");
- }
- else
- { printf("--first track: %d --last track: %d --enter track number: ",first,last);
- cmd=CDROMPLAYTRKIND;
- scanf("%i",&arg1);
- ti.cdti_trk0=arg1;
- if (ti.cdti_trk0<first) ti.cdti_trk0=first;
- if (ti.cdti_trk0>last) ti.cdti_trk0=last;
- ti.cdti_ind0=0;
- ti.cdti_trk1=last;
- ti.cdti_ind1=0;
- if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
- ini=1;
- }
- break;
- case 'n': if (!ini++)
- { if (ioctl(handle,CDROMREADTOCHDR,&tocHdr)) printf("Drive Error\n");
- first=tocHdr.cdth_trk0;
- last= tocHdr.cdth_trk1;
- ti.cdti_trk0=first-1;
- }
- if ((first==0)||(first>last))
- { printf ("--could not read TOC\n");
- }
- else
- { cmd=CDROMPLAYTRKIND;
- if (++ti.cdti_trk0 > last) ti.cdti_trk0=last;
- ti.cdti_ind0=0;
- ti.cdti_trk1=last;
- ti.cdti_ind1=0;
- if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
- ini=1;
- }
- break;
- case 'l': if (!ini++)
- { if (ioctl(handle,CDROMREADTOCHDR,&tocHdr)) printf("Drive Error\n");
- first=tocHdr.cdth_trk0;
- last= tocHdr.cdth_trk1;
- ti.cdti_trk0=first+1;
- }
- if ((first==0)||(first>last))
- { printf ("--could not read TOC\n");
- }
- else
- { cmd=CDROMPLAYTRKIND;
- if (--ti.cdti_trk0 < first) ti.cdti_trk0=first;
- ti.cdti_ind0=0;
- ti.cdti_trk1=last;
- ti.cdti_ind1=0;
- if (ioctl(handle,cmd,&ti)) printf("Drive Error\n");
- ini=1;
- }
- break;
- case 'c': subchnl.cdsc_format=CDROM_MSF;
- if (ioctl(handle,CDROMSUBCHNL,&subchnl))
- printf("Drive Error\n");
- else
- { printf("AudioStatus:%s Track:%d Mode:%d MSF=%d:%d:%d\n", \
- subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING",\
- subchnl.cdsc_trk,subchnl.cdsc_adr, \
- subchnl.cdsc_absaddr.msf.minute, subchnl.cdsc_absaddr.msf.second, \
- subchnl.cdsc_absaddr.msf.frame);
- }
- break;
- case 'i': if (!ini)
- { printf("Command not allowed - play track first\n");
- }
- else
- { cmd=CDROMREADTOCENTRY;
- printf("Track No.: ");
- scanf("%d",&arg1);
- entry.cdte_track=arg1;
- if (entry.cdte_track<first) entry.cdte_track=first;
- if (entry.cdte_track>last) entry.cdte_track=last;
- entry.cdte_format=CDROM_MSF;
- if (ioctl(handle,cmd,&entry))
- { printf("Drive error or invalid track no.\n");
- }
- else
- { printf("Mode %d Track, starts at %d:%d:%d\n", \
- entry.cdte_adr,entry.cdte_addr.msf.minute, \
- entry.cdte_addr.msf.second,entry.cdte_addr.msf.frame);
- }
- }
- break;
- case 'a': cmd=CDROMPLAYMSF;
- printf("Address (min:sec:frame) ");
- scanf("%d:%d:%d",&arg1,&arg2,&arg3);
- msf.cdmsf_min0 =arg1;
- msf.cdmsf_sec0 =arg2;
- msf.cdmsf_frame0=arg3;
- if (msf.cdmsf_sec0 > 59) msf.cdmsf_sec0 =59;
- if (msf.cdmsf_frame0> 74) msf.cdmsf_frame0=74;
- msf.cdmsf_min1=60;
- msf.cdmsf_sec1=00;
- msf.cdmsf_frame1=00;
- if (ioctl(handle,cmd,&msf))
- { printf("Drive error or invalid address\n");
- }
- break;
-#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
- case 'd': cmd=CDROMREADCOOKED;
- printf("Address (min:sec:frame) ");
- scanf("%d:%d:%d",&arg1,&arg2,&arg3);
- azt.msf.cdmsf_min0 =arg1;
- azt.msf.cdmsf_sec0 =arg2;
- azt.msf.cdmsf_frame0=arg3;
- if (azt.msf.cdmsf_sec0 > 59) azt.msf.cdmsf_sec0 =59;
- if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
- if (ioctl(handle,cmd,&azt.msf))
- { printf("Drive error, invalid address or unsupported command\n");
- }
- k=0;
- getchar();
- for (i=0;i<128;i++)
- { printf("%4d:",i*16);
- for (j=0;j<16;j++)
- { printf("%2x ",azt.buf[i*16+j]);
- }
- for (j=0;j<16;j++)
- { if (isalnum(azt.buf[i*16+j]))
- printf("%c",azt.buf[i*16+j]);
- else
- printf(".");
- }
- printf("\n");
- k++;
- if (k>=20)
- { printf("press ENTER to continue\n");
- getchar();
- k=0;
- }
- }
- break;
- case 'w': cmd=CDROMREADRAW;
- printf("Address (min:sec:frame) ");
- scanf("%d:%d:%d",&arg1,&arg2,&arg3);
- azt.msf.cdmsf_min0 =arg1;
- azt.msf.cdmsf_sec0 =arg2;
- azt.msf.cdmsf_frame0=arg3;
- if (azt.msf.cdmsf_sec0 > 59) azt.msf.cdmsf_sec0 =59;
- if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74;
- if (ioctl(handle,cmd,&azt))
- { printf("Drive error, invalid address or unsupported command\n");
- }
- k=0;
- for (i=0;i<147;i++)
- { printf("%4d:",i*16);
- for (j=0;j<16;j++)
- { printf("%2x ",azt.buf[i*16+j]);
- }
- for (j=0;j<16;j++)
- { if (isalnum(azt.buf[i*16+j]))
- printf("%c",azt.buf[i*16+j]);
- else
- printf(".");
- }
- printf("\n");
- k++;
- if (k>=20)
- { getchar();
- k=0;
- }
- }
- break;
-#endif
- case 'v': cmd=CDROMVOLCTRL;
- printf("--Channel 0 Left (0-255): ");
- scanf("%d",&arg1);
- printf("--Channel 1 Right (0-255): ");
- scanf("%d",&arg2);
- volctrl.channel0=arg1;
- volctrl.channel1=arg2;
- volctrl.channel2=0;
- volctrl.channel3=0;
- if (ioctl(handle,cmd,&volctrl))
- { printf("Drive error or unsupported command\n");
- }
- break;
- case 'q': if (close(handle)) printf("Drive Error: CLOSE\n");
- exit(0);
- case 'h': help();
- break;
- default: printf("unknown command\n");
- break;
- }
- }
- }
- return 0;
-}
diff --git a/Documentation/cdrom/cdu31a b/Documentation/cdrom/cdu31a
deleted file mode 100644
index c0667da09c00..000000000000
--- a/Documentation/cdrom/cdu31a
+++ /dev/null
@@ -1,196 +0,0 @@
-
- CDU31A/CDU33A Driver Info
- -------------------------
-
-Information on the Sony CDU31A/CDU33A CDROM driver for the Linux
-kernel.
-
- Corey Minyard (minyard@metronet.com)
-
- Colossians 3:17
-
-Crude Table of Contents
------------------------
-
- Setting Up the Hardware
- Configuring the Kernel
- Configuring as a Module
- Driver Special Features
-
-
-This device driver handles Sony CDU31A/CDU33A CDROM drives and
-provides a complete block-level interface as well as an ioctl()
-interface as specified in include/linux/cdrom.h). With this
-interface, CDROMs can be accessed, standard audio CDs can be played
-back normally, and CD audio information can be read off the drive.
-
-Note that this will only work for CDU31A/CDU33A drives. Some vendors
-market their drives as CDU31A compatible. They lie. Their drives are
-really CDU31A hardware interface compatible (they can plug into the
-same card). They are not software compatible.
-
-Setting Up the Hardware
------------------------
-
-The CDU31A driver is unable to safely tell if an interface card is
-present that it can use because the interface card does not announce
-its presence in any way besides placing 4 I/O locations in memory. It
-used to just probe memory and attempt commands, but Linus wisely asked
-me to remove that because it could really screw up other hardware in
-the system.
-
-Because of this, you must tell the kernel where the drive interface
-is, what interrupts are used, and possibly if you are on a PAS-16
-soundcard.
-
-If you have the Sony CDU31A/CDU33A drive interface card, the following
-diagram will help you set it up. If you have another card, you are on
-your own. You need to make sure that the I/O address and interrupt is
-not used by another card in the system. You will need to know the I/O
-address and interrupt you have set. Note that use of interrupts is
-highly recommended, if possible, it really cuts down on CPU used.
-Unfortunately, most soundcards do not support interrupts for their
-CDROM interfaces. By default, the Sony interface card comes with
-interrupts disabled.
-
- +----------+-----------------+----------------------+
- | JP1 | 34 Pin Conn | |
- | JP2 +-----------------+ |
- | JP3 |
- | JP4 |
- | +--+
- | | +-+
- | | | | External
- | | | | Connector
- | | | |
- | | +-+
- | +--+
- | |
- | +--------+
- | |
- +------------------------------------------+
-
- JP1 sets the Base Address, using the following settings:
-
- Address Pin 1 Pin 2
- ------- ----- -----
- 0x320 Short Short
- 0x330 Short Open
- 0x340 Open Short
- 0x360 Open Open
-
- JP2 and JP3 configure the DMA channel; they must be set the same.
-
- DMA Pin 1 Pin 2 Pin 3
- --- ----- ----- -----
- 1 On Off On
- 2 Off On Off
- 3 Off Off On
-
- JP4 Configures the IRQ:
-
- IRQ Pin 1 Pin 2 Pin 3 Pin 4
- --- ----- ----- ----- -----
- 3 Off Off On Off
- 4 Off Off* Off On
- 5 On Off Off Off
- 6 Off On Off Off
-
- The documentation states to set this for interrupt
- 4, but I think that is a mistake.
-
-Note that if you have another interface card, you will need to look at
-the documentation to find the I/O base address. This is specified to
-the SLCD.SYS driver for DOS with the /B: parameter, so you can look at
-you DOS driver setup to find the address, if necessary.
-
-Configuring the Kernel
-----------------------
-
-You must tell the kernel where the drive is at boot time. This can be
-done at the Linux boot prompt, by using LILO, or by using Bootlin.
-Note that this is no substitute for HOWTOs and LILO documentation, if
-you are confused please read those for info on bootline configuration
-and LILO.
-
-At the linux boot prompt, press the ALT key and add the following line
-after the boot name (you can let the kernel boot, it will tell you the
-default boot name while booting):
-
- cdu31a=<base address>,<interrupt>[,PAS]
-
-The base address needs to have "0x" in front of it, since it is in
-hex. For instance, to configure a drive at address 320 on interrupt 5,
-use the following:
-
- cdu31a=0x320,5
-
-I use the following boot line:
-
- cdu31a=0x1f88,0,PAS
-
-because I have a PAS-16 which does not support interrupt for the
-CDU31A interface.
-
-Adding this as an append line at the beginning of the /etc/lilo.conf
-file will set it for lilo configurations. I have the following as the
-first line in my lilo.conf file:
-
- append="cdu31a=0x1f88,0"
-
-I'm not sure how to set up Bootlin (I have never used it), if someone
-would like to fill in this section please do.
-
-
-Configuring as a Module
------------------------
-
-The driver supports loading as a module. However, you must specify
-the boot address and interrupt on the boot line to insmod. You can't
-use modprobe to load it, since modprobe doesn't support setting
-variables.
-
-Anyway, I use the following line to load my driver as a module
-
- /sbin/insmod /lib/modules/`uname -r`/misc/cdu31a.o cdu31a_port=0x1f88
-
-You can set the following variables in the driver:
-
- cdu31a_port=<I/O address> - sets the base I/O. If hex, put 0x in
- front of it. This must be specified.
-
- cdu31a_irq=<interrupt> - Sets the interrupt number. Leaving this
- off will turn interrupts off.
-
-
-Driver Special Features
------------------------
-
-This section describes features beyond the normal audio and CD-ROM
-functions of the drive.
-
-2048 byte buffer mode
-
-If a disk is mounted with -o block=2048, data is copied straight from
-the drive data port to the buffer. Otherwise, the readahead buffer
-must be involved to hold the other 1K of data when a 1K block
-operation is done. Note that with 2048 byte blocks you cannot execute
-files from the CD.
-
-XA compatibility
-
-The driver should support XA disks for both the CDU31A and CDU33A. It
-does this transparently, the using program doesn't need to set it.
-
-Multi-Session
-
-A multi-session disk looks just like a normal disk to the user. Just
-mount one normally, and all the data should be there. A special
-thanks to Koen for help with this!
-
-Raw sector I/O
-
-Using the CDROMREADAUDIO it is possible to read raw audio and data
-tracks. Both operations return 2352 bytes per sector. On the data
-tracks, the first 12 bytes is not returned by the drive and the value
-of that data is indeterminate.
diff --git a/Documentation/cdrom/cm206 b/Documentation/cdrom/cm206
deleted file mode 100644
index 810368f4f7c4..000000000000
--- a/Documentation/cdrom/cm206
+++ /dev/null
@@ -1,185 +0,0 @@
-This is the readme file for the driver for the Philips/LMS cdrom drive
-cm206 in combination with the cm260 host adapter card.
-
- (c) 1995 David A. van Leeuwen
-
-Changes since version 0.99
---------------------------
-- Interfacing to the kernel is routed though an extra interface layer,
- cdrom.c. This allows runtime-configurable `behavior' of the cdrom-drive,
- independent of the driver.
-
-Features since version 0.33
----------------------------
-- Full audio support, that is, both workman, workbone and cdp work
- now reasonably. Reading TOC still takes some time. xmcd has been
- reported to run successfully.
-- Made auto-probe code a little better, I hope
-
-Features since version 0.28
----------------------------
-- Full speed transfer rate (300 kB/s).
-- Minimum kernel memory usage for buffering (less than 3 kB).
-- Multisession support.
-- Tray locking.
-- Statistics of driver accessible to the user.
-- Module support.
-- Auto-probing of adapter card's base port and irq line,
- also configurable at boot time or module load time.
-
-
-Decide how you are going to use the driver. There are two
-options:
-
- (a) installing the driver as a resident part of the kernel
- (b) compiling the driver as a loadable module
-
- Further, you must decide if you are going to specify the base port
- address and the interrupt request line of the adapter card cm260 as
- boot options for (a), module parameters for (b), use automatic
- probing of these values, or hard-wire your adaptor card's settings
- into the source code. If you don't care, you can choose
- autoprobing, which is the default. In that case you can move on to
- the next step.
-
-Compiling the kernel
---------------------
-1) move to /usr/src/linux and do a
-
- make config
-
- If you have chosen option (a), answer yes to CONFIG_CM206 and
- CONFIG_ISO9660_FS.
-
- If you have chosen option (b), answer yes to CONFIG_MODVERSIONS
- and no (!) to CONFIG_CM206 and CONFIG_ISO9660_FS.
-
-2) then do a
-
- make clean; make zImage; make modules
-
-3) do the usual things to install a new image (backup the old one, run
- `rdev -R zImage 1', copy the new image in place, run lilo). Might
- be `make zlilo'.
-
-Using the driver as a module
-----------------------------
-If you will only occasionally use the cd-rom driver, you can choose
-option (b), install as a loadable module. You may have to re-compile
-the module when you upgrade the kernel to a new version.
-
-Since version 0.96, much of the functionality has been transferred to
-a generic cdrom interface in the file cdrom.c. The module cm206.o
-depends on cdrom.o. If the latter is not compiled into the kernel,
-you must explicitly load it before cm206.o:
-
- insmod /usr/src/linux/modules/cdrom.o
-
-To install the module, you use the command, as root
-
- insmod /usr/src/linux/modules/cm206.o
-
-You can specify the base address on the command line as well as the irq
-line to be used, e.g.
-
- insmod /usr/src/linux/modules/cm206.o cm206=0x300,11
-
-The order of base port and irq line doesn't matter; if you specify only
-one, the other will have the value of the compiled-in default. You
-may also have to install the file-system module `iso9660.o', if you
-didn't compile that into the kernel.
-
-
-Using the driver as part of the kernel
---------------------------------------
-If you have chosen option (a), you can specify the base-port
-address and irq on the lilo boot command line, e.g.:
-
- LILO: linux cm206=0x340,11
-
-This assumes that your linux kernel image keyword is `linux'.
-If you specify either IRQ (3--11) or base port (0x300--0x370),
-auto probing is turned off for both settings, thus setting the
-other value to the compiled-in default.
-
-Note that you can also put these parameters in the lilo configuration file:
-
-# linux config
-image = /vmlinuz
- root = /dev/hda1
- label = Linux
- append = "cm206=0x340,11"
- read-only
-
-
-If module parameters and LILO config options don't work
--------------------------------------------------------
-If autoprobing does not work, you can hard-wire the default values
-of the base port address (CM206_BASE) and interrupt request line
-(CM206_IRQ) into the file /usr/src/linux/drivers/cdrom/cm206.h. Change
-the defines of CM206_IRQ and CM206_BASE.
-
-
-Mounting the cdrom
-------------------
-1) Make sure that the right device is installed in /dev.
-
- mknod /dev/cm206cd b 32 0
-
-2) Make sure there is a mount point, e.g., /cdrom
-
- mkdir /cdrom
-
-3) mount using a command like this (run as root):
-
- mount -rt iso9660 /dev/cm206cd /cdrom
-
-4) For user-mounts, add a line in /etc/fstab
-
- /dev/cm206cd /cdrom iso9660 ro,noauto,user
-
- This will allow users to give the commands
-
- mount /cdrom
- umount /cdrom
-
-If things don't work
---------------------
-
-- Try to do a `dmesg' to find out if the driver said anything about
- what is going wrong during the initialization.
-
-- Try to do a `dd if=/dev/cm206cd | od -tc | less' to read from the
- CD.
-
-- Look in the /proc directory to see if `cm206' shows up under one of
- `interrupts', `ioports', `devices' or `modules' (if applicable).
-
-
-DISCLAIMER
-----------
-I cannot guarantee that this driver works, or that the hardware will
-not be harmed, although I consider it most unlikely.
-
-I hope that you'll find this driver in some way useful.
-
- David van Leeuwen
- david@tm.tno.nl
-
-Note for Linux CDROM vendors
------------------------------
-You are encouraged to include this driver on your Linux CDROM. If
-you do, you might consider sending me a free copy of that cd-rom.
-You can contact me through my e-mail address, david@tm.tno.nl.
-If this driver is compiled into a kernel to boot off a cdrom,
-you should actually send me a free copy of that cd-rom.
-
-Copyright
----------
-The copyright of the cm206 driver for Linux is
-
- (c) 1995 David A. van Leeuwen
-
-The driver is released under the conditions of the GNU general public
-license, which can be found in the file COPYING in the root of this
-source tree.
diff --git a/Documentation/cdrom/gscd b/Documentation/cdrom/gscd
deleted file mode 100644
index d01ca36b5c43..000000000000
--- a/Documentation/cdrom/gscd
+++ /dev/null
@@ -1,60 +0,0 @@
- Goldstar R420 CD-Rom device driver README
-
-For all kind of other information about the GoldStar R420 CDROM
-and this Linux device driver see the WWW page:
-
- http://linux.rz.fh-hannover.de/~raupach
-
-
- If you are the editor of a Linux CD, you should
- enable gscd.c within your boot floppy kernel. Please,
- send me one of your CDs for free.
-
-
-This current driver version 0.4a only supports reading data from the disk.
-Currently we have no audio and no multisession or XA support.
-The polling interface is used, no DMA.
-
-
-Sometimes the GoldStar R420 is sold in a 'Reveal Multimedia Kit'. This kit's
-drive interface is compatible, too.
-
-
-Installation
-------------
-
-Change to '/usr/src/linux/drivers/cdrom' and edit the file 'gscd.h'. Insert
-the i/o address of your interface card.
-
-The default base address is 0x340. This will work for most applications.
-Address selection is accomplished by jumpers PN801-1 to PN801-4 on the
-GoldStar Interface Card.
-Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
-0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0
-
-Then go back to '/usr/src/linux/' and 'make config' to build the new
-configuration for your kernel. If you want to use the GoldStar driver
-like a module, don't select 'GoldStar CDROM support'. By the way, you
-have to include the iso9660 filesystem.
-
-Now start compiling the kernel with 'make zImage'.
-If you want to use the driver as a module, you have to do 'make modules'
-and 'make modules_install', additionally.
-Install your new kernel as usual - maybe you do it with 'make zlilo'.
-
-Before you can use the driver, you have to
- mknod /dev/gscd0 b 16 0
-to create the appropriate device file (you only need to do this once).
-
-If you use modules, you can try to insert the driver.
-Say: 'insmod /usr/src/linux/modules/gscd.o'
-or: 'insmod /usr/src/linux/modules/gscd.o gscd=<address>'
-The driver should report its results.
-
-That's it! Mount a disk, i.e. 'mount -rt iso9660 /dev/gscd0 /cdrom'
-
-Feel free to report errors and suggestions to the following address.
-Be sure, I'm very happy to receive your comments!
-
- Oliver Raupach Hannover, Juni 1995
-(raupach@nwfs1.rz.fh-hannover.de)
diff --git a/Documentation/cdrom/isp16 b/Documentation/cdrom/isp16
deleted file mode 100644
index cc86533ac9f3..000000000000
--- a/Documentation/cdrom/isp16
+++ /dev/null
@@ -1,100 +0,0 @@
- -- Documentation/cdrom/isp16
-
-Docs by Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
-
-This is the README for version 0.6 of the cdrom interface on an
-ISP16, MAD16 or Mozart sound card.
-
-The detection and configuration of this interface used to be included
-in both the sjcd and optcd cdrom driver. Drives supported by these
-drivers came packed with Media Magic's multi media kit, which also
-included the ISP16 card. The idea (thanks Leo Spiekman)
-to move it from these drivers into a separate module and moreover, not to
-rely on the MAD16 sound driver, are as follows:
--duplication of code in the kernel is a waste of resources and should
- be avoided;
--however, kernels and notably those included with Linux distributions
- (cf Slackware 3.0 included version 0.5 of the isp16 configuration
- code included in the drivers) don't always come with sound support
- included. Especially when they already include a bunch of cdrom drivers.
- Hence, the cdrom interface should be configurable _independently_ of
- sound support.
-
-The ISP16, MAD16 and Mozart sound cards have an OPTi 82C928 or an
-OPTi 82C929 chip. The interface on these cards should work with
-any cdrom attached to the card, which is 'electrically' compatible
-with Sanyo/Panasonic, Sony or Mitsumi non-ide drives. However, the
-command sets for any proprietary drives may differ
-(and hence may not be supported in the kernel) from these four types.
-For a fact I know the interface works and the way of configuration
-as described in this documentation works in combination with the
-sjcd (in Sanyo/Panasonic compatibility mode) cdrom drivers
-(probably with the optcd (in Sony compatibility mode) as well).
-If you have such an OPTi based sound card and you want to use the
-cdrom interface with a cdrom drive supported by any of the other cdrom
-drivers, it will probably work. Please let me know any experience you
-might have).
-I understand that cards based on the OPTi 82C929 chips may be configured
-(hardware jumpers that is) as an IDE interface. Initialisation of such a
-card in this mode is not supported (yet?).
-
-The suggestion to configure the ISP16 etc. sound card by booting DOS and
-do a warm reboot to boot Linux somehow doesn't work, at least not
-on my machine (IPC P90), with the OPTi 82C928 based card.
-
-Booting the kernel through the boot manager LILO allows the use
-of some command line options on the 'LILO boot:' prompt. At boot time
-press Alt or Shift while the LILO prompt is written on the screen and enter
-any kernel options. Alternatively these options may be used in
-the appropriate section in /etc/lilo.conf. Adding 'append="<cmd_line_options>"'
-will do the trick as well.
-The syntax of 'cmd_line_options' is
-
- isp16=[<port>[,<irq>[,<dma>]]][[,]<drive_type>]
-
-If there is no ISP16 or compatibles detected, there's probably no harm done.
-These options indicate the values that your cdrom drive has been (or will be)
-configured to use.
-Valid values for the base i/o address are:
- port=0x340,0x320,0x330,0x360
-for the interrupt request number
- irq=0,3,5,7,9,10,11
-for the direct memory access line
- dma=0,3,5,6,7
-and for the type of drive
- drive_type=noisp16,Sanyo,Panasonic,Sony,Mitsumi.
-Note that these options are case sensitive.
-The values 0 for irq and dma indicate that they are not used, and
-the drive will be used in 'polling' mode. The values 5 and 7 for irq
-should be avoided in order to avoid any conflicts with optional
-sound card configuration.
-The syntax of the command line does not allow the specification of
-irq when there's nothing specified for the base address and no
-specification of dma when there is no specification of irq.
-The value 'noisp16' for drive_type, which may be used as the first
-non-integer option value (e.g. 'isp16=noisp16'), makes sure that probing
-for and subsequent configuration of an ISP16-compatible card is skipped
-all together. This can be useful to overcome possible conflicts which
-may arise while the kernel is probing your hardware.
-The default values are
- port=0x340
- irq=0
- dma=0
- drive_type=Sanyo
-reflecting my own configuration. The defaults can be changed in
-the file linux/drivers/cdrom/ips16.h.
-
-The cdrom interface can be configured at run time by loading the
-initialisation driver as a module. In that case, the interface
-parameters can be set by giving appropriate values on the command
-line. Configuring the driver can then be done by the following
-command (assuming you have iso16.o installed in a proper place):
-
- insmod isp16.o isp16_cdrom_base=<port> isp16_cdrom_irq=<irq> \
- isp16_cdrom_dma=<dma> isp16_cdrom_type=<drive_type>
-
-where port, irq, dma and drive_type can have any of the values mentioned
-above.
-
-
-Have fun!
diff --git a/Documentation/cdrom/mcdx b/Documentation/cdrom/mcdx
deleted file mode 100644
index 2bac4b7ff6da..000000000000
--- a/Documentation/cdrom/mcdx
+++ /dev/null
@@ -1,29 +0,0 @@
-If you are using the driver as a module, you can specify your ports and IRQs
-like
-
- # insmod mcdx.o mcdx=0x300,11,0x304,5
-
-and so on ("address,IRQ" pairs).
-This will override the configuration in mcdx.h.
-
-This driver:
-
- o handles XA and (hopefully) multi session CDs as well as
- ordinary CDs;
- o supports up to 5 drives (of course, you'll need free
- IRQs, i/o ports and slots);
- o plays audio
-
-This version doesn't support yet:
-
- o shared IRQs (but it seems to be possible - I've successfully
- connected two drives to the same irq. So it's `only' a
- problem of the driver.)
-
-This driver never will:
-
- o Read digital audio (i.e. copy directly), due to missing
- hardware features.
-
-
-heiko@lotte.sax.de
diff --git a/Documentation/cdrom/optcd b/Documentation/cdrom/optcd
deleted file mode 100644
index 6f46c7adb243..000000000000
--- a/Documentation/cdrom/optcd
+++ /dev/null
@@ -1,57 +0,0 @@
-This is the README file for the Optics Storage 8000 AT CDROM device driver.
-
-This is the driver for the so-called 'DOLPHIN' drive, with the 34-pin
-Sony-compatible interface. For the IDE-compatible Optics Storage 8001
-drive, you will want the ATAPI CDROM driver. The driver also seems to
-work with the Lasermate CR328A. If you have a drive that works with
-this driver, and that doesn't report itself as DOLPHIN, please drop me
-a mail.
-
-The support for multisession CDs is in ALPHA stage. If you use it,
-please mail me your experiences. Multisession support can be disabled
-at compile time.
-
-You can find some older versions of the driver at
- dutette.et.tudelft.nl:/pub/linux/
-and at Eberhard's mirror
- ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/
-
-Before you can use the driver, you have to create the device file once:
- # mknod /dev/optcd0 b 17 0
-
-To specify the base address if the driver is "compiled-in" to your kernel,
-you can use the kernel command line item (LILO option)
- optcd=0x340
-with the right address.
-
-If you have compiled optcd as a module, you can load it with
- # insmod /usr/src/linux/modules/optcd.o
-or
- # insmod /usr/src/linux/modules/optcd.o optcd=0x340
-with the matching address value of your interface card.
-
-The driver employs a number of buffers to do read-ahead and block size
-conversion. The number of buffers is configurable in optcd.h, and has
-influence on the driver performance. For my machine (a P75), 6 buffers
-seems optimal, as can be seen from this table:
-
-#bufs kb/s %cpu
-1 97 0.1
-2 191 0.3
-3 188 0.2
-4 246 0.3
-5 189 19
-6 280 0.4
-7 281 7.0
-8 246 2.8
-16 281 3.4
-
-If you get a throughput significantly below 300 kb/s, try tweaking
-N_BUFS, and don't forget to mail me your results!
-
-I'd appreciate success/failure reports. If you find a bug, try
-recompiling the driver with some strategically chosen debug options
-(these can be found in optcd.h) and include the messages generated in
-your bug report. Good luck.
-
-Leo Spiekman (spiekman@dutette.et.tudelft.nl)
diff --git a/Documentation/cdrom/sbpcd b/Documentation/cdrom/sbpcd
deleted file mode 100644
index b3ba63f4ce3e..000000000000
--- a/Documentation/cdrom/sbpcd
+++ /dev/null
@@ -1,1061 +0,0 @@
-This README belongs to release 4.2 or newer of the SoundBlaster Pro
-(Matsushita, Kotobuki, Panasonic, CreativeLabs, Longshine and Teac)
-CD-ROM driver for Linux.
-
-sbpcd really, really is NOT for ANY IDE/ATAPI drive!
-Not even if you have an "original" SoundBlaster card with an IDE interface!
-So, you'd better have a look into README.ide if your port address is 0x1F0,
-0x170, 0x1E8, 0x168 or similar.
-I get tons of mails from IDE/ATAPI drive users - I really can't continue
-any more to answer them all. So, if your drive/interface information sheets
-mention "IDE" (primary, secondary, tertiary, quaternary) and the DOS driver
-invoking line within your CONFIG.SYS is using an address below 0x230:
-DON'T ROB MY LAST NERVE - jumper your interface to address 0x170 and IRQ 15
-(that is the "secondary IDE" configuration), set your drive to "master" and
-use ide-cd as your driver. If you do not have a second IDE hard disk, use the
-LILO commands
- hdb=noprobe hdc=cdrom
-and get lucky.
-To make it fully clear to you: if you mail me about IDE/ATAPI drive problems,
-my answer is above, and I simply will discard your mail, hoping to stop the
-flood and to find time to lead my 12-year old son towards happy computing.
-
-The driver is able to drive the whole family of "traditional" AT-style (that
-is NOT the new "Enhanced IDE" or "ATAPI" drive standard) Matsushita,
-Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
-well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
-CR-574 is an IDE/ATAPI drive.
-
-The Longshine LCS-7260 is a double-speed drive which uses the "old"
-Matsushita command set. It is supported - with help by Serge Robyns.
-Vertos ("Elitegroup Computer Systems", ECS) has a similar drive - support
-has started; get in contact if you have such a "Vertos 100" or "ECS-AT"
-drive.
-
-There exists an "IBM External ISA CD-ROM Drive" which in fact is a CR-563
-with a special controller board. This drive is supported (the interface is
-of the "LaserMate" type), and it is possibly the best buy today (cheaper than
-an internal drive, and you can use it as an internal, too - e.g. plug it into
-a soundcard).
-
-CreativeLabs has a new drive "CD200" and a similar drive "CD200F". The latter
-is made by Funai and sometimes named "E2550UA", newer models may be named
-"MK4015". The CD200F drives should fully work.
-CD200 drives without "F" are still giving problems: drive detection and
-playing audio should work, data access will result in errors. I need qualified
-feedback about the bugs within the data functions or a drive (I never saw a
-CD200).
-
-The quad-speed Teac CD-55A drive is supported, but still does not reach "full
-speed". The data rate already reaches 500 kB/sec if you set SBP_BUFFER_FRAMES
-to 64 (it is not recommended to do that for normal "file access" usage, but it
-can speed up things a lot if you use something like "dd" to read from the
-drive; I use it for verifying self-written CDs this way).
-The drive itself is able to deliver 600 kB/sec, so this needs
-work; with the normal setup, the performance currently is not even as good as
-double-speed.
-
-This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives,
-and again: this driver is in no way usable for any IDE/ATAPI drive. If you
-think your drive should work and it doesn't: send me the DOS driver for your
-beast (gzipped + uuencoded) and your CONFIG.SYS if you want to ask me for help,
-and include an original log message excerpt, and try to give all information
-a complete idiot needs to understand your hassle already with your first
-mail. And if you want to say "as I have mailed you before", be sure that I
-don't remember your "case" by such remarks; at the moment, I have some
-hundreds of open correspondences about Linux CDROM questions (hope to reduce if
-the IDE/ATAPI user questions disappear).
-
-
-This driver will work with the soundcard interfaces (SB Pro, SB 16, Galaxy,
-SoundFX, Mozart, MAD16 ...) and with the "no-sound" cards (Panasonic CI-101P,
-LaserMate, WDH-7001C, Longshine LCS-6853, Teac ...).
-
-It works with the "configurable" interface "Sequoia S-1000", too, which is
-used on the Spea Media FX and Ensonic Soundscape sound cards. You have to
-specify the type "SBPRO 2" and the true CDROM port address with it, not the
-"configuration port" address.
-
-If you have a sound card which needs a "configuration driver" instead of
-jumpers for interface types and addresses (like Mozart cards) - those
-drivers get invoked before the DOS CDROM driver in your CONFIG.SYS, typical
-names are "cdsetup.sys" and "mztinit.sys" - let the sound driver do the
-CDROM port configuration (the leading comments in linux/drivers/sound/mad16.c
-are just for you!). Hannu Savolainen's mad16.c code is able to set up my
-Mozart card - I simply had to add
- #define MAD16_CONF 0x06
- #define MAD16_CDSEL 0x03
-to configure the CDROM interface for type "Panasonic" (LaserMate) and address
-0x340.
-
-The interface type has to get configured in linux/drivers/cdrom/sbpcd.h,
-because the register layout is different between the "SoundBlaster" and the
-"LaserMate" type.
-
-I got a report that the Teac interface card "I/F E117098" is of type
-"SoundBlaster" (i.e. you have to set SBPRO to 1) even with the addresses
-0x300 and above. This is unusual, and it can't get covered by the auto
-probing scheme.
-The Teac 16-bit interface cards (like P/N E950228-00A, default address 0x2C0)
-need the SBPRO 3 setup.
-
-If auto-probing found the drive, the address is correct. The reported type
-may be wrong. A "mount" will give success only if the interface type is set
-right. Playing audio should work with a wrong set interface type, too.
-
-With some Teac and some CD200 drives I have seen interface cards which seem
-to lack the "drive select" lines; always drive 0 gets addressed. To avoid
-"mirror drives" (four drives detected where you only have one) with such
-interface cards, set MAX_DRIVES to 1 and jumper your drive to ID 0 (if
-possible).
-
-
-Up to 4 drives per interface card, and up to 4 interface cards are supported.
-All supported drive families can be mixed, but the CR-521 drives are
-hard-wired to drive ID 0. The drives have to use different drive IDs, and each
-drive has to get a unique minor number (0...3), corresponding indirectly to
-its drive ID.
-The drive IDs may be selected freely from 0 to 3 - they do not have to be in
-consecutive order.
-
-As Don Carroll, don@ds9.us.dell.com or FIDO 1:382/14, told me, it is possible
-to change old drives to any ID, too. He writes in this sense:
- "In order to be able to use more than one single speed drive
- (they do not have the ID jumpers) you must add a DIP switch
- and two resistors. The pads are already on the board next to
- the power connector. You will see the silkscreen for the
- switch if you remove the top cover.
- 1 2 3 4
- ID 0 = x F F x O = "on"
- ID 1 = x O F x F = "off"
- ID 2 = x F O x x = "don't care"
- ID 3 = x O O x
- Next to the switch are the positions for R76 (7k) and R78
- (12k). I had to play around with the resistor values - ID 3
- did not work with other values. If the values are not good,
- ID 3 behaves like ID 0."
-
-To use more than 4 drives, you simply need a second controller card at a
-different address and a second cable.
-
-The driver supports reading of data from the CD and playing of audio tracks.
-The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
-CDplayer and WorkBone - tell me if it is not compatible with other software.
-The only accepted measure for correctness with the audio functions is the
-"cdtester" utility (appended) - most audio player programmers seem to be
-better musicians than programmers. ;-)
-
-With the CR-56x and the CD200 drives, the reading of audio frames is possible.
-This is implemented by an IOCTL function which reads READ_AUDIO frames of
-2352 bytes at once (configurable with the "READ_AUDIO" define, default is 0).
-Reading the same frame a second time gives different data; the frame data
-start at a different position, but all read bytes are valid, and we always
-read 98 consecutive chunks (of 24 Bytes) as a frame. Reading more than 1 frame
-at once possibly misses some chunks at each frame boundary. This lack has to
-get corrected by external, "higher level" software which reads the same frame
-again and tries to find and eliminate overlapping chunks (24-byte-pieces).
-
-The transfer rate with reading audio (1-frame-pieces) currently is very slow.
-This can be better reading bigger chunks, but the "missing" chunks possibly
-occur at the beginning of each single frame.
-The software interface possibly may change a bit the day the SCSI driver
-supports it too.
-
-With all but the CR-52x drives, MultiSession is supported.
-Photo CDs work (the "old" drives like CR-521 can access only the first
-session of a photoCD).
-At ftp.gwdg.de:/pub/linux/hpcdtoppm/ you will find Hadmut Danisch's package to
-convert photo CD image files and Gerd Knorr's viewing utility.
-
-The transfer rate will reach 150 kB/sec with CR-52x drives, 300 kB/sec with
-CR-56x drives, and currently not more than 500 kB/sec (usually less than
-250 kB/sec) with the Teac quad speed drives.
-XA (PhotoCD) disks with "old" drives give only 50 kB/sec.
-
-This release consists of
-- this README file
-- the driver file linux/drivers/cdrom/sbpcd.c
-- the stub files linux/drivers/cdrom/sbpcd[234].c
-- the header file linux/drivers/cdrom/sbpcd.h.
-
-
-To install:
------------
-
-1. Setup your hardware parameters. Though the driver does "auto-probing" at a
- lot of (not all possible!) addresses, this step is recommended for
- everyday use. You should let sbpcd auto-probe once and use the reported
- address if a drive got found. The reported type may be incorrect; it is
- correct if you can mount a data CD. There is no choice for you with the
- type; only one is right, the others are deadly wrong.
-
- a. Go into /usr/src/linux/drivers/cdrom/sbpcd.h and configure it for your
- hardware (near the beginning):
- a1. Set it up for the appropriate type of interface board.
- "Original" CreativeLabs sound cards need "SBPRO 1".
- Most "compatible" sound cards (almost all "non-CreativeLabs" cards)
- need "SBPRO 0".
- The "no-sound" board from OmniCd needs the "SBPRO 1" setup.
- The Teac 8-bit "no-sound" boards need the "SBPRO 1" setup.
- The Teac 16-bit "no-sound" boards need the "SBPRO 3" setup.
- All other "no-sound" boards need the "SBPRO 0" setup.
- The Spea Media FX and Ensoniq SoundScape cards need "SBPRO 2".
- sbpcd.c holds some examples in its auto-probe list.
- If you configure "SBPRO" wrong, the playing of audio CDs will work,
- but you will not be able to mount a data CD.
- a2. Tell the address of your CDROM_PORT (not of the sound port).
- a3. If 4 drives get found, but you have only one, set MAX_DRIVES to 1.
- a4. Set DISTRIBUTION to 0.
- b. Additionally for 2.a1 and 2.a2, the setup may be done during
- boot time (via the "kernel command line" or "LILO option"):
- sbpcd=0x320,LaserMate
- or
- sbpcd=0x230,SoundBlaster
- or
- sbpcd=0x338,SoundScape
- or
- sbpcd=0x2C0,Teac16bit
- This is especially useful if you install a fresh distribution.
- If the second parameter is a number, it gets taken as the type
- setting; 0 is "LaserMate", 1 is "SoundBlaster", 2 is "SoundScape",
- 3 is "Teac16bit".
- So, for example
- sbpcd=0x230,1
- is equivalent to
- sbpcd=0x230,SoundBlaster
-
-2. "cd /usr/src/linux" and do a "make config" and select "y" for Matsushita
- CD-ROM support and for ISO9660 FileSystem support. If you do not have a
- second, third, or fourth controller installed, do not say "y" to the
- secondary Matsushita CD-ROM questions.
-
-3. Then make the kernel image ("make zlilo" or similar).
-
-4. Make the device file(s). This step usually already has been done by the
- MAKEDEV script.
- The driver uses MAJOR 25, so, if necessary, do
- mknod /dev/sbpcd b 25 0 (if you have only one drive)
- and/or
- mknod /dev/sbpcd0 b 25 0
- mknod /dev/sbpcd1 b 25 1
- mknod /dev/sbpcd2 b 25 2
- mknod /dev/sbpcd3 b 25 3
- to make the node(s).
-
- The "first found" drive gets MINOR 0 (regardless of its jumpered ID), the
- "next found" (at the same cable) gets MINOR 1, ...
-
- For a second interface board, you have to make nodes like
- mknod /dev/sbpcd4 b 26 0
- mknod /dev/sbpcd5 b 26 1
- and so on. Use the MAJORs 26, 27, 28.
-
- If you further make a link like
- ln -s sbpcd /dev/cdrom
- you can use the name /dev/cdrom, too.
-
-5. Reboot with the new kernel.
-
-You should now be able to do
- mkdir /CD
-and
- mount -rt iso9660 /dev/sbpcd /CD
-or
- mount -rt iso9660 -o block=2048 /dev/sbpcd /CD
-and see the contents of your CD in the /CD directory.
-To use audio CDs, a mounting is not recommended (and it would fail if the
-first track is not a data track).
-
-
-Using sbpcd as a "loadable module":
------------------------------------
-
-If you do NOT select "Matsushita/Panasonic CDROM driver support" during the
-"make config" of your kernel, you can build the "loadable module" sbpcd.o.
-
-If sbpcd gets used as a module, the support of more than one interface
-card (i.e. drives 4...15) is disabled.
-
-You can specify interface address and type with the "insmod" command like:
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x340,0
-or
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x230,1
-or
- # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x338,2
-where the last number represents the SBPRO setting (no strings allowed here).
-
-
-Things of interest:
--------------------
-
-The driver is configured to try the LaserMate type of interface at I/O port
-0x0340 first. If this is not appropriate, sbpcd.h should get changed
-(you will find the right place - just at the beginning).
-
-No DMA and no IRQ is used.
-
-To reduce or increase the amount of kernel messages, edit sbpcd.c and play
-with the "DBG_xxx" switches (initialization of the variable "sbpcd_debug").
-Don't forget to reflect on what you do; enabling all DBG_xxx switches at once
-may crash your system, and each message line is accompanied by a delay.
-
-The driver uses the "variable BLOCK_SIZE" feature. To use it, you have to
-specify "block=2048" as a mount option. Doing this will disable the direct
-execution of a binary from the CD; you have to copy it to a device with the
-standard BLOCK_SIZE (1024) first. So, do not use this if your system is
-directly "running from the CDROM" (like some of Yggdrasil's installation
-variants). There are CDs on the market (like the German "unifix" Linux
-distribution) which MUST get handled with a block_size of 1024. Generally,
-one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
-do not use block=2048 with those.
-
-Within sbpcd.h, you will find some "#define"s (e.g. EJECT and JUKEBOX). With
-these, you can configure the driver for some special things.
-You can use the appended program "cdtester" to set the auto-eject feature
-during runtime. Jeff Tranter's "eject" utility can do this, too (and more)
-for you.
-
-There is an ioctl CDROMMULTISESSION to obtain with a user program if
-the CD is an XA disk and - if it is - where the last session starts. The
-"cdtester" program illustrates how to call it.
-
-
-Auto-probing at boot time:
---------------------------
-
-The driver does auto-probing at many well-known interface card addresses,
-but not all:
-Some probings can cause a hang if an NE2000 ethernet card gets touched, because
-SBPCD's auto-probing happens before the initialization of the net drivers.
-Those "hazardous" addresses are excluded from auto-probing; the "kernel
-command line" feature has to be used during installation if you have your
-drive at those addresses. The "module" version is allowed to probe at those
-addresses, too.
-
-The auto-probing looks first at the configured address resp. the address
-submitted by the kernel command line. With this, it is possible to use this
-driver within installation boot floppies, and for any non-standard address,
-too.
-
-Auto-probing will make an assumption about the interface type ("SBPRO" or not),
-based upon the address. That assumption may be wrong (initialization will be
-o.k., but you will get I/O errors during mount). In that case, use the "kernel
-command line" feature and specify address & type at boot time to find out the
-right setup.
-
-For everyday use, address and type should get configured within sbpcd.h. That
-will stop the auto-probing due to success with the first try.
-
-The kernel command "sbpcd=0" suppresses each auto-probing and causes
-the driver not to find any drive; it is meant for people who love sbpcd
-so much that they do not want to miss it, even if they miss the drives. ;-)
-
-If you configure "#define CDROM_PORT 0" in sbpcd.h, the auto-probing is
-initially disabled and needs an explicit kernel command to get activated.
-Once activated, it does not stop before success or end-of-list. This may be
-useful within "universal" CDROM installation boot floppies (but using the
-loadable module would be better because it allows an "extended" auto-probing
-without fearing NE2000 cards).
-
-To shorten the auto-probing list to a single entry, set DISTRIBUTION 0 within
-sbpcd.h.
-
-
-Setting up address and interface type:
---------------------------------------
-
-If your I/O port address is not 0x340, you have to look for the #defines near
-the beginning of sbpcd.h and configure them: set SBPRO to 0 or 1 or 2, and
-change CDROM_PORT to the address of your CDROM I/O port.
-
-Almost all of the "SoundBlaster compatible" cards behave like the no-sound
-interfaces, i.e. need SBPRO 0!
-
-With "original" SB Pro cards, an initial setting of CD_volume through the
-sound card's MIXER register gets done.
-If you are using a "compatible" sound card of types "LaserMate" or "SPEA",
-you can set SOUND_BASE (in sbpcd.h) to get it done with your card, too...
-
-
-Using audio CDs:
-----------------
-
-Workman, WorkBone, xcdplayer, cdplayer and the nice little tool "cdplay" (see
-README.aztcd from the Aztech driver package) should work.
-
-The program CDplayer likes to talk to "/dev/mcd" only, xcdplayer wants
-"/dev/rsr0", workman loves "/dev/sr0" or "/dev/cdrom" - so, make the
-appropriate links to use them without the need to supply parameters.
-
-
-Copying audio tracks:
----------------------
-
-The following program will copy track 1 (or a piece of it) from an audio CD
-into the file "track01":
-
-/*=================== begin program ========================================*/
-/*
- * read an audio track from a CD
- *
- * (c) 1994 Eberhard Moenkeberg <emoenke@gwdg.de>
- * may be used & enhanced freely
- *
- * Due to non-existent sync bytes at the beginning of each audio frame (or due
- * to a firmware bug within all known drives?), it is currently a kind of
- * fortune if two consecutive frames fit together.
- * Usually, they overlap, or a little piece is missing. This happens in units
- * of 24-byte chunks. It has to get fixed by higher-level software (reading
- * until an overlap occurs, and then eliminate the overlapping chunks).
- * ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz holds an example of
- * such an algorithm.
- * This example program further is missing to obtain the SubChannel data
- * which belong to each frame.
- *
- * This is only an example of the low-level access routine. The read data are
- * pure 16-bit CDDA values; they have to get converted to make sound out of
- * them.
- * It is no fun to listen to it without prior overlap/underlap correction!
- */
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <linux/cdrom.h>
-
-static struct cdrom_tochdr hdr;
-static struct cdrom_tocentry entry[101];
-static struct cdrom_read_audio arg;
-static u_char buffer[CD_FRAMESIZE_RAW];
-static int datafile, drive;
-static int i, j, limit, track, err;
-static char filename[32];
-
-int main(int argc, char *argv[])
-{
-/*
- * open /dev/cdrom
- */
- drive=open("/dev/cdrom", 0);
- if (drive<0)
- {
- fprintf(stderr, "can't open drive.\n");
- exit (-1);
- }
-/*
- * get TocHeader
- */
- fprintf(stdout, "getting TocHeader...\n");
- err=ioctl(drive, CDROMREADTOCHDR, &hdr);
- if (err!=0)
- {
- fprintf(stderr, "can't get TocHeader (error %d).\n", err);
- exit (-1);
- }
- else
- fprintf(stdout, "TocHeader: %d %d\n", hdr.cdth_trk0, hdr.cdth_trk1);
-/*
- * get and display all TocEntries
- */
- fprintf(stdout, "getting TocEntries...\n");
- for (i=1;i<=hdr.cdth_trk1+1;i++)
- {
- if (i!=hdr.cdth_trk1+1) entry[i].cdte_track = i;
- else entry[i].cdte_track = CDROM_LEADOUT;
- entry[i].cdte_format = CDROM_LBA;
- err=ioctl(drive, CDROMREADTOCENTRY, &entry[i]);
- if (err!=0)
- {
- fprintf(stderr, "can't get TocEntry #%d (error %d).\n", i, err);
- exit (-1);
- }
- else
- {
- fprintf(stdout, "TocEntry #%d: %1X %1X %06X %02X\n",
- entry[i].cdte_track,
- entry[i].cdte_adr,
- entry[i].cdte_ctrl,
- entry[i].cdte_addr.lba,
- entry[i].cdte_datamode);
- }
- }
- fprintf(stdout, "got all TocEntries.\n");
-/*
- * ask for track number (not implemented here)
- */
-track=1;
-#if 0 /* just read a little piece (4 seconds) */
-entry[track+1].cdte_addr.lba=entry[track].cdte_addr.lba+300;
-#endif
-/*
- * read track into file
- */
- sprintf(filename, "track%02d\0", track);
- datafile=creat(filename, 0755);
- if (datafile<0)
- {
- fprintf(stderr, "can't open datafile %s.\n", filename);
- exit (-1);
- }
- arg.addr.lba=entry[track].cdte_addr.lba;
- arg.addr_format=CDROM_LBA; /* CDROM_MSF would be possible here, too. */
- arg.nframes=1;
- arg.buf=&buffer[0];
- limit=entry[track+1].cdte_addr.lba;
- for (;arg.addr.lba<limit;arg.addr.lba++)
- {
- err=ioctl(drive, CDROMREADAUDIO, &arg);
- if (err!=0)
- {
- fprintf(stderr, "can't read abs. frame #%d (error %d).\n",
- arg.addr.lba, err);
- }
- j=write(datafile, &buffer[0], CD_FRAMESIZE_RAW);
- if (j!=CD_FRAMESIZE_RAW)
- {
- fprintf(stderr,"I/O error (datafile) at rel. frame %d\n",
- arg.addr.lba-entry[track].cdte_addr.lba);
- }
- arg.addr.lba++;
- }
- return 0;
-}
-/*===================== end program ========================================*/
-
-At ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.*.tar.gz is an adapted version of
-Heiko Eissfeldt's digital-audio to .WAV converter (the original is there, too).
-This is preliminary, as Heiko himself will care about it.
-
-
-Known problems:
----------------
-
-Currently, the detection of disk change or removal is actively disabled.
-
-Most attempts to read the UPC/EAN code result in a stream of zeroes. All my
-drives are mostly telling there is no UPC/EAN code on disk or there is, but it
-is an all-zero number. I guess now almost no CD holds such a number.
-
-Bug reports, comments, wishes, donations (technical information is a donation,
-too :-) etc. to emoenke@gwdg.de.
-
-SnailMail address, preferable for CD editors if they want to submit a free
-"cooperation" copy:
- Eberhard Moenkeberg
- Reinholdstr. 14
- D-37083 Goettingen
- Germany
----
-
-
-Appendix -- the "cdtester" utility:
-
-/*
- * cdtester.c -- test the audio functions of a CD driver
- *
- * (c) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
- * published under the GPL
- *
- * made under heavy use of the "Tiny Audio CD Player"
- * from Werner Zimmermann <zimmerma@rz.fht-esslingen.de>
- * (see linux/drivers/block/README.aztcd)
- */
-#undef AZT_PRIVATE_IOCTLS /* not supported by every CDROM driver */
-#define SBP_PRIVATE_IOCTLS /* not supported by every CDROM driver */
-
-#include <stdio.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <linux/cdrom.h>
-
-#ifdef AZT_PRIVATE_IOCTLS
-#include <linux/../../drivers/cdrom/aztcd.h>
-#endif /* AZT_PRIVATE_IOCTLS */
-#ifdef SBP_PRIVATE_IOCTLS
-#include <linux/../../drivers/cdrom/sbpcd.h>
-#include <linux/fs.h>
-#endif /* SBP_PRIVATE_IOCTLS */
-
-struct cdrom_tochdr hdr;
-struct cdrom_tochdr tocHdr;
-struct cdrom_tocentry TocEntry[101];
-struct cdrom_tocentry entry;
-struct cdrom_multisession ms_info;
-struct cdrom_read_audio read_audio;
-struct cdrom_ti ti;
-struct cdrom_subchnl subchnl;
-struct cdrom_msf msf;
-struct cdrom_volctrl volctrl;
-#ifdef AZT_PRIVATE_IOCTLS
-union
-{
- struct cdrom_msf msf;
- unsigned char buf[CD_FRAMESIZE_RAW];
-} azt;
-#endif /* AZT_PRIVATE_IOCTLS */
-int i, i1, i2, i3, j, k;
-unsigned char sequence=0;
-unsigned char command[80];
-unsigned char first=1, last=1;
-char *default_device="/dev/cdrom";
-char dev[20];
-char filename[20];
-int drive;
-int datafile;
-int rc;
-
-void help(void)
-{
- printf("Available Commands:\n");
- printf("STOP s EJECT e QUIT q\n");
- printf("PLAY TRACK t PAUSE p RESUME r\n");
- printf("NEXT TRACK n REPEAT LAST l HELP h\n");
- printf("SUBCHANNEL_Q c TRACK INFO i PLAY AT a\n");
- printf("READ d READ RAW w READ AUDIO A\n");
- printf("MS-INFO M TOC T START S\n");
- printf("SET EJECTSW X DEVICE D DEBUG Y\n");
- printf("AUDIO_BUFSIZ Z RESET R SET VOLUME v\n");
- printf("GET VOLUME V\n");
-}
-
-/*
- * convert MSF number (3 bytes only) to Logical_Block_Address
- */
-int msf2lba(u_char *msf)
-{
- int i;
-
- i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*
- * convert logical_block_address to m-s-f_number (3 bytes only)
- */
-void lba2msf(int lba, unsigned char *msf)
-{
- lba += CD_BLOCK_OFFSET;
- msf[0] = lba / (CD_SECS*CD_FRAMES);
- lba %= CD_SECS*CD_FRAMES;
- msf[1] = lba / CD_FRAMES;
- msf[2] = lba % CD_FRAMES;
-}
-
-int init_drive(char *dev)
-{
- unsigned char msf_ent[3];
-
- /*
- * open the device
- */
- drive=open(dev,0);
- if (drive<0) return (-1);
- /*
- * get TocHeader
- */
- printf("getting TocHeader...\n");
- rc=ioctl(drive,CDROMREADTOCHDR,&hdr);
- if (rc!=0)
- {
- printf("can't get TocHeader (error %d).\n",rc);
- return (-2);
- }
- else
- first=hdr.cdth_trk0;
- last=hdr.cdth_trk1;
- printf("TocHeader: %d %d\n",hdr.cdth_trk0,hdr.cdth_trk1);
- /*
- * get and display all TocEntries
- */
- printf("getting TocEntries...\n");
- for (i=1;i<=hdr.cdth_trk1+1;i++)
- {
- if (i!=hdr.cdth_trk1+1) TocEntry[i].cdte_track = i;
- else TocEntry[i].cdte_track = CDROM_LEADOUT;
- TocEntry[i].cdte_format = CDROM_LBA;
- rc=ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]);
- if (rc!=0)
- {
- printf("can't get TocEntry #%d (error %d).\n",i,rc);
- }
- else
- {
- lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
- if (TocEntry[i].cdte_track==CDROM_LEADOUT)
- {
- printf("TocEntry #%02X: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n",
- TocEntry[i].cdte_track,
- TocEntry[i].cdte_adr,
- TocEntry[i].cdte_ctrl,
- msf_ent[0],
- msf_ent[1],
- msf_ent[2],
- TocEntry[i].cdte_addr.lba,
- TocEntry[i].cdte_datamode);
- }
- else
- {
- printf("TocEntry #%02d: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n",
- TocEntry[i].cdte_track,
- TocEntry[i].cdte_adr,
- TocEntry[i].cdte_ctrl,
- msf_ent[0],
- msf_ent[1],
- msf_ent[2],
- TocEntry[i].cdte_addr.lba,
- TocEntry[i].cdte_datamode);
- }
- }
- }
- return (hdr.cdth_trk1); /* number of tracks */
-}
-
-void display(int size,unsigned char *buffer)
-{
- k=0;
- getchar();
- for (i=0;i<(size+1)/16;i++)
- {
- printf("%4d:",i*16);
- for (j=0;j<16;j++)
- {
- printf(" %02X",buffer[i*16+j]);
- }
- printf(" ");
- for (j=0;j<16;j++)
- {
- if (isalnum(buffer[i*16+j]))
- printf("%c",buffer[i*16+j]);
- else
- printf(".");
- }
- printf("\n");
- k++;
- if (k>=20)
- {
- printf("press ENTER to continue\n");
- getchar();
- k=0;
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- printf("\nTesting tool for a CDROM driver's audio functions V0.1\n");
- printf("(C) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>\n");
- printf("initializing...\n");
-
- rc=init_drive(default_device);
- if (rc<0) printf("could not open %s (rc=%d).\n",default_device,rc);
- help();
- while (1)
- {
- printf("Give a one-letter command (h = help): ");
- scanf("%s",command);
- command[1]=0;
- switch (command[0])
- {
- case 'D':
- printf("device name (f.e. /dev/sbpcd3): ? ");
- scanf("%s",&dev);
- close(drive);
- rc=init_drive(dev);
- if (rc<0) printf("could not open %s (rc %d).\n",dev,rc);
- break;
- case 'e':
- rc=ioctl(drive,CDROMEJECT);
- if (rc<0) printf("CDROMEJECT: rc=%d.\n",rc);
- break;
- case 'p':
- rc=ioctl(drive,CDROMPAUSE);
- if (rc<0) printf("CDROMPAUSE: rc=%d.\n",rc);
- break;
- case 'r':
- rc=ioctl(drive,CDROMRESUME);
- if (rc<0) printf("CDROMRESUME: rc=%d.\n",rc);
- break;
- case 's':
- rc=ioctl(drive,CDROMSTOP);
- if (rc<0) printf("CDROMSTOP: rc=%d.\n",rc);
- break;
- case 'S':
- rc=ioctl(drive,CDROMSTART);
- if (rc<0) printf("CDROMSTART: rc=%d.\n",rc);
- break;
- case 't':
- rc=ioctl(drive,CDROMREADTOCHDR,&tocHdr);
- if (rc<0)
- {
- printf("CDROMREADTOCHDR: rc=%d.\n",rc);
- break;
- }
- first=tocHdr.cdth_trk0;
- last= tocHdr.cdth_trk1;
- if ((first==0)||(first>last))
- {
- printf ("--got invalid TOC data.\n");
- }
- else
- {
- printf("--enter track number(first=%d, last=%d): ",first,last);
- scanf("%d",&i1);
- ti.cdti_trk0=i1;
- if (ti.cdti_trk0<first) ti.cdti_trk0=first;
- if (ti.cdti_trk0>last) ti.cdti_trk0=last;
- ti.cdti_ind0=0;
- ti.cdti_trk1=last;
- ti.cdti_ind1=0;
- rc=ioctl(drive,CDROMSTOP);
- rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
- if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
- }
- break;
- case 'n':
- rc=ioctl(drive,CDROMSTOP);
- if (++ti.cdti_trk0>last) ti.cdti_trk0=last;
- ti.cdti_ind0=0;
- ti.cdti_trk1=last;
- ti.cdti_ind1=0;
- rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
- if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
- break;
- case 'l':
- rc=ioctl(drive,CDROMSTOP);
- if (--ti.cdti_trk0<first) ti.cdti_trk0=first;
- ti.cdti_ind0=0;
- ti.cdti_trk1=last;
- ti.cdti_ind1=0;
- rc=ioctl(drive,CDROMPLAYTRKIND,&ti);
- if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc);
- break;
- case 'c':
- subchnl.cdsc_format=CDROM_MSF;
- rc=ioctl(drive,CDROMSUBCHNL,&subchnl);
- if (rc<0) printf("CDROMSUBCHNL: rc=%d.\n",rc);
- else
- {
- printf("AudioStatus:%s Track:%d Mode:%d MSF=%02d:%02d:%02d\n",
- subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING",
- subchnl.cdsc_trk,subchnl.cdsc_adr,
- subchnl.cdsc_absaddr.msf.minute,
- subchnl.cdsc_absaddr.msf.second,
- subchnl.cdsc_absaddr.msf.frame);
- }
- break;
- case 'i':
- printf("Track No.: ");
- scanf("%d",&i1);
- entry.cdte_track=i1;
- if (entry.cdte_track<first) entry.cdte_track=first;
- if (entry.cdte_track>last) entry.cdte_track=last;
- entry.cdte_format=CDROM_MSF;
- rc=ioctl(drive,CDROMREADTOCENTRY,&entry);
- if (rc<0) printf("CDROMREADTOCENTRY: rc=%d.\n",rc);
- else
- {
- printf("Mode %d Track, starts at %02d:%02d:%02d\n",
- entry.cdte_adr,
- entry.cdte_addr.msf.minute,
- entry.cdte_addr.msf.second,
- entry.cdte_addr.msf.frame);
- }
- break;
- case 'a':
- printf("Address (min:sec:frm) ");
- scanf("%d:%d:%d",&i1,&i2,&i3);
- msf.cdmsf_min0=i1;
- msf.cdmsf_sec0=i2;
- msf.cdmsf_frame0=i3;
- if (msf.cdmsf_sec0>59) msf.cdmsf_sec0=59;
- if (msf.cdmsf_frame0>74) msf.cdmsf_frame0=74;
- lba2msf(TocEntry[last+1].cdte_addr.lba-1,&msf.cdmsf_min1);
- rc=ioctl(drive,CDROMSTOP);
- rc=ioctl(drive,CDROMPLAYMSF,&msf);
- if (rc<0) printf("CDROMPLAYMSF: rc=%d.\n",rc);
- break;
- case 'V':
- rc=ioctl(drive,CDROMVOLREAD,&volctrl);
- if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc);
- printf("Volume: channel 0 (left) %d, channel 1 (right) %d\n",volctrl.channel0,volctrl.channel1);
- break;
- case 'R':
- rc=ioctl(drive,CDROMRESET);
- if (rc<0) printf("CDROMRESET: rc=%d.\n",rc);
- break;
-#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/
- case 'd':
- printf("Address (min:sec:frm) ");
- scanf("%d:%d:%d",&i1,&i2,&i3);
- azt.msf.cdmsf_min0=i1;
- azt.msf.cdmsf_sec0=i2;
- azt.msf.cdmsf_frame0=i3;
- if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59;
- if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74;
- rc=ioctl(drive,CDROMREADMODE1,&azt.msf);
- if (rc<0) printf("CDROMREADMODE1: rc=%d.\n",rc);
- else display(CD_FRAMESIZE,azt.buf);
- break;
- case 'w':
- printf("Address (min:sec:frame) ");
- scanf("%d:%d:%d",&i1,&i2,&i3);
- azt.msf.cdmsf_min0=i1;
- azt.msf.cdmsf_sec0=i2;
- azt.msf.cdmsf_frame0=i3;
- if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59;
- if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74;
- rc=ioctl(drive,CDROMREADMODE2,&azt.msf);
- if (rc<0) printf("CDROMREADMODE2: rc=%d.\n",rc);
- else display(CD_FRAMESIZE_RAW,azt.buf); /* currently only 2336 */
- break;
-#endif
- case 'v':
- printf("--Channel 0 (Left) (0-255): ");
- scanf("%d",&i1);
- volctrl.channel0=i1;
- printf("--Channel 1 (Right) (0-255): ");
- scanf("%d",&i1);
- volctrl.channel1=i1;
- volctrl.channel2=0;
- volctrl.channel3=0;
- rc=ioctl(drive,CDROMVOLCTRL,&volctrl);
- if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc);
- break;
- case 'q':
- close(drive);
- exit(0);
- case 'h':
- help();
- break;
- case 'T': /* display TOC entry - without involving the driver */
- scanf("%d",&i);
- if ((i<hdr.cdth_trk0)||(i>hdr.cdth_trk1))
- printf("invalid track number.\n");
- else
- printf("TocEntry %02d: adr=%01X ctrl=%01X msf=%02d:%02d:%02d mode=%02X\n",
- TocEntry[i].cdte_track,
- TocEntry[i].cdte_adr,
- TocEntry[i].cdte_ctrl,
- TocEntry[i].cdte_addr.msf.minute,
- TocEntry[i].cdte_addr.msf.second,
- TocEntry[i].cdte_addr.msf.frame,
- TocEntry[i].cdte_datamode);
- break;
- case 'A': /* read audio data into file */
- printf("Address (min:sec:frm) ? ");
- scanf("%d:%d:%d",&i1,&i2,&i3);
- read_audio.addr.msf.minute=i1;
- read_audio.addr.msf.second=i2;
- read_audio.addr.msf.frame=i3;
- read_audio.addr_format=CDROM_MSF;
- printf("# of frames ? ");
- scanf("%d",&i1);
- read_audio.nframes=i1;
- k=read_audio.nframes*CD_FRAMESIZE_RAW;
- read_audio.buf=malloc(k);
- if (read_audio.buf==NULL)
- {
- printf("can't malloc %d bytes.\n",k);
- break;
- }
- sprintf(filename,"audio_%02d%02d%02d_%02d.%02d\0",
- read_audio.addr.msf.minute,
- read_audio.addr.msf.second,
- read_audio.addr.msf.frame,
- read_audio.nframes,
- ++sequence);
- datafile=creat(filename, 0755);
- if (datafile<0)
- {
- printf("can't open datafile %s.\n",filename);
- break;
- }
- rc=ioctl(drive,CDROMREADAUDIO,&read_audio);
- if (rc!=0)
- {
- printf("CDROMREADAUDIO: rc=%d.\n",rc);
- }
- else
- {
- rc=write(datafile,&read_audio.buf,k);
- if (rc!=k) printf("datafile I/O error (%d).\n",rc);
- }
- close(datafile);
- break;
- case 'X': /* set EJECT_SW (0: disable, 1: enable auto-ejecting) */
- scanf("%d",&i);
- rc=ioctl(drive,CDROMEJECT_SW,i);
- if (rc!=0)
- printf("CDROMEJECT_SW: rc=%d.\n",rc);
- else
- printf("EJECT_SW set to %d\n",i);
- break;
- case 'M': /* get the multisession redirection info */
- ms_info.addr_format=CDROM_LBA;
- rc=ioctl(drive,CDROMMULTISESSION,&ms_info);
- if (rc!=0)
- {
- printf("CDROMMULTISESSION(lba): rc=%d.\n",rc);
- }
- else
- {
- if (ms_info.xa_flag) printf("MultiSession offset (lba): %d (0x%06X)\n",ms_info.addr.lba,ms_info.addr.lba);
- else
- {
- printf("this CD is not an XA disk.\n");
- break;
- }
- }
- ms_info.addr_format=CDROM_MSF;
- rc=ioctl(drive,CDROMMULTISESSION,&ms_info);
- if (rc!=0)
- {
- printf("CDROMMULTISESSION(msf): rc=%d.\n",rc);
- }
- else
- {
- if (ms_info.xa_flag)
- printf("MultiSession offset (msf): %02d:%02d:%02d (0x%02X%02X%02X)\n",
- ms_info.addr.msf.minute,
- ms_info.addr.msf.second,
- ms_info.addr.msf.frame,
- ms_info.addr.msf.minute,
- ms_info.addr.msf.second,
- ms_info.addr.msf.frame);
- else printf("this CD is not an XA disk.\n");
- }
- break;
-#ifdef SBP_PRIVATE_IOCTLS
- case 'Y': /* set the driver's message level */
-#if 0 /* not implemented yet */
- printf("enter switch name (f.e. DBG_CMD): ");
- scanf("%s",&dbg_switch);
- j=get_dbg_num(dbg_switch);
-#else
- printf("enter DDIOCSDBG switch number: ");
- scanf("%d",&j);
-#endif
- printf("enter 0 for \"off\", 1 for \"on\": ");
- scanf("%d",&i);
- if (i==0) j|=0x80;
- printf("calling \"ioctl(drive,DDIOCSDBG,%d)\"\n",j);
- rc=ioctl(drive,DDIOCSDBG,j);
- printf("DDIOCSDBG: rc=%d.\n",rc);
- break;
- case 'Z': /* set the audio buffer size */
- printf("# frames wanted: ? ");
- scanf("%d",&j);
- rc=ioctl(drive,CDROMAUDIOBUFSIZ,j);
- printf("%d frames granted.\n",rc);
- break;
-#endif /* SBP_PRIVATE_IOCTLS */
- default:
- printf("unknown command: \"%s\".\n",command);
- break;
- }
- }
- return 0;
-}
-/*==========================================================================*/
-
diff --git a/Documentation/cdrom/sjcd b/Documentation/cdrom/sjcd
deleted file mode 100644
index 74a14847b93a..000000000000
--- a/Documentation/cdrom/sjcd
+++ /dev/null
@@ -1,60 +0,0 @@
- -- Documentation/cdrom/sjcd
- 80% of the work takes 20% of the time,
- 20% of the work takes 80% of the time...
- (Murphy's law)
-
- Once started, training can not be stopped...
- (Star Wars)
-
-This is the README for the sjcd cdrom driver, version 1.6.
-
-This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A
-cdrom drive. It will grow as the questions arise. ;-)
-For info on configuring the ISP16 sound card look at Documentation/cdrom/isp16.
-
-The driver should work with any of the Panasonic, Sony or Mitsumi style
-CDROM interfaces.
-The cdrom interface on Media Magic's soft configurable sound card ISP16,
-which used to be included in the driver, is now supported in a separate module.
-This initialisation module will probably also work with other interfaces
-based on an OPTi 82C928 or 82C929 chip (like MAD16 and Mozart): see the
-documentation Documentation/cdrom/isp16.
-
-The device major for sjcd is 18, and minor is 0. Create a block special
-file in your /dev directory (e.g., /dev/sjcd) with these numbers.
-(For those who don't know, being root and doing the following should do
-the trick:
- mknod -m 644 /dev/sjcd b 18 0
-and mount the cdrom by /dev/sjcd).
-
-The default configuration parameters are:
- base address 0x340
- no irq
- no dma
-(Actually the CDR-H94A doesn't know how to use irq and dma.)
-As of version 1.2, setting base address at boot time is supported
-through the use of command line options: type at the "boot:" prompt:
- linux sjcd=<base_address>
-(where you would use the kernel labeled "linux" in lilo's configuration
-file /etc/lilo.conf). You could also use 'append="sjcd=<configuration_info>"'
-in the appropriate section of /etc/lilo.conf
-If you're building a kernel yourself you can set your default base
-i/o address with SJCD_BASE_ADDR in /usr/src/linux/drivers/cdrom/sjcd.h.
-
-The sjcd driver supports being loaded as a module. The following
-command will set the base i/o address on the fly (assuming you
-have installed the module in an appropriate place).
- insmod sjcd.o sjcd_base=<base_address>
-
-
-Have fun!
-
-If something is wrong, please email to vadim@rbrf.ru
- or vadim@ipsun.ras.ru
- or model@cecmow.enet.dec.com
- or H.T.M.v.d.Maarel@marin.nl
-
-It happens sometimes that Vadim is not reachable by mail. For these
-instances, Eric van der Maarel will help too.
-
- Vadim V. Model, Eric van der Maarel, Eberhard Moenkeberg
diff --git a/Documentation/cdrom/sonycd535 b/Documentation/cdrom/sonycd535
deleted file mode 100644
index b81e109970aa..000000000000
--- a/Documentation/cdrom/sonycd535
+++ /dev/null
@@ -1,122 +0,0 @@
- README FOR LINUX SONY CDU-535/531 DRIVER
- ========================================
-
-This is the Sony CDU-535 (and 531) driver version 0.7 for Linux.
-I do not think I have the documentation to add features like DMA support
-so if anyone else wants to pursue it or help me with it, please do.
-(I need to see what was done for the CDU-31A driver -- perhaps I can
-steal some of that code.)
-
-This is a Linux device driver for the Sony CDU-535 CDROM drive. This is
-one of the older Sony drives with its own interface card (Sony bus).
-The DOS driver for this drive is named SONY_CDU.SYS - when you boot DOS
-your drive should be identified as a SONY CDU-535. The driver works
-with a CDU-531 also. One user reported that the driver worked on drives
-OEM'ed by Procomm, drive and interface board were labelled Procomm.
-
-The Linux driver is based on Corey Minyard's sonycd 0.3 driver for
-the CDU-31A. Ron Jeppesen just changed the commands that were sent
-to the drive to correspond to the CDU-535 commands and registers.
-There were enough changes to let bugs creep in but it seems to be stable.
-Ron was able to tar an entire CDROM (should read all blocks) and built
-ghostview and xfig off Walnut Creek's X11R5/GNU CDROM. xcdplayer and
-workman work with the driver. Others have used the driver without
-problems except those dealing with wait loops (fixed in third release).
-Like Minyard's original driver this one uses a polled interface (this
-is also the default setup for the DOS driver). It has not been tried
-with interrupts or DMA enabled on the board.
-
-REQUIREMENTS
-============
-
- - Sony CDU-535 drive, preferably without interrupts and DMA
- enabled on the card.
-
- - Drive must be set up as unit 1. Only the first unit will be
- recognized
-
- - You must enter your interface address into
- /usr/src/linux/drivers/cdrom/sonycd535.h and build the
- appropriate kernel or use the "kernel command line" parameter
- sonycd535=0x320
- with the correct interface address.
-
-NOTES:
-======
-
-1) The drive MUST be turned on when booting or it will not be recognized!
- (but see comments on modularized version below)
-
-2) when the cdrom device is opened the eject button is disabled to keep the
- user from ejecting a mounted disk and replacing it with another.
- Unfortunately xcdplayer and workman also open the cdrom device so you
- have to use the eject button in the software. Keep this in mind if your
- cdrom player refuses to give up its disk -- exit workman or xcdplayer, or
- umount the drive if it has been mounted.
-
-THANKS
-======
-
-Many thanks to Ron Jeppesen (ronj.an@site007.saic.com) for getting
-this project off the ground. He wrote the initial release
-and the first two patches to this driver (0.1, 0.2, and 0.3).
-Thanks also to Eberhard Moenkeberg (emoenke@gwdg.de) for prodding
-me to place this code into the mainstream Linux source tree
-(as of Linux version 1.1.91), as well as some patches to make
-it a better device citizen. Further thanks to Joel Katz
-<joelkatz@webchat.org> for his MODULE patches (see details below),
-Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
-to make the driver work with the older CDU-510/515 series, and
-Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
-the verify_area() checks were ignoring the results of said checks
-(note: verify_area() has since been replaced by access_ok()).
-
-(Acknowledgments from Ron Jeppesen in the 0.3 release:)
-Thanks to Corey Minyard who wrote the original CDU-31A driver on which
-this driver is based. Thanks to Ken Pizzini and Bob Blair who provided
-patches and feedback on the first release of this driver.
-
-Ken Pizzini
-ken@halcyon.com
-
-------------------------------------------------------------------------------
-(The following is from Joel Katz <joelkatz@webchat.org>.)
-
- To build a version of sony535.o that can be installed as a module,
-use the following command:
-
-gcc -c -D__KERNEL__ -DMODULE -O2 sonycd535.c -o sonycd535.o
-
- To install the module, simply type:
-
-insmod sony535.o
- or
-insmod sony535.o sonycd535=<address>
-
- And to remove it:
-
-rmmod sony535
-
- The code checks to see if MODULE is defined and behaves as it used
-to if MODULE is not defined. That means your patched file should behave
-exactly as it used to if compiled into the kernel.
-
- I have an external drive, and I usually leave it powered off. I used
-to have to reboot if I needed to use the CDROM drive. Now I don't.
-
- Even if you have an internal drive, why waste the 96K of memory
-(unswappable) that the driver uses if you use your CD-ROM drive infrequently?
-
- This driver will not install (whether compiled in or loaded as a
-module) if the CDROM drive is not available during its initialization. This
-means that you can have the driver compiled into the kernel and still load
-the module later (assuming the driver doesn't install itself during
-power-on). This only wastes 12K when you boot with the CDROM drive off.
-
- This is what I usually do; I leave the driver compiled into the
-kernel, but load it as a module if I powered the system up with the drive
-off and then later decided to use the CDROM drive.
-
- Since the driver only uses a single page to point to the chunks,
-attempting to set the buffer cache to more than 2 Megabytes would be very
-bad; don't do that.
diff --git a/Documentation/fault-injection/failcmd.sh b/Documentation/fault-injection/failcmd.sh
deleted file mode 100644
index 63177aba8106..000000000000
--- a/Documentation/fault-injection/failcmd.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-echo 1 > /proc/self/make-it-fail
-exec $*
diff --git a/Documentation/fault-injection/failmodule.sh b/Documentation/fault-injection/failmodule.sh
deleted file mode 100644
index 474a8b971f9c..000000000000
--- a/Documentation/fault-injection/failmodule.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#
-# Usage: failmodule <failname> <modulename> [stacktrace-depth]
-#
-# <failname>: "failslab", "fail_alloc_page", or "fail_make_request"
-#
-# <modulename>: module name that you want to inject faults.
-#
-# [stacktrace-depth]: the maximum number of stacktrace walking allowed
-#
-
-STACKTRACE_DEPTH=5
-if [ $# -gt 2 ]; then
- STACKTRACE_DEPTH=$3
-fi
-
-if [ ! -d /debug/$1 ]; then
- echo "Fault-injection $1 does not exist" >&2
- exit 1
-fi
-if [ ! -d /sys/module/$2 ]; then
- echo "Module $2 does not exist" >&2
- exit 1
-fi
-
-# Disable any fault injection
-echo 0 > /debug/$1/stacktrace-depth
-
-echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start
-echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end
-echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
index b7ca560b9340..4bc374a14345 100644
--- a/Documentation/fault-injection/fault-injection.txt
+++ b/Documentation/fault-injection/fault-injection.txt
@@ -103,6 +103,11 @@ configuration of fault-injection capabilities.
default is 'N', setting it to 'Y' will inject failures
only into non-sleep allocations (GFP_ATOMIC allocations).
+- /debug/fail_page_alloc/min-order:
+
+ specifies the minimum page allocation order to be injected
+ failures.
+
o Boot option
In order to inject faults while debugfs is not available (early boot time),
@@ -156,70 +161,77 @@ o add a hook to insert failures
Application Examples
--------------------
-o inject slab allocation failures into module init/cleanup code
+o Inject slab allocation failures into module init/exit code
-------------------------------------------------------------------------------
#!/bin/bash
-FAILCMD=Documentation/fault-injection/failcmd.sh
-BLACKLIST="root_plug evbug"
-
-FAILNAME=failslab
-echo Y > /debug/$FAILNAME/task-filter
-echo 10 > /debug/$FAILNAME/probability
-echo 100 > /debug/$FAILNAME/interval
-echo -1 > /debug/$FAILNAME/times
-echo 2 > /debug/$FAILNAME/verbose
-echo 1 > /debug/$FAILNAME/ignore-gfp-wait
+FAILTYPE=failslab
+echo Y > /debug/$FAILTYPE/task-filter
+echo 10 > /debug/$FAILTYPE/probability
+echo 100 > /debug/$FAILTYPE/interval
+echo -1 > /debug/$FAILTYPE/times
+echo 0 > /debug/$FAILTYPE/space
+echo 2 > /debug/$FAILTYPE/verbose
+echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
-blacklist()
+faulty_system()
{
- echo $BLACKLIST | grep $1 > /dev/null 2>&1
+ bash -c "echo 1 > /proc/self/make-it-fail && exec $*"
}
-oops()
-{
- dmesg | grep BUG > /dev/null 2>&1
-}
+if [ $# -eq 0 ]
+then
+ echo "Usage: $0 modulename [ modulename ... ]"
+ exit 1
+fi
+
+for m in $*
+do
+ echo inserting $m...
+ faulty_system modprobe $m
-find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; |
- while read i
- do
- oops && exit 1
-
- if ! blacklist $i
- then
- echo inserting $i...
- bash $FAILCMD modprobe $i
- fi
- done
-
-lsmod | awk '{ if ($3 == 0) { print $1 } }' |
- while read i
- do
- oops && exit 1
-
- if ! blacklist $i
- then
- echo removing $i...
- bash $FAILCMD modprobe -r $i
- fi
- done
+ echo removing $m...
+ faulty_system modprobe -r $m
+done
------------------------------------------------------------------------------
-o inject slab allocation failures only for a specific module
+o Inject page allocation failures only for a specific module
-------------------------------------------------------------------------------
#!/bin/bash
-FAILMOD=Documentation/fault-injection/failmodule.sh
+FAILTYPE=fail_page_alloc
+module=$1
-echo injecting errors into the module $1...
+if [ -z $module ]
+then
+ echo "Usage: $0 <modulename>"
+ exit 1
+fi
-modprobe $1
-bash $FAILMOD failslab $1 10
-echo 25 > /debug/failslab/probability
+modprobe $module
-------------------------------------------------------------------------------
+if [ ! -d /sys/module/$module/sections ]
+then
+ echo Module $module is not loaded
+ exit 1
+fi
+
+cat /sys/module/$module/sections/.text > /debug/$FAILTYPE/require-start
+cat /sys/module/$module/sections/.data > /debug/$FAILTYPE/require-end
+
+echo N > /debug/$FAILTYPE/task-filter
+echo 10 > /debug/$FAILTYPE/probability
+echo 100 > /debug/$FAILTYPE/interval
+echo -1 > /debug/$FAILTYPE/times
+echo 0 > /debug/$FAILTYPE/space
+echo 2 > /debug/$FAILTYPE/verbose
+echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
+echo 1 > /debug/$FAILTYPE/ignore-gfp-highmem
+echo 10 > /debug/$FAILTYPE/stacktrace-depth
+
+trap "echo 0 > /debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
+
+echo "Injecting errors into the module $module... (interrupt to stop)"
+sleep 1000000
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 092c65dd35c2..d05e6243b4df 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -41,14 +41,6 @@ Who: Pavel Machek <pavel@suse.cz>
---------------------------
-What: RAW driver (CONFIG_RAW_DRIVER)
-When: December 2005
-Why: declared obsolete since kernel 2.6.3
- O_DIRECT can be used instead
-Who: Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
What: old NCR53C9x driver
When: October 2007
Why: Replaced by the much better esp_scsi driver. Actual low-level
@@ -119,13 +111,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: drivers depending on OSS_OBSOLETE_DRIVER
-When: options in 2.6.20, code in 2.6.22
-Why: OSS drivers with ALSA replacements
-Who: Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
(temporary transition config option provided until then)
The transition config option will also be removed at the same time.
@@ -264,6 +249,14 @@ Who: Jean Delvare <khali@linux-fr.org>
---------------------------
+What: 'time' kernel boot parameter
+When: January 2008
+Why: replaced by 'printk.time=<value>' so that printk timestamps can be
+ enabled or disabled as needed
+Who: Randy Dunlap <randy.dunlap@oracle.com>
+
+---------------------------
+
What: drivers depending on OSS_OBSOLETE
When: options in 2.6.23, code in 2.6.25
Why: obsolete OSS drivers
@@ -304,3 +297,16 @@ Why: Obsolete for multiple years now, NAT core provides the same behaviour.
Who: Patrick McHardy <kaber@trash.net>
---------------------------
+
+What: The arch/ppc and include/asm-ppc directories
+When: Jun 2008
+Why: The arch/powerpc tree is the merged architecture for ppc32 and ppc64
+ platforms. Currently there are efforts underway to port the remaining
+ arch/ppc platforms to the merged tree. New submissions to the arch/ppc
+ tree have been frozen with the 2.6.22 kernel release and that tree will
+ remain in bug-fix only mode until its scheduled removal. Platforms
+ that are not ported by June 2008 will be removed due to the lack of an
+ interested maintainer.
+Who: linuxppc-dev@ozlabs.org
+
+---------------------------
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index b34cdb50eab4..d1b98257d000 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -238,6 +238,8 @@ config_item_type.
struct config_group *(*make_group)(struct config_group *group,
const char *name);
int (*commit_item)(struct config_item *item);
+ void (*disconnect_notify)(struct config_group *group,
+ struct config_item *item);
void (*drop_item)(struct config_group *group,
struct config_item *item);
};
@@ -268,6 +270,16 @@ the item in other threads, the memory is safe. It may take some time
for the item to actually disappear from the subsystem's usage. But it
is gone from configfs.
+When drop_item() is called, the item's linkage has already been torn
+down. It no longer has a reference on its parent and has no place in
+the item hierarchy. If a client needs to do some cleanup before this
+teardown happens, the subsystem can implement the
+ct_group_ops->disconnect_notify() method. The method is called after
+configfs has removed the item from the filesystem view but before the
+item is removed from its parent group. Like drop_item(),
+disconnect_notify() is void and cannot fail. Client subsystems should
+not drop any references here, as they still must do it in drop_item().
+
A config_group cannot be removed while it still has child items. This
is implemented in the configfs rmdir(2) code. ->drop_item() will not be
called, as the item has not been dropped. rmdir(2) will fail, as the
@@ -280,18 +292,18 @@ tells configfs to make the subsystem appear in the file tree.
struct configfs_subsystem {
struct config_group su_group;
- struct semaphore su_sem;
+ struct mutex su_mutex;
};
int configfs_register_subsystem(struct configfs_subsystem *subsys);
void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
- A subsystem consists of a toplevel config_group and a semaphore.
+ A subsystem consists of a toplevel config_group and a mutex.
The group is where child config_items are created. For a subsystem,
this group is usually defined statically. Before calling
configfs_register_subsystem(), the subsystem must have initialized the
group via the usual group _init() functions, and it must also have
-initialized the semaphore.
+initialized the mutex.
When the register call returns, the subsystem is live, and it
will be visible via configfs. At that point, mkdir(2) can be called and
the subsystem must be ready for it.
@@ -303,7 +315,7 @@ subsystem/group and the simple_child item in configfs_example.c It
shows a trivial object displaying and storing an attribute, and a simple
group creating and destroying these children.
-[Hierarchy Navigation and the Subsystem Semaphore]
+[Hierarchy Navigation and the Subsystem Mutex]
There is an extra bonus that configfs provides. The config_groups and
config_items are arranged in a hierarchy due to the fact that they
@@ -314,19 +326,19 @@ and config_item->ci_parent structure members.
A subsystem can navigate the cg_children list and the ci_parent pointer
to see the tree created by the subsystem. This can race with configfs'
-management of the hierarchy, so configfs uses the subsystem semaphore to
+management of the hierarchy, so configfs uses the subsystem mutex to
protect modifications. Whenever a subsystem wants to navigate the
hierarchy, it must do so under the protection of the subsystem
-semaphore.
+mutex.
-A subsystem will be prevented from acquiring the semaphore while a newly
+A subsystem will be prevented from acquiring the mutex while a newly
allocated item has not been linked into this hierarchy. Similarly, it
-will not be able to acquire the semaphore while a dropping item has not
+will not be able to acquire the mutex while a dropping item has not
yet been unlinked. This means that an item's ci_parent pointer will
never be NULL while the item is in configfs, and that an item will only
be in its parent's cg_children list for the same duration. This allows
a subsystem to trust ci_parent and cg_children while they hold the
-semaphore.
+mutex.
[Item Aggregation Via symlink(2)]
@@ -386,6 +398,33 @@ As a consequence of this, default_groups cannot be removed directly via
rmdir(2). They also are not considered when rmdir(2) on the parent
group is checking for children.
+[Dependant Subsystems]
+
+Sometimes other drivers depend on particular configfs items. For
+example, ocfs2 mounts depend on a heartbeat region item. If that
+region item is removed with rmdir(2), the ocfs2 mount must BUG or go
+readonly. Not happy.
+
+configfs provides two additional API calls: configfs_depend_item() and
+configfs_undepend_item(). A client driver can call
+configfs_depend_item() on an existing item to tell configfs that it is
+depended on. configfs will then return -EBUSY from rmdir(2) for that
+item. When the item is no longer depended on, the client driver calls
+configfs_undepend_item() on it.
+
+These API cannot be called underneath any configfs callbacks, as
+they will conflict. They can block and allocate. A client driver
+probably shouldn't calling them of its own gumption. Rather it should
+be providing an API that external subsystems call.
+
+How does this work? Imagine the ocfs2 mount process. When it mounts,
+it asks for a heartbeat region item. This is done via a call into the
+heartbeat code. Inside the heartbeat code, the region item is looked
+up. Here, the heartbeat code calls configfs_depend_item(). If it
+succeeds, then heartbeat knows the region is safe to give to ocfs2.
+If it fails, it was being torn down anyway, and heartbeat can gracefully
+pass up an error.
+
[Committable Items]
NOTE: Committable items are currently unimplemented.
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c
index 2d6a14a463e0..e56d49264b39 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example.c
@@ -453,7 +453,7 @@ static int __init configfs_example_init(void)
subsys = example_subsys[i];
config_group_init(&subsys->su_group);
- init_MUTEX(&subsys->su_sem);
+ mutex_init(&subsys->su_mutex);
ret = configfs_register_subsystem(subsys);
if (ret) {
printk(KERN_ERR "Error %d while registering subsystem %s\n",
diff --git a/Documentation/ecryptfs.txt b/Documentation/filesystems/ecryptfs.txt
index 01d8a08351ac..01d8a08351ac 100644
--- a/Documentation/ecryptfs.txt
+++ b/Documentation/filesystems/ecryptfs.txt
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 8756a07f4dc3..ebffdffb3d99 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -171,7 +171,9 @@ read the file /proc/PID/status:
This shows you nearly the same information you would get if you viewed it with
the ps command. In fact, ps uses the proc file system to obtain its
information. The statm file contains more detailed information about the
-process memory usage. Its seven fields are explained in Table 1-2.
+process memory usage. Its seven fields are explained in Table 1-2. The stat
+file contains details information about the process itself. Its fields are
+explained in Table 1-3.
Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
@@ -188,16 +190,65 @@ Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
dt number of dirty pages (always 0 on 2.6)
..............................................................................
+
+Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
+..............................................................................
+ Field Content
+ pid process id
+ tcomm filename of the executable
+ state state (R is running, S is sleeping, D is sleeping in an
+ uninterruptible wait, Z is zombie, T is traced or stopped)
+ ppid process id of the parent process
+ pgrp pgrp of the process
+ sid session id
+ tty_nr tty the process uses
+ tty_pgrp pgrp of the tty
+ flags task flags
+ min_flt number of minor faults
+ cmin_flt number of minor faults with child's
+ maj_flt number of major faults
+ cmaj_flt number of major faults with child's
+ utime user mode jiffies
+ stime kernel mode jiffies
+ cutime user mode jiffies with child's
+ cstime kernel mode jiffies with child's
+ priority priority level
+ nice nice level
+ num_threads number of threads
+ start_time time the process started after system boot
+ vsize virtual memory size
+ rss resident set memory size
+ rsslim current limit in bytes on the rss
+ start_code address above which program text can run
+ end_code address below which program text can run
+ start_stack address of the start of the stack
+ esp current value of ESP
+ eip current value of EIP
+ pending bitmap of pending signals (obsolete)
+ blocked bitmap of blocked signals (obsolete)
+ sigign bitmap of ignored signals (obsolete)
+ sigcatch bitmap of catched signals (obsolete)
+ wchan address where process went to sleep
+ 0 (place holder)
+ 0 (place holder)
+ exit_signal signal to send to parent thread on exit
+ task_cpu which CPU the task is scheduled on
+ rt_priority realtime priority
+ policy scheduling policy (man sched_setscheduler)
+ blkio_ticks time spent waiting for block IO
+..............................................................................
+
+
1.2 Kernel data
---------------
Similar to the process entries, the kernel data files give information about
the running kernel. The files used to obtain this information are contained in
-/proc and are listed in Table 1-3. Not all of these will be present in your
+/proc and are listed in Table 1-4. Not all of these will be present in your
system. It depends on the kernel configuration and the loaded modules, which
files are there, and which are missing.
-Table 1-3: Kernel info in /proc
+Table 1-4: Kernel info in /proc
..............................................................................
File Content
apm Advanced power management info
@@ -473,10 +524,10 @@ IDE devices:
More detailed information can be found in the controller specific
subdirectories. These are named ide0, ide1 and so on. Each of these
-directories contains the files shown in table 1-4.
+directories contains the files shown in table 1-5.
-Table 1-4: IDE controller info in /proc/ide/ide?
+Table 1-5: IDE controller info in /proc/ide/ide?
..............................................................................
File Content
channel IDE channel (0 or 1)
@@ -486,11 +537,11 @@ Table 1-4: IDE controller info in /proc/ide/ide?
..............................................................................
Each device connected to a controller has a separate subdirectory in the
-controllers directory. The files listed in table 1-5 are contained in these
+controllers directory. The files listed in table 1-6 are contained in these
directories.
-Table 1-5: IDE device information
+Table 1-6: IDE device information
..............................................................................
File Content
cache The cache
@@ -1297,6 +1348,21 @@ nr_hugepages configures number of hugetlb page reserved for the system.
hugetlb_shm_group contains group id that is allowed to create SysV shared
memory segment using hugetlb page.
+hugepages_treat_as_movable
+--------------------------
+
+This parameter is only useful when kernelcore= is specified at boot time to
+create ZONE_MOVABLE for pages that may be reclaimed or migrated. Huge pages
+are not movable so are not normally allocated from ZONE_MOVABLE. A non-zero
+value written to hugepages_treat_as_movable allows huge pages to be allocated
+from ZONE_MOVABLE.
+
+Once enabled, the ZONE_MOVABLE is treated as an area of memory the huge
+pages pool can easily grow or shrink within. Assuming that applications are
+not running that mlock() a lot of memory, it is likely the huge pages pool
+can grow to the size of ZONE_MOVABLE by repeatedly entering the desired value
+into nr_hugepages and triggering page reclaim.
+
laptop_mode
-----------
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index a47cc819f37b..045f3e055a28 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -3,7 +3,7 @@
Original author: Richard Gooch <rgooch@atnf.csiro.au>
- Last updated on October 28, 2005
+ Last updated on June 24, 2007.
Copyright (C) 1999 Richard Gooch
Copyright (C) 2005 Pekka Enberg
@@ -107,7 +107,7 @@ file /proc/filesystems.
struct file_system_type
-----------------------
-This describes the filesystem. As of kernel 2.6.13, the following
+This describes the filesystem. As of kernel 2.6.22, the following
members are defined:
struct file_system_type {
@@ -119,6 +119,8 @@ struct file_system_type {
struct module *owner;
struct file_system_type * next;
struct list_head fs_supers;
+ struct lock_class_key s_lock_key;
+ struct lock_class_key s_umount_key;
};
name: the name of the filesystem type, such as "ext2", "iso9660",
@@ -137,11 +139,12 @@ struct file_system_type {
next: for internal VFS use: you should initialize this to NULL
+ s_lock_key, s_umount_key: lockdep-specific
+
The get_sb() method has the following arguments:
- struct super_block *sb: the superblock structure. This is partially
- initialized by the VFS and the rest must be initialized by the
- get_sb() method
+ struct file_system_type *fs_type: decribes the filesystem, partly initialized
+ by the specific filesystem code
int flags: mount flags
@@ -150,12 +153,13 @@ The get_sb() method has the following arguments:
void *data: arbitrary mount options, usually comes as an ASCII
string
- int silent: whether or not to be silent on error
+ struct vfsmount *mnt: a vfs-internal representation of a mount point
The get_sb() method must determine if the block device specified
-in the superblock contains a filesystem of the type the method
-supports. On success the method returns the superblock pointer, on
-failure it returns NULL.
+in the dev_name and fs_type contains a filesystem of the type the method
+supports. If it succeeds in opening the named block device, it initializes a
+struct super_block descriptor for the filesystem contained by the block device.
+On failure it returns an error.
The most interesting member of the superblock structure that the
get_sb() method fills in is the "s_op" field. This is a pointer to
@@ -193,7 +197,7 @@ struct super_operations
-----------------------
This describes how the VFS can manipulate the superblock of your
-filesystem. As of kernel 2.6.13, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
@@ -216,8 +220,6 @@ struct super_operations {
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
- void (*sync_inodes) (struct super_block *sb,
- struct writeback_control *wbc);
int (*show_options)(struct seq_file *, struct vfsmount *);
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
@@ -300,9 +302,6 @@ or bottom half).
umount_begin: called when the VFS is unmounting a filesystem.
- sync_inodes: called when the VFS is writing out dirty data associated with
- a superblock.
-
show_options: called by the VFS to show mount options for /proc/<pid>/mounts.
quota_read: called by the VFS to read from filesystem quota file.
@@ -324,7 +323,7 @@ struct inode_operations
-----------------------
This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.6.13, the following members are defined:
+filesystem. As of kernel 2.6.22, the following members are defined:
struct inode_operations {
int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
@@ -348,6 +347,7 @@ struct inode_operations {
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
+ void (*truncate_range)(struct inode *, loff_t, loff_t);
};
Again, all methods are called without any locks being held, unless
@@ -444,6 +444,9 @@ otherwise noted.
removexattr: called by the VFS to remove an extended attribute from
a file. This method is called by removexattr(2) system call.
+ truncate_range: a method provided by the underlying filesystem to truncate a
+ range of blocks , i.e. punch a hole somewhere in a file.
+
The Address Space Object
========================
@@ -522,7 +525,7 @@ struct address_space_operations
-------------------------------
This describes how the VFS can manipulate mapping of a file to page cache in
-your filesystem. As of kernel 2.6.16, the following members are defined:
+your filesystem. As of kernel 2.6.22, the following members are defined:
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -543,6 +546,7 @@ struct address_space_operations {
int);
/* migrate the contents of a page to the specified target */
int (*migratepage) (struct page *, struct page *);
+ int (*launder_page) (struct page *);
};
writepage: called by the VM to write a dirty page to backing store.
@@ -689,6 +693,10 @@ struct address_space_operations {
transfer any private data across and update any references
that it has to the page.
+ launder_page: Called before freeing a page - it writes back the dirty page. To
+ prevent redirtying the page, it is kept locked during the whole
+ operation.
+
The File Object
===============
@@ -699,9 +707,10 @@ struct file_operations
----------------------
This describes how the VFS can manipulate an open file. As of kernel
-2.6.17, the following members are defined:
+2.6.22, the following members are defined:
struct file_operations {
+ struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
@@ -728,10 +737,8 @@ struct file_operations {
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
- ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned
-int);
- ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned
-int);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
+ ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
};
Again, all methods are called without any locks being held, unless
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
index 22b0814d0ad0..20d368c59814 100644
--- a/Documentation/hrtimer/timer_stats.txt
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -67,3 +67,7 @@ executed on expiry.
Thomas, Ingo
+Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
+timer will appear as follows
+ 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
+
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 3de7d379cf07..5c7fbf9d96b4 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -67,7 +67,7 @@ Code Seq# Include File Comments
0x00 00-1F linux/wavefront.h conflict!
0x02 all linux/fd.h
0x03 all linux/hdreg.h
-0x04 all linux/umsdos_fs.h
+0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these.
0x06 all linux/lp.h
0x09 all linux/md.h
0x12 all linux/fs.h
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4d880b3d1f35..9a541486fb7e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -34,7 +34,6 @@ parameter is applicable:
APIC APIC support is enabled.
APM Advanced Power Management support is enabled.
AX25 Appropriate AX.25 support is enabled.
- CD Appropriate CD support is enabled.
DRM Direct Rendering Management support is enabled.
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
EFI EFI Partitioning (GPT) is enabled
@@ -238,16 +237,9 @@ and is between 256 and 4096 characters. It is defined in the file
Disable PIN 1 of APIC timer
Can be useful to work around chipset bugs.
- ad1816= [HW,OSS]
- Format: <io>,<irq>,<dma>,<dma2>
- See also Documentation/sound/oss/AD1816.
-
ad1848= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>,<type>
- adlib= [HW,OSS]
- Format: <io>
-
advansys= [HW,SCSI]
See header of drivers/scsi/advansys.c.
@@ -326,9 +318,6 @@ and is between 256 and 4096 characters. It is defined in the file
autotest [IA64]
- aztcd= [HW,CD] Aztech CD268 CDROM driver
- Format: <io>,0x79 (?)
-
baycom_epp= [HW,AX25]
Format: <io>,<mode>
@@ -371,10 +360,6 @@ and is between 256 and 4096 characters. It is defined in the file
possible to determine what the correct size should be.
This option provides an override for these situations.
- cdu31a= [HW,CD]
- Format: <io>,<irq>[,PAS]
- See header of drivers/cdrom/cdu31a.c.
-
chandev= [HW,NET] Generic channel device initialisation
checkreqprot [SELINUX] Set initial checkreqprot flag value.
@@ -428,9 +413,6 @@ and is between 256 and 4096 characters. It is defined in the file
hpet= [IA-32,HPET] option to disable HPET and use PIT.
Format: disable
- cm206= [HW,CD]
- Format: { auto | [<io>,][<irq>] }
-
com20020= [HW,NET] ARCnet - COM20020 chipset
Format:
<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
@@ -462,13 +444,20 @@ and is between 256 and 4096 characters. It is defined in the file
Documentation/networking/netconsole.txt for an
alternative.
- uart,io,<addr>[,options]
- uart,mmio,<addr>[,options]
+ uart[8250],io,<addr>[,options]
+ uart[8250],mmio,<addr>[,options]
Start an early, polled-mode console on the 8250/16550
UART at the specified I/O port or MMIO address,
switching to the matching ttyS device later. The
options are the same as for ttyS, above.
+ earlycon= [KNL] Output early console device and options.
+ uart[8250],io,<addr>[,options]
+ uart[8250],mmio,<addr>[,options]
+ Start an early, polled-mode console on the 8250/16550
+ UART at the specified I/O port or MMIO address.
+ The options are the same as for ttyS, above.
+
cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
Format:
<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -660,9 +649,6 @@ and is between 256 and 4096 characters. It is defined in the file
gpt [EFI] Forces disk with valid GPT signature but
invalid Protective MBR to be treated as GPT.
- gscd= [HW,CD]
- Format: <io>
-
gvp11= [HW,SCSI]
hashdist= [KNL,NUMA] Large hashes allocated during boot
@@ -826,14 +812,37 @@ and is between 256 and 4096 characters. It is defined in the file
tasks in the system -- can cause problems and
suboptimal load balancer performance.
- isp16= [HW,CD]
- Format: <io>,<irq>,<dma>,<setup>
-
iucv= [HW,NET]
js= [HW,JOY] Analog joystick
See Documentation/input/joystick.txt.
+ kernelcore=nn[KMG] [KNL,IA-32,IA-64,PPC,X86-64] This parameter
+ specifies the amount of memory usable by the kernel
+ for non-movable allocations. The requested amount is
+ spread evenly throughout all nodes in the system. The
+ remaining memory in each node is used for Movable
+ pages. In the event, a node is too small to have both
+ kernelcore and Movable pages, kernelcore pages will
+ take priority and other nodes will have a larger number
+ of kernelcore pages. The Movable zone is used for the
+ allocation of pages that may be reclaimed or moved
+ by the page migration subsystem. This means that
+ HugeTLB pages may not be allocated from this zone.
+ Note that allocations like PTEs-from-HighMem still
+ use the HighMem zone if it exists, and the Normal
+ zone if it does not.
+
+ movablecore=nn[KMG] [KNL,IA-32,IA-64,PPC,X86-64] This parameter
+ is similar to kernelcore except it specifies the
+ amount of memory used for migratable allocations.
+ If both kernelcore and movablecore is specified,
+ then kernelcore will be at *least* the specified
+ value but may be more. If movablecore on its own
+ is specified, the administrator must be careful
+ that the amount of memory usable for all allocations
+ is not too small.
+
keepinitrd [HW,ARM]
kstack=N [IA-32,X86-64] Print N words from the kernel stack
@@ -967,11 +976,6 @@ and is between 256 and 4096 characters. It is defined in the file
mcatest= [IA-64]
- mcd= [HW,CD]
- Format: <port>,<irq>,<mitsumi_bug_93_wait>
-
- mcdx= [HW,CD]
-
mce [IA-32] Machine Check Exception
md= [HW] RAID subsystems devices and level
@@ -1181,6 +1185,8 @@ and is between 256 and 4096 characters. It is defined in the file
nosmp [SMP] Tells an SMP kernel to act as a UP kernel.
+ nosoftlockup [KNL] Disable the soft-lockup detector.
+
nosync [HW,M68K] Disables sync negotiation for all devices.
notsc [BUGS=IA-32] Disable Time Stamp Counter
@@ -1189,20 +1195,19 @@ and is between 256 and 4096 characters. It is defined in the file
nowb [ARM]
+ numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
+ one of ['zone', 'node', 'default'] can be specified
+ This can be set from sysctl after boot.
+ See Documentation/sysctl/vm.txt for details.
+
nr_uarts= [SERIAL] maximum number of UARTs to be registered.
opl3= [HW,OSS]
Format: <io>
- opl3sa2= [HW,OSS] Format:
- <io>,<irq>,<dma>,<dma2>,<mss_io>,<mpu_io>,<ymode>,<loopback>[,<isapnp>,<multiple]
-
oprofile.timer= [HW]
Use timer interrupt instead of performance counters
- optcd= [HW,CD]
- Format: <io>
-
osst= [HW,SCSI] SCSI Tape Driver
Format: <buffer_size>,<write_threshold>
See also Documentation/scsi/st.txt.
@@ -1381,6 +1386,15 @@ and is between 256 and 4096 characters. It is defined in the file
autoconfiguration.
Ranges are in pairs (memory base and size).
+ print-fatal-signals=
+ [KNL] debug: print fatal signals
+ print-fatal-signals=1: print segfault info to
+ the kernel console.
+ default: off.
+
+ printk.time= Show timing data prefixed to each printk message line
+ Format: <bool> (1/Y/y=enable, 0/N/n=disable)
+
profile= [KNL] Enable kernel profiling via /proc/profile
Format: [schedule,]<number>
Param: "schedule" - profile schedule points.
@@ -1493,6 +1507,10 @@ and is between 256 and 4096 characters. It is defined in the file
rootfstype= [KNL] Set root filesystem type
+ rootwait [KNL] Wait (indefinitely) for root device to show up.
+ Useful for devices that are detected asynchronously
+ (e.g. USB and MMC devices).
+
rw [KNL] Mount root device read-write on boot
S [KNL] Run init in single mode
@@ -1505,11 +1523,6 @@ and is between 256 and 4096 characters. It is defined in the file
sbni= [NET] Granch SBNI12 leased line adapter
- sbpcd= [HW,CD] Soundblaster CD adapter
- Format: <io>,<type>
- See a comment before function sbpcd_setup() in
- drivers/cdrom/sbpcd.c.
-
sc1200wdt= [HW,WDT] SC1200 WDT (watchdog) driver
Format: <io>[,<timeout>[,<isapnp>]]
@@ -1562,41 +1575,41 @@ and is between 256 and 4096 characters. It is defined in the file
simeth= [IA-64]
simscsi=
- sjcd= [HW,CD]
- Format: <io>,<irq>,<dma>
- See header of drivers/cdrom/sjcd.c.
-
slram= [HW,MTD]
- slub_debug [MM, SLUB]
- Enabling slub_debug allows one to determine the culprit
- if slab objects become corrupted. Enabling slub_debug
- creates guard zones around objects and poisons objects
- when not in use. Also tracks the last alloc / free.
- For more information see Documentation/vm/slub.txt.
+ slub_debug[=options[,slabs]] [MM, SLUB]
+ Enabling slub_debug allows one to determine the
+ culprit if slab objects become corrupted. Enabling
+ slub_debug can create guard zones around objects and
+ may poison objects when not in use. Also tracks the
+ last alloc / free. For more information see
+ Documentation/vm/slub.txt.
slub_max_order= [MM, SLUB]
- Determines the maximum allowed order for slabs. Setting
- this too high may cause fragmentation.
- For more information see Documentation/vm/slub.txt.
+ Determines the maximum allowed order for slabs.
+ A high setting may cause OOMs due to memory
+ fragmentation. For more information see
+ Documentation/vm/slub.txt.
slub_min_objects= [MM, SLUB]
- The minimum objects per slab. SLUB will increase the
- slab order up to slub_max_order to generate a
- sufficiently big slab to satisfy the number of objects.
- The higher the number of objects the smaller the overhead
- of tracking slabs.
+ The minimum number of objects per slab. SLUB will
+ increase the slab order up to slub_max_order to
+ generate a sufficiently large slab able to contain
+ the number of objects indicated. The higher the number
+ of objects the smaller the overhead of tracking slabs
+ and the less frequently locks need to be acquired.
For more information see Documentation/vm/slub.txt.
slub_min_order= [MM, SLUB]
Determines the mininum page order for slabs. Must be
- lower than slub_max_order
+ lower than slub_max_order.
For more information see Documentation/vm/slub.txt.
slub_nomerge [MM, SLUB]
- Disable merging of slabs of similar size. May be
+ Disable merging of slabs with similar size. May be
necessary if there is some reason to distinguish
- allocs to different slabs.
+ allocs to different slabs. Debug options disable
+ merging on their own.
For more information see Documentation/vm/slub.txt.
smart2= [HW]
@@ -1738,9 +1751,6 @@ and is between 256 and 4096 characters. It is defined in the file
snd-ymfpci= [HW,ALSA]
- sonycd535= [HW,CD]
- Format: <io>[,<irq>]
-
sonypi.*= [HW] Sony Programmable I/O Control Device driver
See Documentation/sonypi.txt
@@ -1812,6 +1822,7 @@ and is between 256 and 4096 characters. It is defined in the file
Set number of hash buckets for TCP connection
time Show timing data prefixed to each printk message line
+ [deprecated, see 'printk.time']
tipar.timeout= [HW,PPT]
Set communications timeout in tenths of a second
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt
index 1c41db21d3c1..59108cebe163 100644
--- a/Documentation/m68k/kernel-options.txt
+++ b/Documentation/m68k/kernel-options.txt
@@ -82,13 +82,6 @@ Valid names are:
/dev/fd : -> 0x0200 (floppy disk)
/dev/xda: -> 0x0c00 (first XT disk, unused in Linux/m68k)
/dev/xdb: -> 0x0c40 (second XT disk, unused in Linux/m68k)
- /dev/ada: -> 0x1c00 (first ACSI device)
- /dev/adb: -> 0x1c10 (second ACSI device)
- /dev/adc: -> 0x1c20 (third ACSI device)
- /dev/add: -> 0x1c30 (forth ACSI device)
-
-The last four names are available only if the kernel has been compiled
-with Atari and ACSI support.
The name must be followed by a decimal number, that stands for the
partition number. Internally, the value of the number is just
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
index 0b27863f155c..98c4392dd0fd 100644
--- a/Documentation/networking/net-modules.txt
+++ b/Documentation/networking/net-modules.txt
@@ -146,12 +146,6 @@ at1700.c:
irq = 0
(Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
-atari_bionet.c:
- Supports full autoprobing. (m68k/Atari)
-
-atari_pamsnet.c:
- Supports full autoprobing. (m68k/Atari)
-
atarilance.c:
Supports full autoprobing. (m68k/Atari)
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 7d5b60dea551..7f60dfe642ca 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -86,6 +86,20 @@ stuff are the values reported by the Oops - you can just cut-and-paste
and do a replace of spaces to "\x" - that's what I do, as I'm too lazy
to write a program to automate this all).
+Alternatively, you can use the shell script in scripts/decodecode.
+Its usage is: decodecode < oops.txt
+
+The hex bytes that follow "Code:" may (in some architectures) have a series
+of bytes that precede the current instruction pointer as well as bytes at and
+following the current instruction pointer. In some cases, one instruction
+byte or word is surrounded by <> or (), as in "<86>" or "(f00d)". These
+<> or () markings indicate the current instruction pointer. Example from
+i386, split into multiple lines for readability:
+
+Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
+64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
+7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
+
Finally, if you want to see where the code comes from, you can do
cd /usr/src/linux
@@ -237,6 +251,8 @@ characters, each representing a particular tainted value.
7: 'U' if a user or user application specifically requested that the
Tainted flag be set, ' ' otherwise.
+ 8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
+
The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent: even if an offending module is
diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt
new file mode 100644
index 000000000000..af1a282c71a3
--- /dev/null
+++ b/Documentation/power/freezing-of-tasks.txt
@@ -0,0 +1,160 @@
+Freezing of tasks
+ (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+I. What is the freezing of tasks?
+
+The freezing of tasks is a mechanism by which user space processes and some
+kernel threads are controlled during hibernation or system-wide suspend (on some
+architectures).
+
+II. How does it work?
+
+There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
+and PF_FREEZER_SKIP (the last one is auxiliary). The tasks that have
+PF_NOFREEZE unset (all user space processes and some kernel threads) are
+regarded as 'freezable' and treated in a special way before the system enters a
+suspend state as well as before a hibernation image is created (in what follows
+we only consider hibernation, but the description also applies to suspend).
+
+Namely, as the first step of the hibernation procedure the function
+freeze_processes() (defined in kernel/power/process.c) is called. It executes
+try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
+sends a fake signal to each of them. A task that receives such a signal and has
+TIF_FREEZE set, should react to it by calling the refrigerator() function
+(defined in kernel/power/process.c), which sets the task's PF_FROZEN flag,
+changes its state to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is
+cleared for it. Then, we say that the task is 'frozen' and therefore the set of
+functions handling this mechanism is called 'the freezer' (these functions are
+defined in kernel/power/process.c and include/linux/freezer.h). User space
+processes are generally frozen before kernel threads.
+
+It is not recommended to call refrigerator() directly. Instead, it is
+recommended to use the try_to_freeze() function (defined in
+include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the
+task enter refrigerator() if the flag is set.
+
+For user space processes try_to_freeze() is called automatically from the
+signal-handling code, but the freezable kernel threads need to call it
+explicitly in suitable places. The code to do this may look like the following:
+
+ do {
+ hub_events();
+ wait_event_interruptible(khubd_wait,
+ !list_empty(&hub_event_list));
+ try_to_freeze();
+ } while (!signal_pending(current));
+
+(from drivers/usb/core/hub.c::hub_thread()).
+
+If a freezable kernel thread fails to call try_to_freeze() after the freezer has
+set TIF_FREEZE for it, the freezing of tasks will fail and the entire
+hibernation operation will be cancelled. For this reason, freezable kernel
+threads must call try_to_freeze() somewhere.
+
+After the system memory state has been restored from a hibernation image and
+devices have been reinitialized, the function thaw_processes() is called in
+order to clear the PF_FROZEN flag for each frozen task. Then, the tasks that
+have been frozen leave refrigerator() and continue running.
+
+III. Which kernel threads are freezable?
+
+Kernel threads are not freezable by default. However, a kernel thread may clear
+PF_NOFREEZE for itself by calling set_freezable() (the resetting of PF_NOFREEZE
+directly is strongly discouraged). From this point it is regarded as freezable
+and must call try_to_freeze() in a suitable place.
+
+IV. Why do we do that?
+
+Generally speaking, there is a couple of reasons to use the freezing of tasks:
+
+1. The principal reason is to prevent filesystems from being damaged after
+hibernation. At the moment we have no simple means of checkpointing
+filesystems, so if there are any modifications made to filesystem data and/or
+metadata on disks, we cannot bring them back to the state from before the
+modifications. At the same time each hibernation image contains some
+filesystem-related information that must be consistent with the state of the
+on-disk data and metadata after the system memory state has been restored from
+the image (otherwise the filesystems will be damaged in a nasty way, usually
+making them almost impossible to repair). We therefore freeze tasks that might
+cause the on-disk filesystems' data and metadata to be modified after the
+hibernation image has been created and before the system is finally powered off.
+The majority of these are user space processes, but if any of the kernel threads
+may cause something like this to happen, they have to be freezable.
+
+2. The second reason is to prevent user space processes and some kernel threads
+from interfering with the suspending and resuming of devices. A user space
+process running on a second CPU while we are suspending devices may, for
+example, be troublesome and without the freezing of tasks we would need some
+safeguards against race conditions that might occur in such a case.
+
+Although Linus Torvalds doesn't like the freezing of tasks, he said this in one
+of the discussions on LKML (http://lkml.org/lkml/2007/4/27/608):
+
+"RJW:> Why we freeze tasks at all or why we freeze kernel threads?
+
+Linus: In many ways, 'at all'.
+
+I _do_ realize the IO request queue issues, and that we cannot actually do
+s2ram with some devices in the middle of a DMA. So we want to be able to
+avoid *that*, there's no question about that. And I suspect that stopping
+user threads and then waiting for a sync is practically one of the easier
+ways to do so.
+
+So in practice, the 'at all' may become a 'why freeze kernel threads?' and
+freezing user threads I don't find really objectionable."
+
+Still, there are kernel threads that may want to be freezable. For example, if
+a kernel that belongs to a device driver accesses the device directly, it in
+principle needs to know when the device is suspended, so that it doesn't try to
+access it at that time. However, if the kernel thread is freezable, it will be
+frozen before the driver's .suspend() callback is executed and it will be
+thawed after the driver's .resume() callback has run, so it won't be accessing
+the device while it's suspended.
+
+3. Another reason for freezing tasks is to prevent user space processes from
+realizing that hibernation (or suspend) operation takes place. Ideally, user
+space processes should not notice that such a system-wide operation has occurred
+and should continue running without any problems after the restore (or resume
+from suspend). Unfortunately, in the most general case this is quite difficult
+to achieve without the freezing of tasks. Consider, for example, a process
+that depends on all CPUs being online while it's running. Since we need to
+disable nonboot CPUs during the hibernation, if this process is not frozen, it
+may notice that the number of CPUs has changed and may start to work incorrectly
+because of that.
+
+V. Are there any problems related to the freezing of tasks?
+
+Yes, there are.
+
+First of all, the freezing of kernel threads may be tricky if they depend one
+on another. For example, if kernel thread A waits for a completion (in the
+TASK_UNINTERRUPTIBLE state) that needs to be done by freezable kernel thread B
+and B is frozen in the meantime, then A will be blocked until B is thawed, which
+may be undesirable. That's why kernel threads are not freezable by default.
+
+Second, there are the following two problems related to the freezing of user
+space processes:
+1. Putting processes into an uninterruptible sleep distorts the load average.
+2. Now that we have FUSE, plus the framework for doing device drivers in
+userspace, it gets even more complicated because some userspace processes are
+now doing the sorts of things that kernel threads do
+(https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html).
+
+The problem 1. seems to be fixable, although it hasn't been fixed so far. The
+other one is more serious, but it seems that we can work around it by using
+hibernation (and suspend) notifiers (in that case, though, we won't be able to
+avoid the realization by the user space processes that the hibernation is taking
+place).
+
+There are also problems that the freezing of tasks tends to expose, although
+they are not directly related to it. For example, if request_firmware() is
+called from a device driver's .resume() routine, it will timeout and eventually
+fail, because the user land process that should respond to the request is frozen
+at this point. So, seemingly, the failure is due to the freezing of tasks.
+Suppose, however, that the firmware file is located on a filesystem accessible
+only through another device that hasn't been resumed yet. In that case,
+request_firmware() will fail regardless of whether or not the freezing of tasks
+is used. Consequently, the problem is not really related to the freezing of
+tasks, since it generally exists anyway. [The solution to this particular
+problem is to keep the firmware in memory after it's loaded for the first time
+and upload if from memory to the device whenever necessary.]
diff --git a/Documentation/power/kernel_threads.txt b/Documentation/power/kernel_threads.txt
deleted file mode 100644
index fb57784986b1..000000000000
--- a/Documentation/power/kernel_threads.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-KERNEL THREADS
-
-
-Freezer
-
-Upon entering a suspended state the system will freeze all
-tasks. This is done by delivering pseudosignals. This affects
-kernel threads, too. To successfully freeze a kernel thread
-the thread has to check for the pseudosignal and enter the
-refrigerator. Code to do this looks like this:
-
- do {
- hub_events();
- wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
- try_to_freeze();
- } while (!signal_pending(current));
-
-from drivers/usb/core/hub.c::hub_thread()
-
-
-The Unfreezable
-
-Some kernel threads however, must not be frozen. The kernel must
-be able to finish pending IO operations and later on be able to
-write the memory image to disk. Kernel threads needed to do IO
-must stay awake. Such threads must mark themselves unfreezable
-like this:
-
- /*
- * This thread doesn't need any user-level access,
- * so get rid of all our resources.
- */
- daemonize("usb-storage");
-
- current->flags |= PF_NOFREEZE;
-
-from drivers/usb/storage/usb.c::usb_stor_control_thread()
-
-Such drivers are themselves responsible for staying quiet during
-the actual snapshotting.
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 152b510d1bbb..aea7e9209667 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -140,21 +140,11 @@ should be sent to the mailing list available through the suspend2
website, and not to the Linux Kernel Mailing List. We are working
toward merging suspend2 into the mainline kernel.
-Q: A kernel thread must voluntarily freeze itself (call 'refrigerator').
-I found some kernel threads that don't do it, and they don't freeze
-so the system can't sleep. Is this a known behavior?
-
-A: All such kernel threads need to be fixed, one by one. Select the
-place where the thread is safe to be frozen (no kernel semaphores
-should be held at that point and it must be safe to sleep there), and
-add:
-
- try_to_freeze();
-
-If the thread is needed for writing the image to storage, you should
-instead set the PF_NOFREEZE process flag when creating the thread (and
-be very careful).
+Q: What is the freezing of tasks and why are we using it?
+A: The freezing of tasks is a mechanism by which user space processes and some
+kernel threads are controlled during hibernation or system-wide suspend (on some
+architectures). See freezing-of-tasks.txt for details.
Q: What is the difference between "platform" and "shutdown"?
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index d42d98107d49..0c2434822094 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -42,15 +42,16 @@ Table of Contents
1) Defining child nodes of an SOC
2) Representing devices without a current OF specification
a) MDIO IO device
- c) PHY nodes
b) Gianfar-compatible ethernet nodes
+ c) PHY nodes
d) Interrupt controllers
e) I2C
f) Freescale SOC USB controllers
g) Freescale SOC SEC Security Engines
h) Board Control and Status (BCSR)
i) Freescale QUICC Engine module (QE)
- g) Flash chip nodes
+ j) Flash chip nodes
+ k) Global Utilities Block
VII - Specifying interrupt information for devices
1) interrupts property
@@ -626,6 +627,14 @@ So the node content can be summarized as a start token, a full path,
a list of properties, a list of child nodes, and an end token. Every
child node is a full node structure itself as defined above.
+NOTE: The above definition requires that all property definitions for
+a particular node MUST precede any subnode definitions for that node.
+Although the structure would not be ambiguous if properties and
+subnodes were intermingled, the kernel parser requires that the
+properties come first (up until at least 2.6.22). Any tools
+manipulating a flattened tree must take care to preserve this
+constraint.
+
4) Device tree "strings" block
In order to save space, property names, which are generally redundant,
@@ -1782,6 +1791,33 @@ platforms are moved over to use the flattened-device-tree model.
partition-names = "fs\0firmware";
};
+ k) Global Utilities Block
+
+ The global utilities block controls power management, I/O device
+ enabling, power-on-reset configuration monitoring, general-purpose
+ I/O signal configuration, alternate function selection for multiplexed
+ signals, and clock control.
+
+ Required properties:
+
+ - compatible : Should define the compatible device type for
+ global-utilities.
+ - reg : Offset and length of the register set for the device.
+
+ Recommended properties:
+
+ - fsl,has-rstcr : Indicates that the global utilities register set
+ contains a functioning "reset control register" (i.e. the board
+ is wired to reset upon setting the HRESET_REQ bit in this register).
+
+ Example:
+
+ global-utilities@e0000 { /* global utilities block */
+ compatible = "fsl,mpc8548-guts";
+ reg = <e0000 1000>;
+ fsl,has-rstcr;
+ };
+
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 7c701b88d6d5..c931d613f641 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -385,7 +385,7 @@ test_PIE:
/* not all RTCs support periodic IRQs */
if (errno == ENOTTY) {
fprintf(stderr, "\nNo periodic IRQ support\n");
- return 0;
+ goto done;
}
perror("RTC_IRQP_READ ioctl");
exit(errno);
diff --git a/Documentation/sound/oss/AD1816 b/Documentation/sound/oss/AD1816
deleted file mode 100644
index 14bd8f25d523..000000000000
--- a/Documentation/sound/oss/AD1816
+++ /dev/null
@@ -1,84 +0,0 @@
-Documentation for the AD1816(A) sound driver
-============================================
-
-Installation:
--------------
-
-To get your AD1816(A) based sound card work, you'll have to enable support for
-experimental code ("Prompt for development and/or incomplete code/drivers")
-and isapnp ("Plug and Play support", "ISA Plug and Play support"). Enable
-"Sound card support", "OSS modules support" and "Support for AD1816(A) based
-cards (EXPERIMENTAL)" in the sound configuration menu, too. Now build, install
-and reboot the new kernel as usual.
-
-Features:
----------
-
-List of features supported by this driver:
-- full-duplex support
-- supported audio formats: unsigned 8bit, signed 16bit little endian,
- signed 16bit big endian, µ-law, A-law
-- supported channels: mono and stereo
-- supported recording sources: Master, CD, Line, Line1, Line2, Mic
-- supports phat 3d stereo circuit (Line 3)
-
-
-Supported cards:
-----------------
-
-The following cards are known to work with this driver:
-- Terratec Base 1
-- Terratec Base 64
-- HP Kayak
-- Acer FX-3D
-- SY-1816
-- Highscreen Sound-Boostar 32 Wave 3D
-- Highscreen Sound-Boostar 16
-- AVM Apex Pro card
-- (Aztech SC-16 3D)
-- (Newcom SC-16 3D)
-- (Terratec EWS64S)
-
-Cards listed in brackets are not supported reliable. If you have such a card
-you should add the extra parameter:
- options=1
-when loading the ad1816 module via modprobe.
-
-
-Troubleshooting:
-----------------
-
-First of all you should check, if the driver has been loaded
-properly.
-
-If loading of the driver succeeds, but playback/capture fails, check
-if you used the correct values for irq, dma and dma2 when loading the module.
-If one of them is wrong you usually get the following error message:
-
-Nov 6 17:06:13 tek01 kernel: Sound: DMA (output) timed out - IRQ/DRQ config error?
-
-If playback/capture is too fast or to slow, you should have a look at
-the clock chip of your sound card. The AD1816 was designed for a 33MHz
-oscillator, however most sound card manufacturer use slightly
-different oscillators as they are cheaper than 33MHz oscillators. If
-you have such a card you have to adjust the ad1816_clockfreq parameter
-above. For example: For a card using a 32.875MHz oscillator use
-ad1816_clockfreq=32875 instead of ad1816_clockfreq=33000.
-
-
-Updates, bugfixes and bugreports:
---------------------------------
-
-As the driver is still experimental and under development, you should
-watch out for updates. Updates of the driver are available on the
-Internet from one of my home pages:
- http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
-or:
- http://www.tu-darmstadt.de/~tek01/projects/linux.html
-
-Bugreports, bugfixes and related questions should be sent via E-Mail to:
- tek@rbg.informatik.tu-darmstadt.de
-
-Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
-Christoph Hellwig <hch@infradead.org>
- Last modified: 2000/09/20
diff --git a/Documentation/sound/oss/NM256 b/Documentation/sound/oss/NM256
deleted file mode 100644
index b503217488b3..000000000000
--- a/Documentation/sound/oss/NM256
+++ /dev/null
@@ -1,280 +0,0 @@
-=======================================================
-Documentation for the NeoMagic 256AV/256ZX sound driver
-=======================================================
-
-You're looking at version 1.1 of the driver. (Woohoo!) It has been
-successfully tested against the following laptop models:
-
- Sony Z505S/Z505SX/Z505DX/Z505RX
- Sony F150, F160, F180, F250, F270, F280, PCG-F26
- Dell Latitude CPi, CPt (various submodels)
-
-There are a few caveats, which is why you should read the entirety of
-this document first.
-
-This driver was developed without any support or assistance from
-NeoMagic. There is no warranty, expressed, implied, or otherwise. It
-is free software in the public domain; feel free to use it, sell it,
-give it to your best friends, even claim that you wrote it (but why?!)
-but don't go whining to me, NeoMagic, Sony, Dell, or anyone else
-when it blows up your computer.
-
-Version 1.1 contains a change to try and detect non-AC97 versions of
-the hardware, and not install itself appropriately. It should also
-reinitialize the hardware on an APM resume event, assuming that APM
-was configured into your kernel.
-
-============
-Installation
-============
-
-Enable the sound drivers, the OSS sound drivers, and then the NM256
-driver. The NM256 driver *must* be configured as a module (it won't
-give you any other choice).
-
-Next, do the usual "make modules" and "make modules_install".
-Finally, insmod the soundcore, sound and nm256 modules.
-
-When the nm256 driver module is loaded, you should see a couple of
-confirmation messages in the kernel logfile indicating that it found
-the device (the device does *not* use any I/O ports or DMA channels).
-Now try playing a wav file, futz with the CD-ROM if you have one, etc.
-
-The NM256 is entirely a PCI-based device, and all the necessary
-information is automatically obtained from the card. It can only be
-configured as a module in a vain attempt to prevent people from
-hurting themselves. It works correctly if it shares an IRQ with
-another device (it normally shares IRQ 9 with the builtin eepro100
-ethernet on the Sony Z505 laptops).
-
-It does not run the card in any sort of compatibility mode. It will
-not work on laptops that have the SB16-compatible, AD1848-compatible
-or CS4232-compatible codec/mixer; you will want to use the appropriate
-compatible OSS driver with these chipsets. I cannot provide any
-assistance with machines using the SB16, AD1848 or CS4232 compatible
-versions. (The driver now attempts to detect the mixer version, and
-will refuse to load if it believes the hardware is not
-AC97-compatible.)
-
-The sound support is very basic, but it does include simultaneous
-playback and record capability. The mixer support is also quite
-simple, although this is in keeping with the rather limited
-functionality of the chipset.
-
-There is no hardware synthesizer available, as the Losedows OPL-3 and
-MIDI support is done via hardware emulation.
-
-Only three recording devices are available on the Sony: the
-microphone, the CD-ROM input, and the volume device (which corresponds
-to the stereo output). (Other devices may be available on other
-models of laptops.) The Z505 series does not have a builtin CD-ROM,
-so of course the CD-ROM input doesn't work. It does work on laptops
-with a builtin CD-ROM drive.
-
-The mixer device does not appear to have any tone controls, at least
-on the Z505 series. The mixer module checks for tone controls in the
-AC97 mixer, and will enable them if they are available.
-
-==============
-Known problems
-==============
-
- * There are known problems with PCMCIA cards and the eepro100 ethernet
- driver on the Z505S/Z505SX/Z505DX. Keep reading.
-
- * There are also potential problems with using a virtual X display, and
- also problems loading the module after the X server has been started.
- Keep reading.
-
- * The volume control isn't anywhere near linear. Sorry. This will be
- fixed eventually, when I get sufficiently annoyed with it. (I doubt
- it will ever be fixed now, since I've never gotten sufficiently
- annoyed with it and nobody else seems to care.)
-
- * There are reports that the CD-ROM volume is very low. Since I do not
- have a CD-ROM equipped laptop, I cannot test this (it's kinda hard to
- do remotely).
-
- * Only 8 fixed-rate speeds are supported. This is mainly a chipset
- limitation. It may be possible to support other speeds in the future.
-
- * There is no support for the telephone mixer/codec. There is support
- for a phonein/phoneout device in the mixer driver; whether or not
- it does anything is anyone's guess. (Reports on this would be
- appreciated. You'll have to figure out how to get the phone to
- go off-hook before it'll work, tho.)
-
- * This driver was not written with any cooperation or support from
- NeoMagic. If you have any questions about this, see their website
- for their official stance on supporting open source drivers.
-
-============
-Video memory
-============
-
-The NeoMagic sound engine uses a portion of the display memory to hold
-the sound buffer. (Crazy, eh?) The NeoMagic video BIOS sets up a
-special pointer at the top of video RAM to indicate where the top of
-the audio buffer should be placed.
-
-At the present time XFree86 is apparently not aware of this. It will
-thus write over either the pointer or the sound buffer with abandon.
-(Accelerated-X seems to do a better job here.)
-
-This implies a few things:
-
- * Sometimes the NM256 driver has to guess at where the buffer
- should be placed, especially if the module is loaded after the
- X server is started. It's usually correct, but it will consistently
- fail on the Sony F250.
-
- * Virtual screens greater than 1024x768x16 under XFree86 are
- problematic on laptops with only 2.5MB of screen RAM. This
- includes all of the 256AV-equipped laptops. (Virtual displays
- may or may not work on the 256ZX, which has at least 4MB of
- video RAM.)
-
-If you start having problems with random noise being output either
-constantly (this is the usual symptom on the F250), or when windows
-are moved around (this is the usual symptom when using a virtual
-screen), the best fix is to
-
- * Don't use a virtual frame buffer.
- * Make sure you load the NM256 module before the X server is
- started.
-
-On the F250, it is possible to force the driver to load properly even
-after the XFree86 server is started by doing:
-
- insmod nm256 buffertop=0x25a800
-
-This forces the audio buffers to the correct offset in screen RAM.
-
-One user has reported a similar problem on the Sony F270, although
-others apparently aren't seeing any problems. His suggested command
-is
-
- insmod nm256 buffertop=0x272800
-
-=================
-Official WWW site
-=================
-
-The official site for the NM256 driver is:
-
- http://www.uglx.org/sony.html
-
-You should always be able to get the latest version of the driver there,
-and the driver will be supported for the foreseeable future.
-
-==============
-Z505RX and IDE
-==============
-
-There appears to be a problem with the IDE chipset on the Z505RX; one
-of the symptoms is that sound playback periodically hangs (when the
-disk is accessed). The user reporting the problem also reported that
-enabling all of the IDE chipset workarounds in the kernel solved the
-problem, tho obviously only one of them should be needed--if someone
-can give me more details I would appreciate it.
-
-==============================
-Z505S/Z505SX on-board Ethernet
-==============================
-
-If you're using the on-board Ethernet Pro/100 ethernet support on the Z505
-series, I strongly encourage you to download the latest eepro100 driver from
-Donald Becker's site:
-
- ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/test/eepro100.c
-
-There was a reported problem on the Z505SX that if the ethernet
-interface is disabled and reenabled while the sound driver is loaded,
-the machine would lock up. I have included a workaround that is
-working satisfactorily. However, you may occasionally see a message
-about "Releasing interrupts, over 1000 bad interrupts" which indicates
-that the workaround is doing its job.
-
-==================================
-PCMCIA and the Z505S/Z505SX/Z505DX
-==================================
-
-There is also a known problem with the Sony Z505S and Z505SX hanging
-if a PCMCIA card is inserted while the ethernet driver is loaded, or
-in some cases if the laptop is suspended. This is caused by tons of
-spurious IRQ 9s, probably generated from the PCMCIA or ACPI bridges.
-
-There is currently no fix for the problem that works in every case.
-The only known workarounds are to disable the ethernet interface
-before inserting or removing a PCMCIA card, or with some cards
-disabling the PCMCIA card before ejecting it will also help the
-problem with the laptop hanging when the card is ejected.
-
-One user has reported that setting the tcic's cs_irq to some value
-other than 9 (like 11) fixed the problem. This doesn't work on my
-Z505S, however--changing the value causes the cardmgr to stop seeing
-card insertions and removals, cards don't seem to work correctly, and
-I still get hangs if a card is inserted when the kernel is booted.
-
-Using the latest ethernet driver and pcmcia package allows me to
-insert an Adaptec 1480A SlimScsi card without the laptop hanging,
-although I still have to shut down the card before ejecting or
-powering down the laptop. However, similar experiments with a DE-660
-ethernet card still result in hangs when the card is inserted. I am
-beginning to think that the interrupts are CardBus-related, since the
-Adaptec card is a CardBus card, and the DE-660 is not; however, I
-don't have any other CardBus cards to test with.
-
-======
-Thanks
-======
-
-First, I want to thank everyone (except NeoMagic of course) for their
-generous support and encouragement. I'd like to list everyone's name
-here that replied during the development phase, but the list is
-amazingly long.
-
-I will be rather unfair and single out a few people, however:
-
- Justin Maurer, for being the first random net.person to try it,
- and for letting me login to his Z505SX to get it working there
-
- Edi Weitz for trying out several different versions, and giving
- me a lot of useful feedback
-
- Greg Rumple for letting me login remotely to get the driver
- functional on the 256ZX, for his assistance on tracking
- down all sorts of random stuff, and for trying out Accel-X
-
- Zach Brown, for the initial AC97 mixer interface design
-
- Jeff Garzik, for various helpful suggestions on the AC97
- interface
-
- "Mr. Bumpy" for feedback on the Z505RX
-
- Bill Nottingham, for generous assistance in getting the mixer ID
- code working
-
-=================
-Previous versions
-=================
-
-Versions prior to 0.3 (aka `noname') had problems with weird artifacts
-in the output and failed to set the recording rate properly. These
-problems have long since been fixed.
-
-Versions prior to 0.5 had problems with clicks in the output when
-anything other than 16-bit stereo sound was being played, and also had
-periodic clicks when recording.
-
-Version 0.7 first incorporated support for the NM256ZX chipset, which
-is found on some Dell Latitude laptops (the CPt, and apparently
-some CPi models as well). It also included the generic AC97
-mixer module.
-
-Version 0.75 renamed all the functions and files with slightly more
-generic names.
-
-Note that previous versions of this document claimed that recording was
-8-bit only; it actually has been working for 16-bits all along.
diff --git a/Documentation/sound/oss/OPL3-SA2 b/Documentation/sound/oss/OPL3-SA2
deleted file mode 100644
index d8b6d2bbada6..000000000000
--- a/Documentation/sound/oss/OPL3-SA2
+++ /dev/null
@@ -1,210 +0,0 @@
-Documentation for the OPL3-SA2, SA3, and SAx driver (opl3sa2.o)
----------------------------------------------------------------
-
-Scott Murray, scott@spiteful.org
-January 7, 2001
-
-NOTE: All trade-marked terms mentioned below are properties of their
- respective owners.
-
-
-Supported Devices
------------------
-
-This driver is for PnP soundcards based on the following Yamaha audio
-controller chipsets:
-
-YMF711 aka OPL3-SA2
-YMF715 and YMF719 aka OPL3-SA3
-
-Up until recently (December 2000), I'd thought the 719 to be a
-different chipset, the OPL3-SAx. After an email exhange with
-Yamaha, however, it turns out that the 719 is just a re-badged
-715, and the chipsets are identical. The chipset detection code
-has been updated to reflect this.
-
-Anyways, all of these chipsets implement the following devices:
-
-OPL3 FM synthesizer
-Soundblaster Pro
-Microsoft/Windows Sound System
-MPU401 MIDI interface
-
-Note that this driver uses the MSS device, and to my knowledge these
-chipsets enforce an either/or situation with the Soundblaster Pro
-device and the MSS device. Since the MSS device has better
-capabilities, I have implemented the driver to use it.
-
-
-Mixer Channels
---------------
-
-Older versions of this driver (pre-December 2000) had two mixers,
-an OPL3-SA2 or SA3 mixer and a MSS mixer. The OPL3-SA[23] mixer
-device contained a superset of mixer channels consisting of its own
-channels and all of the MSS mixer channels. To simplify the driver
-considerably, and to partition functionality better, the OPL3-SA[23]
-mixer device now contains has its own specific mixer channels. They
-are:
-
-Volume - Hardware master volume control
-Bass - SA3 only, now supports left and right channels
-Treble - SA3 only, now supports left and right channels
-Microphone - Hardware microphone input volume control
-Digital1 - Yamaha 3D enhancement "Wide" mixer
-
-All other mixer channels (e.g. "PCM", "CD", etc.) now have to be
-controlled via the "MS Sound System (CS4231)" mixer. To facilitate
-this, the mixer device creation order has been switched so that
-the MSS mixer is created first. This allows accessing the majority
-of the useful mixer channels even via single mixer-aware tools
-such as "aumix".
-
-
-Plug 'n Play
-------------
-
-In previous kernels (2.2.x), some configuration was required to
-get the driver to talk to the card. Being the new millennium and
-all, the 2.4.x kernels now support auto-configuration if ISA PnP
-support is configured in. Theoretically, the driver even supports
-having more than one card in this case.
-
-With the addition of PnP support to the driver, two new parameters
-have been added to control it:
-
-isapnp - set to 0 to disable ISA PnP card detection
-
-multiple - set to 0 to disable multiple PnP card detection
-
-
-Optional Parameters
--------------------
-
-Recent (December 2000) additions to the driver (based on a patch
-provided by Peter Englmaier) are two new parameters:
-
-ymode - Set Yamaha 3D enhancement mode:
- 0 = Desktop/Normal 5-12 cm speakers
- 1 = Notebook PC (1) 3 cm speakers
- 2 = Notebook PC (2) 1.5 cm speakers
- 3 = Hi-Fi 16-38 cm speakers
-
-loopback - Set A/D input source. Useful for echo cancellation:
- 0 = Mic Right channel (default)
- 1 = Mono output loopback
-
-The ymode parameter has been tested and does work. The loopback
-parameter, however, is untested. Any feedback on its usefulness
-would be appreciated.
-
-
-Manual Configuration
---------------------
-
-If for some reason you decide not to compile ISA PnP support into
-your kernel, or disabled the driver's usage of it by setting the
-isapnp parameter as discussed above, then you will need to do some
-manual configuration. There are two ways of doing this. The most
-common is to use the isapnptools package to initialize the card, and
-use the kernel module form of the sound subsystem and sound drivers.
-Alternatively, some BIOS's allow manual configuration of installed
-PnP devices in a BIOS menu, which should allow using the non-modular
-sound drivers, i.e. built into the kernel.
-
-I personally use isapnp and modules, and do not have access to a PnP
-BIOS machine to test. If you have such a beast, configuring the
-driver to be built into the kernel should just work (thanks to work
-done by David Luyer <luyer@ucs.uwa.edu.au>). You will still need
-to specify settings, which can be done by adding:
-
-opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>
-
-to the kernel command line. For example:
-
-opl3sa2=0x370,5,0,1,0x530,0x330
-
-If you are instead using the isapnp tools (as most people have been
-before Linux 2.4.x), follow the directions in their documentation to
-produce a configuration file. Here is the relevant excerpt I used to
-use for my SA3 card from my isapnp.conf:
-
-(CONFIGURE YMH0800/-1 (LD 0
-
-# NOTE: IO 0 is for the unused SoundBlaster part of the chipset.
-(IO 0 (BASE 0x0220))
-(IO 1 (BASE 0x0530))
-(IO 2 (BASE 0x0388))
-(IO 3 (BASE 0x0330))
-(IO 4 (BASE 0x0370))
-(INT 0 (IRQ 5 (MODE +E)))
-(DMA 0 (CHANNEL 0))
-(DMA 1 (CHANNEL 1))
-
-Here, note that:
-
-Port Acceptable Range Purpose
----- ---------------- -------
-IO 0 0x0220 - 0x0280 SB base address, unused.
-IO 1 0x0530 - 0x0F48 MSS base address
-IO 2 0x0388 - 0x03F8 OPL3 base address
-IO 3 0x0300 - 0x0334 MPU base address
-IO 4 0x0100 - 0x0FFE card's own base address for its control I/O ports
-
-The IRQ and DMA values can be any that are considered acceptable for a
-MSS. Assuming you've got isapnp all happy, then you should be able to
-do something like the following (which matches up with the isapnp
-configuration above):
-
-modprobe mpu401
-modprobe ad1848
-modprobe opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=5 dma=0 dma2=1
-modprobe opl3 io=0x388
-
-See the section "Automatic Module Loading" below for how to set up
-/etc/modprobe.conf to automate this.
-
-An important thing to remember that the opl3sa2 module's io argument is
-for it's own control port, which handles the card's master mixer for
-volume (on all cards), and bass and treble (on SA3 cards).
-
-
-Troubleshooting
----------------
-
-If all goes well and you see no error messages, you should be able to
-start using the sound capabilities of your system. If you get an
-error message while trying to insert the opl3sa2 module, then make
-sure that the values of the various arguments match what you specified
-in your isapnp configuration file, and that there is no conflict with
-another device for an I/O port or interrupt. Checking the contents of
-/proc/ioports and /proc/interrupts can be useful to see if you're
-butting heads with another device.
-
-If you still cannot get the module to load, look at the contents of
-your system log file, usually /var/log/messages. If you see the
-message "opl3sa2: Unknown Yamaha audio controller version", then you
-have a different chipset version than I've encountered so far. Look
-for all messages in the log file that start with "opl3sa2: " and see
-if they provide any clues. If you do not see the chipset version
-message, and none of the other messages present in the system log are
-helpful, email me some details and I'll try my best to help.
-
-
-Automatic Module Loading
-------------------------
-
-Lastly, if you're using modules and want to set up automatic module
-loading with kmod, the kernel module loader, here is the section I
-currently use in my modprobe.conf file:
-
-# Sound
-alias sound-slot-0 opl3sa2
-options opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
-options opl3 io=0x388
-
-That's all it currently takes to get an OPL3-SA3 card working on my
-system. Once again, if you have any other problems, email me at the
-address listed above.
-
-Scott
diff --git a/Documentation/sound/oss/VIA-chipset b/Documentation/sound/oss/VIA-chipset
deleted file mode 100644
index 37865234e54d..000000000000
--- a/Documentation/sound/oss/VIA-chipset
+++ /dev/null
@@ -1,43 +0,0 @@
-Running sound cards on VIA chipsets
-
-o There are problems with VIA chipsets and sound cards that appear to
- lock the hardware solidly. Test programs under DOS have verified the
- problem exists on at least some (but apparently not all) VIA boards
-
-o VIA have so far failed to bother to answer support mail on the subject
- so if you are a VIA engineer feeling aggrieved as you read this
- document go chase your own people. If there is a workaround please
- let us know so we can implement it.
-
-
-Certain patterns of ISA DMA access used for most PC sound cards cause the
-VIA chipsets to lock up. From the collected reports this appears to cover a
-wide range of boards. Some also lock up with sound cards under Win* as well.
-
-Linux implements a workaround providing your chipset is PCI and you compiled
-with PCI Quirks enabled. If so you will see a message
- "Activating ISA DMA bug workarounds"
-
-during booting. If you have a VIA PCI chipset that hangs when you use the
-sound and is not generating this message even with PCI quirks enabled
-please report the information to the linux-kernel list (see REPORTING-BUGS).
-
-If you are one of the tiny number of unfortunates with a 486 ISA/VLB VIA
-chipset board you need to do the following to build a special kernel for
-your board
-
- edit linux/include/asm-i386/dma.h
-
-change
-
-#define isa_dma_bridge_buggy (0)
-
-to
-
-#define isa_dma_bridge_buggy (1)
-
-and rebuild a kernel without PCI quirk support.
-
-
-Other than this particular glitch the VIA [M]VP* chipsets appear to work
-perfectly with Linux.
diff --git a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx
deleted file mode 100644
index b54432709863..000000000000
--- a/Documentation/sound/oss/cs46xx
+++ /dev/null
@@ -1,138 +0,0 @@
-
-Documentation for the Cirrus Logic/Crystal SoundFusion cs46xx/cs4280 audio
-controller chips (2001/05/11)
-
-The cs46xx audio driver supports the DSP line of Cirrus controllers.
-Specifically, the cs4610, cs4612, cs4614, cs4622, cs4624, cs4630 and the cs4280
-products. This driver uses the generic ac97_codec driver for AC97 codec
-support.
-
-
-Features:
-
-Full Duplex Playback/Capture supported from 8k-48k.
-16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
-
-APM/PM - 2.2.x PM is enabled and functional. APM can also
-be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
-definition.
-
-DMA playback buffer size is configurable from 16k (defaultorder=2) up to 2Meg
-(defaultorder=11). DMA capture buffer size is fixed at a single 4k page as
-two 2k fragments.
-
-MMAP seems to work well with QuakeIII, and test XMMS plugin.
-
-Myth2 works, but the polling logic is not fully correct, but is functional.
-
-The 2.4.4-ac6 gameport code in the cs461x joystick driver has been tested
-with a Microsoft Sidewinder joystick (cs461x.o and sidewinder.o). This
-audio driver must be loaded prior to the joystick driver to enable the
-DSP task image supporting the joystick device.
-
-
-Limitations:
-
-SPDIF is currently not supported.
-
-Primary codec support only. No secondary codec support is implemented.
-
-
-
-NOTES:
-
-Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
-and has been tested.
-Module parameter hercules_egpio_disable set to 1, will force a 0 to EGPIODR
-to disable the external amplifier.
-
-VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
-the external amplifier for the "back" speakers, since we do not
-support the secondary codec then this external amp is not
-turned on. The primary codec external amplifier is supported but
-note that the AC97 EAPD bit is inverted logic (amp_voyetra()).
-
-DMA buffer size - there are issues with many of the Linux applications
-concerning the optimal buffer size. Several applications request a
-certain fragment size and number and then do not verify that the driver
-has the ability to support the requested configuration.
-SNDCTL_DSP_SETFRAGMENT ioctl is used to request a fragment size and
-number of fragments. Some applications exit if an error is returned
-on this particular ioctl. Therefore, in alignment with the other OSS audio
-drivers, no error is returned when a SETFRAGs IOCTL is received, but the
-values passed from the app are not used in any buffer calculation
-(ossfragshift/ossmaxfrags are not used).
-Use the "defaultorder=N" module parameter to change the buffer size if
-you have an application that requires a specific number of fragments
-or a specific buffer size (see below).
-
-Debug Interface
----------------
-There is an ioctl debug interface to allow runtime modification of the
-debug print levels. This debug interface code can be disabled from the
-compilation process with commenting the following define:
-#define CSDEBUG_INTERFACE 1
-There is also a debug print methodolgy to select printf statements from
-different areas of the driver. A debug print level is also used to allow
-additional printfs to be active. Comment out the following line in the
-driver to disable compilation of the CS_DBGOUT print statements:
-#define CSDEBUG 1
-
-Please see the definitions for cs_debuglevel and cs_debugmask for additional
-information on the debug levels and sections.
-
-There is also a csdbg executable to allow runtime manipulation of these
-parameters. for a copy email: twoller@crystal.cirrus.com
-
-
-
-MODULE_PARMS definitions
-------------------------
-module_param(defaultorder, ulong, 0);
-defaultorder=N
-where N is a value from 1 to 12
-The buffer order determines the size of the dma buffer for the driver.
-under Linux, a smaller buffer allows more responsiveness from many of the
-applications (e.g. games). A larger buffer allows some of the apps (esound)
-to not underrun the dma buffer as easily. As default, use 32k (order=3)
-rather than 64k as some of the games work more responsively.
-(2^N) * PAGE_SIZE = allocated buffer size
-
-module_param(cs_debuglevel, ulong, 0644);
-module_param(cs_debugmask, ulong, 0644);
-cs_debuglevel=N
-cs_debugmask=0xMMMMMMMM
-where N is a value from 0 (no debug printfs), to 9 (maximum)
-0xMMMMMMMM is a debug mask corresponding to the CS_xxx bits (see driver source).
-
-module_param(hercules_egpio_disable, ulong, 0);
-hercules_egpio_disable=N
-where N is a 0 (enable egpio), or a 1 (disable egpio support)
-
-module_param(initdelay, ulong, 0);
-initdelay=N
-This value is used to determine the millescond delay during the initialization
-code prior to powering up the PLL. On laptops this value can be used to
-assist with errors on resume, mostly with IBM laptops. Basically, if the
-system is booted under battery power then the mdelay()/udelay() functions fail to
-properly delay the required time. Also, if the system is booted under AC power
-and then the power removed, the mdelay()/udelay() functions will not delay properly.
-
-module_param(powerdown, ulong, 0);
-powerdown=N
-where N is 0 (disable any powerdown of the internal blocks) or 1 (enable powerdown)
-
-
-module_param(external_amp, bool, 0);
-external_amp=1
-if N is set to 1, then force enabling the EAPD support in the primary AC97 codec.
-override the detection logic and force the external amp bit in the AC97 0x26 register
-to be reset (0). EAPD should be 0 for powerup, and 1 for powerdown. The VTB Santa Cruz
-card has inverted logic, so there is a special function for these cards.
-
-module_param(thinkpad, bool, 0);
-thinkpad=1
-if N is set to 1, then force enabling the clkrun functionality.
-Currently, when the part is being used, then clkrun is disabled for the entire system,
-but re-enabled when the driver is released or there is no outstanding open count.
-
diff --git a/Documentation/spi/spi-lm70llp b/Documentation/spi/spi-lm70llp
new file mode 100644
index 000000000000..154bd02220b9
--- /dev/null
+++ b/Documentation/spi/spi-lm70llp
@@ -0,0 +1,69 @@
+spi_lm70llp : LM70-LLP parport-to-SPI adapter
+==============================================
+
+Supported board/chip:
+ * National Semiconductor LM70 LLP evaluation board
+ Datasheet: http://www.national.com/pf/LM/LM70.html
+
+Author:
+ Kaiwan N Billimoria <kaiwan@designergraphix.com>
+
+Description
+-----------
+This driver provides glue code connecting a National Semiconductor LM70 LLP
+temperature sensor evaluation board to the kernel's SPI core subsystem.
+
+In effect, this driver turns the parallel port interface on the eval board
+into a SPI bus with a single device, which will be driven by the generic
+LM70 driver (drivers/hwmon/lm70.c).
+
+The hardware interfacing on the LM70 LLP eval board is as follows:
+
+ Parallel LM70 LLP
+ Port Direction JP2 Header
+ ----------- --------- ----------------
+ D0 2 - -
+ D1 3 --> V+ 5
+ D2 4 --> V+ 5
+ D3 5 --> V+ 5
+ D4 6 --> V+ 5
+ D5 7 --> nCS 8
+ D6 8 --> SCLK 3
+ D7 9 --> SI/O 5
+ GND 25 - GND 7
+ Select 13 <-- SI/O 1
+ ----------- --------- ----------------
+
+Note that since the LM70 uses a "3-wire" variant of SPI, the SI/SO pin
+is connected to both pin D7 (as Master Out) and Select (as Master In)
+using an arrangment that lets either the parport or the LM70 pull the
+pin low. This can't be shared with true SPI devices, but other 3-wire
+devices might share the same SI/SO pin.
+
+The bitbanger routine in this driver (lm70_txrx) is called back from
+the bound "hwmon/lm70" protocol driver through its sysfs hook, using a
+spi_write_then_read() call. It performs Mode 0 (SPI/Microwire) bitbanging.
+The lm70 driver then inteprets the resulting digital temperature value
+and exports it through sysfs.
+
+A "gotcha": National Semiconductor's LM70 LLP eval board circuit schematic
+shows that the SI/O line from the LM70 chip is connected to the base of a
+transistor Q1 (and also a pullup, and a zener diode to D7); while the
+collector is tied to VCC.
+
+Interpreting this circuit, when the LM70 SI/O line is High (or tristate
+and not grounded by the host via D7), the transistor conducts and switches
+the collector to zero, which is reflected on pin 13 of the DB25 parport
+connector. When SI/O is Low (driven by the LM70 or the host) on the other
+hand, the transistor is cut off and the voltage tied to it's collector is
+reflected on pin 13 as a High level.
+
+So: the getmiso inline routine in this driver takes this fact into account,
+inverting the value read at pin 13.
+
+
+Thanks to
+---------
+o David Brownell for mentoring the SPI-side driver development.
+o Dr.Craig Hollabaugh for the (early) "manual" bitbanging driver version.
+o Nadir Billimoria for help interpreting the circuit schematic.
diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
index a661d684768e..471e75389778 100644
--- a/Documentation/spinlocks.txt
+++ b/Documentation/spinlocks.txt
@@ -1,7 +1,12 @@
-UPDATE March 21 2005 Amit Gud <gud@eth.net>
+SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and
+are hence deprecated.
-Macros SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated and will be
-removed soon. So for any new code dynamic initialization should be used:
+Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or
+__SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate for static
+initialization.
+
+Dynamic initialization, when necessary, may be performed as
+demonstrated below.
spinlock_t xxx_lock;
rwlock_t xxx_rw_lock;
@@ -15,12 +20,9 @@ removed soon. So for any new code dynamic initialization should be used:
module_init(xxx_init);
-Reasons for deprecation
- - it hurts automatic lock validators
- - it becomes intrusive for the realtime preemption patches
-
-Following discussion is still valid, however, with the dynamic initialization
-of spinlocks instead of static.
+The following discussion is still valid, however, with the dynamic
+initialization of spinlocks or with DEFINE_SPINLOCK, etc., used
+instead of SPIN_LOCK_UNLOCKED.
-----------------------
diff --git a/Documentation/sysctl/ctl_unnumbered.txt b/Documentation/sysctl/ctl_unnumbered.txt
new file mode 100644
index 000000000000..23003a8ea3e7
--- /dev/null
+++ b/Documentation/sysctl/ctl_unnumbered.txt
@@ -0,0 +1,22 @@
+
+Except for a few extremely rare exceptions user space applications do not use
+the binary sysctl interface. Instead everyone uses /proc/sys/... with
+readable ascii names.
+
+Recently the kernel has started supporting setting the binary sysctl value to
+CTL_UNNUMBERED so we no longer need to assign a binary sysctl path to allow
+sysctls to show up in /proc/sys.
+
+Assigning binary sysctl numbers is an endless source of conflicts in sysctl.h,
+breaking of the user space ABI (because of those conflicts), and maintenance
+problems. A complete pass through all of the sysctl users revealed multiple
+instances where the sysctl binary interface was broken and had gone undetected
+for years.
+
+So please do not add new binary sysctl numbers. They are unneeded and
+problematic.
+
+If you really need a new binary sysctl number please first merge your sysctl
+into the kernel and then as a separate patch allocate a binary sysctl number.
+
+(ebiederm@xmission.com, June 2007)
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 8cfca173d4bc..a0ccc5b60260 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -32,12 +32,14 @@ Currently, these files are in /proc/sys/vm:
- min_slab_ratio
- panic_on_oom
- mmap_min_address
+- numa_zonelist_order
==============================================================
dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
-block_dump, swap_token_timeout, drop-caches:
+block_dump, swap_token_timeout, drop-caches,
+hugepages_treat_as_movable:
See Documentation/filesystems/proc.txt
@@ -231,3 +233,47 @@ security module. Setting this value to something like 64k will allow the
vast majority of applications to work correctly and provide defense in depth
against future potential kernel bugs.
+==============================================================
+
+numa_zonelist_order
+
+This sysctl is only for NUMA.
+'where the memory is allocated from' is controlled by zonelists.
+(This documentation ignores ZONE_HIGHMEM/ZONE_DMA32 for simple explanation.
+ you may be able to read ZONE_DMA as ZONE_DMA32...)
+
+In non-NUMA case, a zonelist for GFP_KERNEL is ordered as following.
+ZONE_NORMAL -> ZONE_DMA
+This means that a memory allocation request for GFP_KERNEL will
+get memory from ZONE_DMA only when ZONE_NORMAL is not available.
+
+In NUMA case, you can think of following 2 types of order.
+Assume 2 node NUMA and below is zonelist of Node(0)'s GFP_KERNEL
+
+(A) Node(0) ZONE_NORMAL -> Node(0) ZONE_DMA -> Node(1) ZONE_NORMAL
+(B) Node(0) ZONE_NORMAL -> Node(1) ZONE_NORMAL -> Node(0) ZONE_DMA.
+
+Type(A) offers the best locality for processes on Node(0), but ZONE_DMA
+will be used before ZONE_NORMAL exhaustion. This increases possibility of
+out-of-memory(OOM) of ZONE_DMA because ZONE_DMA is tend to be small.
+
+Type(B) cannot offer the best locality but is more robust against OOM of
+the DMA zone.
+
+Type(A) is called as "Node" order. Type (B) is "Zone" order.
+
+"Node order" orders the zonelists by node, then by zone within each node.
+Specify "[Nn]ode" for zone order
+
+"Zone Order" orders the zonelists by zone type, then by node within each
+zone. Specify "[Zz]one"for zode order.
+
+Specify "[Dd]efault" to request automatic configuration. Autoconfiguration
+will select "node" order in following case.
+(1) if the DMA zone does not exist or
+(2) if the DMA zone comprises greater than 50% of the available memory or
+(3) if any node's DMA zone comprises greater than 60% of its local memory and
+ the amount of local memory is big enough.
+
+Otherwise, "zone" order will be selected. Default order is recommended unless
+this is causing problems for your system/application.
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 687104bfd09a..51ccc48aa763 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -77,8 +77,9 @@ If the user applications are going to request hugepages using mmap system
call, then it is required that system administrator mount a file system of
type hugetlbfs:
- mount none /mnt/huge -t hugetlbfs <uid=value> <gid=value> <mode=value>
- <size=value> <nr_inodes=value>
+ mount -t hugetlbfs \
+ -o uid=<value>,gid=<value>,mode=<value>,size=<value>,nr_inodes=<value> \
+ none /mnt/huge
This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
/mnt/huge. Any files created on /mnt/huge uses hugepages. The uid and gid
@@ -88,11 +89,10 @@ mode of root of file system to value & 0777. This value is given in octal.
By default the value 0755 is picked. The size option sets the maximum value of
memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
rounded down to HPAGE_SIZE. The option nr_inodes sets the maximum number of
-inodes that /mnt/huge can use. If the size or nr_inodes options are not
+inodes that /mnt/huge can use. If the size or nr_inodes option is not
provided on command line then no limits are set. For size and nr_inodes
options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
-example, size=2K has the same meaning as size=2048. An example is given at
-the end of this document.
+example, size=2K has the same meaning as size=2048.
read and write system calls are not supported on files that reside on hugetlb
file systems.
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
index 1523320abd87..d17f324db9f5 100644
--- a/Documentation/vm/slub.txt
+++ b/Documentation/vm/slub.txt
@@ -41,6 +41,8 @@ Possible debug options are
P Poisoning (object and padding)
U User tracking (free and alloc)
T Trace (please only use on single slabs)
+ - Switch all debugging off (useful if the kernel is
+ configured with CONFIG_SLUB_DEBUG_ON)
F.e. in order to boot just with sanity checks and red zoning one would specify:
@@ -125,13 +127,20 @@ SLUB Debug output
Here is a sample of slub debug output:
-*** SLUB kmalloc-8: Redzone Active@0xc90f6d20 slab 0xc528c530 offset=3360 flags=0x400000c3 inuse=61 freelist=0xc90f6d58
- Bytes b4 0xc90f6d10: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
- Object 0xc90f6d20: 31 30 31 39 2e 30 30 35 1019.005
- Redzone 0xc90f6d28: 00 cc cc cc .
-FreePointer 0xc90f6d2c -> 0xc90f6d58
-Last alloc: get_modalias+0x61/0xf5 jiffies_ago=53 cpu=1 pid=554
-Filler 0xc90f6d50: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ
+====================================================================
+BUG kmalloc-8: Redzone overwritten
+--------------------------------------------------------------------
+
+INFO: 0xc90f6d28-0xc90f6d2b. First byte 0x00 instead of 0xcc
+INFO: Slab 0xc528c530 flags=0x400000c3 inuse=61 fp=0xc90f6d58
+INFO: Object 0xc90f6d20 @offset=3360 fp=0xc90f6d58
+INFO: Allocated in get_modalias+0x61/0xf5 age=53 cpu=1 pid=554
+
+Bytes b4 0xc90f6d10: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
+ Object 0xc90f6d20: 31 30 31 39 2e 30 30 35 1019.005
+ Redzone 0xc90f6d28: 00 cc cc cc .
+ Padding 0xc90f6d50: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ
+
[<c010523d>] dump_trace+0x63/0x1eb
[<c01053df>] show_trace_log_lvl+0x1a/0x2f
[<c010601d>] show_trace+0x12/0x14
@@ -153,74 +162,108 @@ Filler 0xc90f6d50: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ
[<c0104112>] sysenter_past_esp+0x5f/0x99
[<b7f7b410>] 0xb7f7b410
=======================
-@@@ SLUB kmalloc-8: Restoring redzone (0xcc) from 0xc90f6d28-0xc90f6d2b
+FIX kmalloc-8: Restoring Redzone 0xc90f6d28-0xc90f6d2b=0xcc
+If SLUB encounters a corrupted object (full detection requires the kernel
+to be booted with slub_debug) then the following output will be dumped
+into the syslog:
-If SLUB encounters a corrupted object then it will perform the following
-actions:
-
-1. Isolation and report of the issue
+1. Description of the problem encountered
This will be a message in the system log starting with
-*** SLUB <slab cache affected>: <What went wrong>@<object address>
-offset=<offset of object into slab> flags=<slabflags>
-inuse=<objects in use in this slab> freelist=<first free object in slab>
+===============================================
+BUG <slab cache affected>: <What went wrong>
+-----------------------------------------------
-2. Report on how the problem was dealt with in order to ensure the continued
-operation of the system.
+INFO: <corruption start>-<corruption_end> <more info>
+INFO: Slab <address> <slab information>
+INFO: Object <address> <object information>
+INFO: Allocated in <kernel function> age=<jiffies since alloc> cpu=<allocated by
+ cpu> pid=<pid of the process>
+INFO: Freed in <kernel function> age=<jiffies since free> cpu=<freed by cpu>
+ pid=<pid of the process>
-These are messages in the system log beginning with
-
-@@@ SLUB <slab cache affected>: <corrective action taken>
+(Object allocation / free information is only available if SLAB_STORE_USER is
+set for the slab. slub_debug sets that option)
+2. The object contents if an object was involved.
-In the above sample SLUB found that the Redzone of an active object has
-been overwritten. Here a string of 8 characters was written into a slab that
-has the length of 8 characters. However, a 8 character string needs a
-terminating 0. That zero has overwritten the first byte of the Redzone field.
-After reporting the details of the issue encountered the @@@ SLUB message
-tell us that SLUB has restored the redzone to its proper value and then
-system operations continue.
-
-Various types of lines can follow the @@@ SLUB line:
+Various types of lines can follow the BUG SLUB line:
Bytes b4 <address> : <bytes>
- Show a few bytes before the object where the problem was detected.
+ Shows a few bytes before the object where the problem was detected.
Can be useful if the corruption does not stop with the start of the
object.
Object <address> : <bytes>
The bytes of the object. If the object is inactive then the bytes
- typically contain poisoning values. Any non-poison value shows a
+ typically contain poison values. Any non-poison value shows a
corruption by a write after free.
Redzone <address> : <bytes>
- The redzone following the object. The redzone is used to detect
+ The Redzone following the object. The Redzone is used to detect
writes after the object. All bytes should always have the same
value. If there is any deviation then it is due to a write after
the object boundary.
-Freepointer
- The pointer to the next free object in the slab. May become
- corrupted if overwriting continues after the red zone.
-
-Last alloc:
-Last free:
- Shows the address from which the object was allocated/freed last.
- We note the pid, the time and the CPU that did so. This is usually
- the most useful information to figure out where things went wrong.
- Here get_modalias() did an kmalloc(8) instead of a kmalloc(9).
+ (Redzone information is only available if SLAB_RED_ZONE is set.
+ slub_debug sets that option)
-Filler <address> : <bytes>
+Padding <address> : <bytes>
Unused data to fill up the space in order to get the next object
properly aligned. In the debug case we make sure that there are
- at least 4 bytes of filler. This allow for the detection of writes
+ at least 4 bytes of padding. This allows the detection of writes
before the object.
-Following the filler will be a stackdump. That stackdump describes the
-location where the error was detected. The cause of the corruption is more
-likely to be found by looking at the information about the last alloc / free.
+3. A stackdump
+
+The stackdump describes the location where the error was detected. The cause
+of the corruption is may be more likely found by looking at the function that
+allocated or freed the object.
+
+4. Report on how the problem was dealt with in order to ensure the continued
+operation of the system.
+
+These are messages in the system log beginning with
+
+FIX <slab cache affected>: <corrective action taken>
+
+In the above sample SLUB found that the Redzone of an active object has
+been overwritten. Here a string of 8 characters was written into a slab that
+has the length of 8 characters. However, a 8 character string needs a
+terminating 0. That zero has overwritten the first byte of the Redzone field.
+After reporting the details of the issue encountered the FIX SLUB message
+tell us that SLUB has restored the Redzone to its proper value and then
+system operations continue.
+
+Emergency operations:
+---------------------
+
+Minimal debugging (sanity checks alone) can be enabled by booting with
+
+ slub_debug=F
+
+This will be generally be enough to enable the resiliency features of slub
+which will keep the system running even if a bad kernel component will
+keep corrupting objects. This may be important for production systems.
+Performance will be impacted by the sanity checks and there will be a
+continual stream of error messages to the syslog but no additional memory
+will be used (unlike full debugging).
+
+No guarantees. The kernel component still needs to be fixed. Performance
+may be optimized further by locating the slab that experiences corruption
+and enabling debugging only for that cache
+
+I.e.
+
+ slub_debug=F,dentry
+
+If the corruption occurs by writing after the end of the object then it
+may be advisable to enable a Redzone to avoid corrupting the beginning
+of other objects.
+
+ slub_debug=FZ,dentry
-Christoph Lameter, <clameter@sgi.com>, May 23, 2007
+Christoph Lameter, <clameter@sgi.com>, May 30, 2007
diff --git a/MAINTAINERS b/MAINTAINERS
index 391426977826..368a7181fa14 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -194,13 +194,6 @@ M: jes@trained-monkey.org
L: linux-acenic@sunsite.dk
S: Maintained
-ACI MIXER DRIVER
-P: Robert Siemer
-M: Robert.Siemer@gmx.de
-L: linux-sound@vger.kernel.org
-W: http://www.stud.uni-karlsruhe.de/~uh1b/
-S: Maintained
-
IPS SCSI RAID DRIVER
P: Adaptec OEM Raid Solutions
M: aacraid@adaptec.com
@@ -272,21 +265,6 @@ L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
-AD1816 SOUND DRIVER
-P: Thorsten Knabe
-M: Thorsten Knabe <linux@thorsten-knabe.de>
-W: http://linux.thorsten-knabe.de
-S: Maintained
-
-AD1889 SOUND DRIVER
-P: Kyle McMartin
-M: kyle@parisc-linux.org
-P: Thibaut Varene
-M: T-Bone@parisc-linux.org
-W: http://wiki.parisc-linux.org/AD1889
-L: parisc-linux@lists.parisc-linux.org
-S: Maintained
-
ADM1025 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
@@ -935,6 +913,12 @@ M: mchan@broadcom.com
L: netdev@vger.kernel.org
S: Supported
+BSG (block layer generic sg v4 driver)
+P: FUJITA Tomonori
+M: fujita.tomonori@lab.ntt.co.jp
+L: linux-scsi@vger.kernel.org
+S: Supported
+
BTTV VIDEO4LINUX DRIVER
P: Mauro Carvalho Chehab
M: mchehab@infradead.org
@@ -1276,6 +1260,12 @@ M: tori@unhappy.mine.nu
L: netdev@vger.kernel.org
S: Maintained
+DMA GENERIC MEMCPY SUBSYSTEM
+P: Shannon Nelson
+M: shannon.nelson@intel.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
DOCBOOK FOR DOCUMENTATION
P: Randy Dunlap
M: rdunlap@xenotime.net
@@ -1398,13 +1388,6 @@ M: raisch@de.ibm.com
L: general@lists.openfabrics.org
S: Supported
-EMU10K1 SOUND DRIVER
-P: James Courtier-Dutton
-M: James@superbug.demon.co.uk
-L: emu10k1-devel@lists.sourceforge.net
-W: http://sourceforge.net/projects/emu10k1/
-S: Maintained
-
EMULEX LPFC FC SCSI DRIVER
P: James Smart
M: james.smart@emulex.com
@@ -1900,6 +1883,12 @@ P: Tigran Aivazian
M: tigran@aivazian.fsnet.co.uk
S: Maintained
+INTEL I/OAT DMA DRIVER
+P: Shannon Nelson
+M: shannon.nelson@intel.com
+L: linux-kernel@vger.kernel.org
+S: Supported
+
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
P: Deepak Saxena
M: dsaxena@plexity.net
@@ -2297,6 +2286,14 @@ M: matthew@wil.cx
L: linux-scsi@vger.kernel.org
S: Maintained
+M32R ARCHITECTURE
+P: Hirokazu Takata
+M: takata@linux-m32r.org
+L: linux-m32r@ml.linux-m32r.org
+L: linux-m32r-ja@ml.linux-m32r.org (in Japanese)
+W: http://www.linux-m32r.org/
+S: Maintained
+
M68K ARCHITECTURE
P: Geert Uytterhoeven
M: geert@linux-m68k.org
@@ -2622,12 +2619,6 @@ M: yokota@netlab.is.tsukuba.ac.jp
W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
S: Maintained
-NON-IDE/NON-SCSI CDROM DRIVERS [GENERAL] (come on, crew - mark your responsibility)
-P: Eberhard Moenkeberg
-M: emoenke@gwdg.de
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
NTFS FILESYSTEM
P: Anton Altaparmakov
M: aia21@cantab.net
@@ -2710,12 +2701,6 @@ L: osst-users@lists.sourceforge.net
L: linux-scsi@vger.kernel.org
S: Maintained
-OPL3-SA2, SA3, and SAx DRIVER
-P: Zwane Mwaikambo
-M: zwane@arm.linux.org.uk
-L: linux-sound@vger.kernel.org
-S: Maintained
-
OPROFILE
P: Philippe Elie
M: phil.el@wanadoo.fr
@@ -3120,12 +3105,6 @@ M: michael@mihu.de
W: http://www.mihu.de/linux/saa7146
S: Maintained
-SBPCD CDROM DRIVER
-P: Eberhard Moenkeberg
-M: emoenke@gwdg.de
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
SC1200 WDT DRIVER
P: Zwane Mwaikambo
M: zwane@arm.linux.org.uk
diff --git a/Makefile b/Makefile
index de4f8f7d396c..ddbfcac299c1 100644
--- a/Makefile
+++ b/Makefile
@@ -313,7 +313,8 @@ LINUXINCLUDE := -Iinclude \
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
- -fno-strict-aliasing -fno-common
+ -fno-strict-aliasing -fno-common \
+ -Werror-implicit-function-declaration
AFLAGS := -D__ASSEMBLY__
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 0cd060598f9a..83a781842266 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -315,9 +315,7 @@ do_sys_ptrace(long request, long pid, long addr, long data,
/* When I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- tmp = data;
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
- ret = (copied == sizeof(tmp)) ? 0 : -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the specified register */
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 80cfb758ee2b..b28731437c31 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -65,7 +65,7 @@ enum ipi_message_type {
};
/* Set to a secondary's cpuid when it comes online. */
-static int smp_secondary_alive __initdata = 0;
+static int smp_secondary_alive __devinitdata = 0;
/* Which cpus ids came online. */
cpumask_t cpu_online_map;
@@ -173,7 +173,7 @@ smp_callin(void)
}
/* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */
-static int __init
+static int __devinit
wait_for_txrdy (unsigned long cpumask)
{
unsigned long timeout;
@@ -358,7 +358,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
/*
* Bring one cpu online.
*/
-static int __init
+static int __devinit
smp_boot_one_cpu(int cpuid)
{
struct task_struct *idle;
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 930cedc8be24..783f4e50c111 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -289,7 +289,7 @@ srm_console_device(struct console *co, int *index)
return srmcons_driver;
}
-static int __init
+static int
srm_console_setup(struct console *co, char *options)
{
return 0;
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 0bcb968cb60a..922143ea1cdb 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -420,7 +420,7 @@ marvel_init_pci(void)
io7_clear_errors(io7);
}
-static void
+static void __init
marvel_init_rtc(void)
{
init_rtc_irq();
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 4748e14a28bc..1dd50d07693c 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -144,7 +144,7 @@ irqreturn_t timer_interrupt(int irq, void *dev)
return IRQ_HANDLED;
}
-void
+void __init
common_init_rtc(void)
{
unsigned char x;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index d6e665d567bd..ec0f05e0d8ff 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -184,6 +184,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
#endif
printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
dik_show_regs(regs, r9_15);
+ add_taint(TAINT_DIE);
dik_show_trace((unsigned long *)(regs+1));
dik_show_code((unsigned int *)regs->pc);
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index ab3761c437a8..8698e0746f9f 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -69,6 +69,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
result = (result & 0xffffffff) + (result >> 32);
return (__force __wsum)result;
}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
/*
* Do a 64-bit checksum on an arbitrary memory area..
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 6f2f46c2e406..78c9f1a3d41f 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -657,7 +657,6 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- unsigned long tmp;
int ret;
switch (request) {
@@ -666,12 +665,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
*/
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- ret = access_process_vm(child, addr, &tmp,
- sizeof(unsigned long), 0);
- if (ret == sizeof(unsigned long))
- ret = put_user(tmp, (unsigned long __user *) data);
- else
- ret = -EIO;
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
case PTRACE_PEEKUSR:
@@ -683,12 +677,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
*/
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = access_process_vm(child, addr, &data,
- sizeof(unsigned long), 1);
- if (ret == sizeof(unsigned long))
- ret = 0;
- else
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR:
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 237f4999b9a1..f2114bcf09d5 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -249,6 +249,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(1);
__die(str, err, thread, regs);
bust_spinlocks(0);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index e18a41e61f0c..dde089922e3b 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -23,6 +23,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/mtd/physmap.h>
@@ -83,6 +84,13 @@ static struct at91_udc_data __initdata csb337_udc_data = {
.pullup_pin = AT91_PIN_PA24,
};
+static struct i2c_board_info __initdata csb337_i2c_devices[] = {
+ { I2C_BOARD_INFO("rtc-ds1307", 0x68),
+ .type = "ds1307",
+ },
+};
+
+
static struct at91_cf_data __initdata csb337_cf_data = {
/*
* connector P4 on the CSB 337 mates to
@@ -161,6 +169,8 @@ static void __init csb337_board_init(void)
at91_add_device_udc(&csb337_udc_data);
/* I2C */
at91_add_device_i2c();
+ i2c_register_board_info(0, csb337_i2c_devices,
+ ARRAY_SIZE(csb337_i2c_devices));
/* Compact Flash */
at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */
at91_add_device_cf(&csb337_cf_data);
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 390a97d39e5a..1873bd8cd1b2 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -25,6 +25,7 @@
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <asm/hardware.h>
@@ -199,6 +200,12 @@ static struct platform_device n2100_serial_device = {
.resource = &n2100_uart_resource,
};
+static struct i2c_board_info __initdata n2100_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("rtc-rs5c372", 0x32),
+ .type = "rs5c372b",
+ },
+};
/*
* Pull PCA9532 GPIO #8 low to power off the machine.
@@ -248,6 +255,9 @@ static void __init n2100_init_machine(void)
platform_device_register(&iop3xx_dma_0_channel);
platform_device_register(&iop3xx_dma_1_channel);
+ i2c_register_board_info(0, n2100_i2c_devices,
+ ARRAY_SIZE(n2100_i2c_devices));
+
pm_power_off = n2100_power_off;
init_timer(&power_button_poll_timer);
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 20688bc13e9b..9044f33299f7 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -17,6 +17,9 @@ config MMU
bool
default y
+config NO_DMA
+ def_bool y
+
config ARCH_ACORN
bool
default y
diff --git a/arch/arm26/defconfig b/arch/arm26/defconfig
index c4a89703c3d8..2b7d44bf49bf 100644
--- a/arch/arm26/defconfig
+++ b/arch/arm26/defconfig
@@ -248,7 +248,6 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 416927956721..0fefb86970c6 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -531,7 +531,6 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- unsigned long tmp;
int ret;
switch (request) {
@@ -540,12 +539,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
*/
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- ret = access_process_vm(child, addr, &tmp,
- sizeof(unsigned long), 0);
- if (ret == sizeof(unsigned long))
- ret = put_user(tmp, (unsigned long *) data);
- else
- ret = -EIO;
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
case PTRACE_PEEKUSR:
@@ -557,12 +551,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
*/
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = access_process_vm(child, addr, &data,
- sizeof(unsigned long), 1);
- if (ret == sizeof(unsigned long))
- ret = 0;
- else
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR:
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index d594fb59e945..2911e2eae80e 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -185,6 +185,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
printk("Internal error: %s: %x\n", str, err);
printk("CPU: %d\n", smp_processor_id());
show_regs(regs);
+ add_taint(TAINT_DIE);
printk("Process %s (pid: %d, stack limit = 0x%p)\n",
current->comm, current->pid, end_of_stack(tsk));
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index 562fac12eb95..36e7ee3f8321 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -33,9 +33,6 @@
#include <asm/map.h>
-
-#define TABLE_SIZE PTRS_PER_PTE * sizeof(pte_t))
-
struct mmu_gather mmu_gathers[NR_CPUS];
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
index 3c36c2d16148..39060cbeb2a3 100644
--- a/arch/avr32/kernel/ptrace.c
+++ b/arch/avr32/kernel/ptrace.c
@@ -153,7 +153,6 @@ static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- unsigned long tmp;
int ret;
pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n",
@@ -166,11 +165,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Read the word at location addr in the child process */
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (ret == sizeof(tmp))
- ret = put_user(tmp, (unsigned long __user *)data);
- else
- ret = -EIO;
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
case PTRACE_PEEKUSR:
@@ -181,11 +176,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Write the word in data at location addr */
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = access_process_vm(child, addr, &data, sizeof(data), 1);
- if (ret == sizeof(data))
- ret = 0;
- else
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR:
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 86d107511dd4..9a73ce7eb50f 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -56,6 +56,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
show_regs_log_lvl(regs, KERN_EMERG);
show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
bust_spinlocks(0);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
@@ -184,7 +185,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) {
enum bug_trap_type type;
- type = report_bug(regs->pc);
+ type = report_bug(regs->pc, regs);
switch (type) {
case BUG_TRAP_TYPE_NONE:
break;
diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig
index 2a3411eaace9..710c20ba2be7 100644
--- a/arch/cris/arch-v10/defconfig
+++ b/arch/cris/arch-v10/defconfig
@@ -429,7 +429,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index fd2129a04586..f4f9db698b44 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -83,19 +83,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* Read word at location address. */
case PTRACE_PEEKTEXT:
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
-
- if (copied != sizeof(tmp))
- break;
-
- ret = put_user(tmp,datap);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* Read the word at location address in the USER area. */
case PTRACE_PEEKUSR: {
@@ -113,12 +103,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Write the word at location address. */
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = 0;
-
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
-
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
/* Write the word at location address in the USER area. */
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index 1a071f17446d..e8914d401696 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -267,10 +267,10 @@ static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op);
const struct file_operations cryptocop_fops = {
- owner: THIS_MODULE,
- open: cryptocop_open,
- release: cryptocop_release,
- ioctl: cryptocop_ioctl
+ .owner = THIS_MODULE,
+ .open = cryptocop_open,
+ .release = cryptocop_release,
+ .ioctl = cryptocop_ioctl
};
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5d6c52737df3..e12f6cc6f4a2 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -574,10 +574,10 @@ i2c_ioctl(struct inode *inode, struct file *file,
}
static const struct file_operations i2c_fops = {
- owner: THIS_MODULE,
- ioctl: i2c_ioctl,
- open: i2c_open,
- release: i2c_release,
+ .owner = THIS_MODULE,
+ .ioctl = i2c_ioctl,
+ .open = i2c_open,
+ .release = i2c_release,
};
int __init
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index 24b919b3821a..fa8d50007e4c 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -51,10 +51,10 @@ int pcf8563_open(struct inode *, struct file *);
int pcf8563_release(struct inode *, struct file *);
static const struct file_operations pcf8563_fops = {
- owner: THIS_MODULE,
- ioctl: pcf8563_ioctl,
- open: pcf8563_open,
- release: pcf8563_release,
+ .owner = THIS_MODULE,
+ .ioctl = pcf8563_ioctl,
+ .open = pcf8563_open,
+ .release = pcf8563_release,
};
unsigned char
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index d4d57b741334..38ece0cd47cb 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -146,12 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Write the word at location address. */
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = 0;
-
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
-
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
/* Write the word at location address in the USER area. */
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 43dc08ec7511..275673c192aa 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1492,6 +1492,10 @@ sys_call_table:
.long sys_move_pages
.long sys_getcpu
.long sys_epoll_pwait
+ .long sys_utimensat /* 320 */
+ .long sys_signalfd
+ .long sys_timerfd
+ .long sys_eventfd
syscall_table_size = (. - sys_call_table)
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 1e7a101cbf4c..e89cad1192a9 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -647,17 +647,11 @@ void debug_to_serial(const char *p, int n)
}
#endif
-#ifdef CONFIG_GDBSTUB_CONSOLE
-
-static kdev_t gdbstub_console_dev(struct console *con)
-{
- return MKDEV(1,3); /* /dev/null */
-}
+#ifdef CONFIG_GDB_CONSOLE
static struct console gdbstub_console = {
.name = "gdb",
.write = gdbstub_console_write, /* in break.S */
- .device = gdbstub_console_dev,
.flags = CON_PRINTBUFFER,
.index = -1,
};
@@ -2021,7 +2015,7 @@ void __init gdbstub_init(void)
ptr = mem2hex(gdbstub_banner, ptr, sizeof(gdbstub_banner) - 1, 0);
gdbstub_send_packet(output_buffer);
#endif
-#if defined(CONFIG_GDBSTUB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined(CONFIG_GDB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE)
register_console(&gdbstub_console);
#endif
@@ -2031,7 +2025,7 @@ void __init gdbstub_init(void)
/*
* register the console at a more appropriate time
*/
-#if defined (CONFIG_GDBSTUB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
+#if defined (CONFIG_GDB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE)
static int __init gdbstub_postinit(void)
{
printk("registering console\n");
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index ce88fb95ee59..709e9bdc6126 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -112,20 +112,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- int copied;
-
+ case PTRACE_PEEKDATA:
ret = -EIO;
if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
break;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (copied != sizeof(tmp))
- break;
-
- ret = put_user(tmp,(unsigned long *) data);
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -176,9 +168,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO;
if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
break;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
- break;
- ret = 0;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index aa3c795d5354..c1c32e4c863d 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -60,10 +60,6 @@ static void __init setup_linux_memory(void);
static void __init setup_uclinux_memory(void);
#endif
-#ifdef CONFIG_CONSOLE
-extern struct consw *conswitchp;
-#endif
-
#ifdef CONFIG_MB93090_MB00
static char __initdata mb93090_banner[] = "FJ/RH FR-V Linux";
static char __initdata mb93090_version[] = UTS_RELEASE;
@@ -795,13 +791,6 @@ void __init setup_arch(char **cmdline_p)
#endif
#endif
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
- /* we need to initialize the Flashrom device here since we might
- * do things with flash early on in the boot
- */
- flash_probe();
-#endif
-
/* deal with the command line - RedBoot may have passed one to the kernel */
memcpy(command_line, boot_command_line, sizeof(command_line));
*cmdline_p = &command_line[0];
@@ -837,11 +826,6 @@ void __init setup_arch(char **cmdline_p)
#endif
#endif
-#ifdef CONFIG_BLK_DEV_BLKMEM
- ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);
-#endif
- /*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/
-
#ifdef CONFIG_MMU
setup_linux_memory();
#else
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 618dbad696f6..e35f74e6e505 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -68,6 +68,9 @@ config TIME_LOW_RES
config NO_IOPORT
def_bool y
+config NO_DMA
+ def_bool y
+
config ISA
bool
default y
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
index b2d896a7e598..53b5c1edf596 100644
--- a/arch/h8300/Makefile
+++ b/arch/h8300/Makefile
@@ -61,10 +61,11 @@ archmrproper:
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-vmlinux.srec vmlinux.bin: vmlinux
+vmlinux.srec vmlinux.bin zImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
define archhelp
- echo 'vmlinux.bin - Create raw binary'
- echo 'vmlinux.srec - Create srec binary'
+ @echo 'vmlinux.bin - Create raw binary'
+ @echo 'vmlinux.srec - Create srec binary'
+ @echo 'zImage - Compressed kernel image'
endef
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
index 71aac82a8ae0..d6189e057ed3 100644
--- a/arch/h8300/boot/compressed/Makefile
+++ b/arch/h8300/boot/compressed/Makefile
@@ -15,10 +15,10 @@ OBJECTS = $(obj)/head.o $(obj)/misc.o
# in order to suppress error message.
#
CONFIG_MEMORY_START ?= 0x00400000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00400000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
-LDFLAGS_vmlinux := -T $(obj)/vmlinux.lds
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
$(call if_changed,ld)
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
index b8e90d12d19e..985a81a2435a 100644
--- a/arch/h8300/boot/compressed/head.S
+++ b/arch/h8300/boot/compressed/head.S
@@ -4,7 +4,7 @@
* Copyright (C) 2006 Yoshinori Sato
*/
-.h8300h
+ .h8300h
#include <linux/linkage.h>
#define SRAM_START 0xff4000
diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
new file mode 100644
index 000000000000..65e2a0d1ae39
--- /dev/null
+++ b/arch/h8300/boot/compressed/vmlinux.lds
@@ -0,0 +1,32 @@
+SECTIONS
+{
+ .text :
+ {
+ __stext = . ;
+ __text = .;
+ *(.text.startup)
+ *(.text)
+ __etext = . ;
+ }
+
+ .rodata :
+ {
+ *(.rodata)
+ }
+ .data :
+
+ {
+ __sdata = . ;
+ ___data_start = . ;
+ *(.data.*)
+ }
+ .bss :
+ {
+ . = ALIGN(0x4) ;
+ __sbss = . ;
+ *(.bss*)
+ . = ALIGN(0x4) ;
+ __ebss = . ;
+ __end = . ;
+ }
+}
diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr
new file mode 100644
index 000000000000..a0f6962736e9
--- /dev/null
+++ b/arch/h8300/boot/compressed/vmlinux.scr
@@ -0,0 +1,9 @@
+SECTIONS
+{
+ .data : {
+ _input_len = .;
+ LONG(_input_data_end - _input_data) _input_data = .;
+ *(.data)
+ _input_data_end = .;
+ }
+}
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index ccc1a7fbf94b..874f6aefee65 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -6,6 +6,7 @@ extra-y := vmlinux.lds
obj-y := process.o traps.o ptrace.o irq.o \
sys_h8300.o time.o semaphore.o signal.o \
- setup.o gpio.o init_task.o syscalls.o
+ setup.o gpio.o init_task.o syscalls.o \
+ entry.o
obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
diff --git a/arch/h8300/platform/h8s/entry.S b/arch/h8300/kernel/entry.S
index f3d6b8e8f959..ca7431690300 100644
--- a/arch/h8300/platform/h8s/entry.S
+++ b/arch/h8300/kernel/entry.S
@@ -1,11 +1,10 @@
/* -*- mode: asm -*-
*
- * linux/arch/h8300/platform/h8s/entry.S
+ * linux/arch/h8300/platform/h8300h/entry.S
*
* Yoshinori Sato <ysato@users.sourceforge.jp>
+ * David McCullough <davidm@snapgear.com>
*
- * fairly heavy changes to fix syscall args and signal processing
- * by David McCullough <davidm@snapgear.com>
*/
/*
@@ -23,13 +22,66 @@
#include <asm/thread_info.h>
#include <asm/errno.h>
+#if defined(CONFIG_CPU_H8300H)
+#define USERRET 8
+INTERRUPTS = 64
+ .h8300h
+ .macro SHLL2 reg
+ shll.l \reg
+ shll.l \reg
+ .endm
+ .macro SHLR2 reg
+ shlr.l \reg
+ shlr.l \reg
+ .endm
+ .macro SAVEREGS
+ mov.l er0,@-sp
+ mov.l er1,@-sp
+ mov.l er2,@-sp
+ mov.l er3,@-sp
+ .endm
+ .macro RESTOREREGS
+ mov.l @sp+,er3
+ mov.l @sp+,er2
+ .endm
+ .macro SAVEEXR
+ .endm
+ .macro RESTOREEXR
+ .endm
+#endif
+#if defined(CONFIG_CPU_H8S)
+#define USERRET 10
+#define USEREXR 8
+INTERRUPTS = 128
.h8300s
+ .macro SHLL2 reg
+ shll.l #2,\reg
+ .endm
+ .macro SHLR2 reg
+ shlr.l #2,\reg
+ .endm
+ .macro SAVEREGS
+ stm.l er0-er3,@-sp
+ .endm
+ .macro RESTOREREGS
+ ldm.l @sp+,er2-er3
+ .endm
+ .macro SAVEEXR
+ mov.w @(USEREXR:16,er0),r1
+ mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */
+ .endm
+ .macro RESTOREEXR
+ mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */
+ mov.b r1l,r1h
+ mov.w r1,@(USEREXR:16,er0)
+ .endm
+#endif
+
/* CPU context save/restore macros. */
-
+
.macro SAVE_ALL
mov.l er0,@-sp
-
stc ccr,r0l /* check kernel mode */
btst #4,r0l
bne 5f
@@ -39,42 +91,38 @@
mov.l @sp,er0 /* restore saved er0 */
orc #0x10,ccr /* switch kernel stack */
mov.l @SYMBOL_NAME(sw_ksp),sp
- sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
- stm.l er0-er3,@-sp
- mov.l @SYMBOL_NAME(sw_usp),er0
- mov.l @(10:16,er0),er1 /* copy the RET addr */
- mov.l er1,@(LRET-LER3:16,sp)
- mov.w @(8:16,er0),r1
- mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */
+ sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
+ SAVEREGS
+ mov.l @SYMBOL_NAME(sw_usp),er0
+ mov.l @(USERRET:16,er0),er1 /* copy the RET addr */
+ mov.l er1,@(LRET-LER3:16,sp)
+ SAVEEXR
- mov.w e1,r1 /* e1 highbyte = ccr */
- and #0xef,r1h /* mask mode? flag */
- sub.w r0,r0
- mov.b r1h,r0l
- mov.w r0,@(LCCR-LER3:16,sp) /* copy ccr */
mov.l @(LORIG-LER3:16,sp),er0
mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */
+ mov.w e1,r1 /* e1 highbyte = ccr */
+ and #0xef,r1h /* mask mode? flag */
bra 6f
5:
/* kernel mode */
mov.l @sp,er0 /* restore saved er0 */
subs #2,sp /* set dummy ccr */
- stm.l er0-er3,@-sp
+ SAVEREGS
mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */
+6:
mov.b r1h,r1l
mov.b #0,r1h
- mov.w r1,@(LCCR-LER3:16,sp)
-6:
+ mov.w r1,@(LCCR-LER3:16,sp) /* set ccr */
mov.l er6,@-sp /* syscall arg #6 */
mov.l er5,@-sp /* syscall arg #5 */
mov.l er4,@-sp /* syscall arg #4 */
- .endm
+ .endm /* r1 = ccr */
.macro RESTORE_ALL
mov.l @sp+,er4
mov.l @sp+,er5
mov.l @sp+,er6
- ldm.l @sp+,er2-er3
+ RESTOREREGS
mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
btst #4,r0l
bne 7f
@@ -83,18 +131,16 @@
mov.l @SYMBOL_NAME(sw_usp),er0
mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */
mov.l er1,@er0
- mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */
- mov.b r1l,r1h
- mov.w r1,@(8:16,er0)
+ RESTOREEXR
mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
mov.b r1l,r1h
mov.b @(LRET+1-LER1:16,sp),r1l
mov.w r1,e1
mov.w @(LRET+2-LER1:16,sp),r1
- mov.l er1,@(10:16,er0)
+ mov.l er1,@(USERRET:16,er0)
mov.l @sp+,er1
- add.l #(LRET-LER1),sp /* remove LORIG - LRET */
+ add.l #(LRET-LER1),sp /* remove LORIG - LRET */
mov.l sp,@SYMBOL_NAME(sw_ksp)
andc #0xef,ccr /* switch to user mode */
mov.l er0,sp
@@ -108,7 +154,7 @@
adds #4,sp /* remove the sw created LVEC */
rte
.endm
-
+
.globl SYMBOL_NAME(system_call)
.globl SYMBOL_NAME(ret_from_exception)
.globl SYMBOL_NAME(ret_from_fork)
@@ -116,16 +162,25 @@
.globl SYMBOL_NAME(interrupt_redirect_table)
.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
.globl SYMBOL_NAME(resume)
-.globl SYMBOL_NAME(trace_break)
.globl SYMBOL_NAME(interrupt_entry)
-
-INTERRUPTS = 128
+.globl SYMBOL_NAME(trace_break)
+
#if defined(CONFIG_ROMKERNEL)
.section .int_redirect,"ax"
SYMBOL_NAME_LABEL(interrupt_redirect_table)
+#if defined(CONFIG_CPU_H8300H)
.rept 7
.long 0
.endr
+#endif
+#if defined(CONFIG_CPU_H8S)
+ .rept 5
+ .long 0
+ .endr
+ jmp @SYMBOL_NAME(trace_break)
+ .long 0
+#endif
+
jsr @SYMBOL_NAME(interrupt_entry) /* NMI */
jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */
.long 0
@@ -141,20 +196,20 @@ SYMBOL_NAME_LABEL(interrupt_redirect_table)
SYMBOL_NAME_LABEL(interrupt_redirect_table)
.space 4
#endif
-
+
.section .text
.align 2
SYMBOL_NAME_LABEL(interrupt_entry)
SAVE_ALL
- mov.w @(LCCR,sp),r0
- btst #4,r0l
+ mov.l sp,er0
+ add.l #LVEC,er0
+ btst #4,r1l
bne 1f
+ /* user LVEC */
mov.l @SYMBOL_NAME(sw_usp),er0
- mov.l @(4:16,er0),er0
- bra 2f
+ adds #4,er0
1:
- mov.l @(LVEC:16,sp),er0
-2:
+ mov.l @er0,er0 /* LVEC address */
#if defined(CONFIG_ROMKERNEL)
sub.l #SYMBOL_NAME(interrupt_redirect_table),er0
#endif
@@ -162,69 +217,62 @@ SYMBOL_NAME_LABEL(interrupt_entry)
mov.l @SYMBOL_NAME(interrupt_redirect_table),er1
sub.l er1,er0
#endif
- shlr.l #2,er0
+ SHLR2 er0
dec.l #1,er0
mov.l sp,er1
subs #4,er1 /* adjust ret_pc */
- jsr @SYMBOL_NAME(process_int)
- mov.l @SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
- beq 1f
- jsr @SYMBOL_NAME(do_softirq)
-1:
- jmp @SYMBOL_NAME(ret_from_exception)
+ jsr @SYMBOL_NAME(do_IRQ)
+ jmp @SYMBOL_NAME(ret_from_interrupt)
SYMBOL_NAME_LABEL(system_call)
subs #4,sp /* dummy LVEC */
SAVE_ALL
+ andc #0x7f,ccr
mov.l er0,er4
- mov.l #-ENOSYS,er0
- mov.l er0,@(LER0:16,sp)
/* save top of frame */
mov.l sp,er0
jsr @SYMBOL_NAME(set_esp0)
- cmp.l #NR_syscalls,er4
- bcc SYMBOL_NAME(ret_from_exception):16
- shll.l #2,er4
- mov.l #SYMBOL_NAME(sys_call_table),er0
- add.l er4,er0
- mov.l @er0,er0
- mov.l er0,er4
- beq SYMBOL_NAME(ret_from_exception):16
mov.l sp,er2
and.w #0xe000,r2
- mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
+ mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
btst #(TIF_SYSCALL_TRACE & 7),r2l
+ beq 1f
+ jsr @SYMBOL_NAME(do_syscall_trace)
+1:
+ cmp.l #NR_syscalls,er4
+ bcc badsys
+ SHLL2 er4
+ mov.l #SYMBOL_NAME(sys_call_table),er0
+ add.l er4,er0
+ mov.l @er0,er4
+ beq SYMBOL_NAME(ret_from_exception):16
mov.l @(LER1:16,sp),er0
mov.l @(LER2:16,sp),er1
mov.l @(LER3:16,sp),er2
- andc #0x7f,ccr
jsr @er4
- mov.l er0,@(LER0:16,sp) /* save the return value */
+ mov.l er0,@(LER0:16,sp) /* save the return value */
+ mov.l sp,er2
+ and.w #0xe000,r2
+ mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
+ btst #(TIF_SYSCALL_TRACE & 7),r2l
+ beq 2f
+ jsr @SYMBOL_NAME(do_syscall_trace)
+2:
#if defined(CONFIG_SYSCALL_PRINT)
jsr @SYMBOL_NAME(syscall_print)
#endif
- bra SYMBOL_NAME(ret_from_exception):8
-1:
- jsr SYMBOL_NAME(syscall_trace)
- mov.l @(LER1:16,sp),er0
- mov.l @(LER2:16,sp),er1
- mov.l @(LER3:16,sp),er2
- jsr @er4
- mov.l er0,@(LER0:16,sp) /* save the return value */
- jsr @SYMBOL_NAME(syscall_trace)
- bra SYMBOL_NAME(ret_from_exception):8
+ orc #0x80,ccr
+ bra resume_userspace
-SYMBOL_NAME_LABEL(ret_from_fork)
- mov.l er2,er0
- jsr @SYMBOL_NAME(schedule_tail)
- bra SYMBOL_NAME(ret_from_exception):8
+badsys:
+ mov.l #-ENOSYS,er0
+ mov.l er0,@(LER0:16,sp)
+ bra resume_userspace
-SYMBOL_NAME_LABEL(reschedule)
- /* save top of frame */
- mov.l sp,er0
- jsr @SYMBOL_NAME(set_esp0)
- jsr @SYMBOL_NAME(schedule)
+#if !defined(CONFIG_PREEMPT)
+#define resume_kernel restore_all
+#endif
SYMBOL_NAME_LABEL(ret_from_exception)
#if defined(CONFIG_PREEMPT)
@@ -232,58 +280,68 @@ SYMBOL_NAME_LABEL(ret_from_exception)
#endif
SYMBOL_NAME_LABEL(ret_from_interrupt)
mov.b @(LCCR+1:16,sp),r0l
- btst #4,r0l /* check if returning to kernel */
- bne done:8 /* if so, skip resched, signals */
+ btst #4,r0l
+ bne resume_kernel:8 /* return from kernel */
+resume_userspace:
andc #0x7f,ccr
mov.l sp,er4
- and.w #0xe000,r4
+ and.w #0xe000,r4 /* er4 <- current thread info */
mov.l @(TI_FLAGS:16,er4),er1
and.l #_TIF_WORK_MASK,er1
- beq done:8
-1:
- mov.l @(TI_FLAGS:16,er4),er1
+ beq restore_all:8
+work_pending:
btst #TIF_NEED_RESCHED,r1l
- bne SYMBOL_NAME(reschedule):16
+ bne work_resched:8
+ /* work notifysig */
mov.l sp,er0
- subs #4,er0 /* adjust retpc */
- mov.l er2,er1
- jsr @SYMBOL_NAME(do_signal)
+ subs #4,er0 /* er0: pt_regs */
+ jsr @SYMBOL_NAME(do_notify_resume)
+ bra restore_all:8
+work_resched:
+ mov.l sp,er0
+ jsr @SYMBOL_NAME(set_esp0)
+ jsr @SYMBOL_NAME(schedule)
+ bra resume_userspace:8
+restore_all:
+ RESTORE_ALL /* Does RTE */
+
#if defined(CONFIG_PREEMPT)
- bra done:8 /* userspace thoru */
-3:
- btst #4,r0l
- beq done:8 /* userspace thoru */
-4:
- mov.l @(TI_PRE_COUNT:16,er4),er1
- bne done:8
- mov.l @(TI_FLAGS:16,er4),er1
- btst #TIF_NEED_RESCHED,r1l
- beq done:8
- mov.b r0l,r0l
- bpl done:8 /* interrupt off (exception path?) */
- mov.l #PREEMPT_ACTIVE,er1
- mov.l er1,@(TI_PRE_COUNT:16,er4)
+resume_kernel:
+ mov.l @(TI_PRE_COUNT:16,er4),er0
+ bne restore_all:8
+need_resched:
+ mov.l @(TI_FLAGS:16,er4),er0
+ btst #TIF_NEED_RESCHED,r0l
+ beq restore_all:8
+ mov.b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */
+ bmi restore_all:8
+ mov.l #PREEMPT_ACTIVE,er0
+ mov.l er0,@(TI_PRE_COUNT:16,er4)
andc #0x7f,ccr
+ mov.l sp,er0
+ jsr @SYMBOL_NAME(set_esp0)
jsr @SYMBOL_NAME(schedule)
- sub.l er1,er1
- mov.l er1,@(TI_PRE_COUNT:16,er4)
orc #0x80,ccr
- bra 4b:8
+ bra need_resched:8
#endif
-done:
- RESTORE_ALL /* Does RTE */
+
+SYMBOL_NAME_LABEL(ret_from_fork)
+ mov.l er2,er0
+ jsr @SYMBOL_NAME(schedule_tail)
+ jmp @SYMBOL_NAME(ret_from_exception)
SYMBOL_NAME_LABEL(resume)
/*
- * er0 = prev
- * er1 = next
- * return last in er2
+ * Beware - when entering resume, offset of tss is in d1,
+ * prev (the current task) is in a0, next (the new task)
+ * is in a1 and d2.b is non-zero if the mm structure is
+ * shared between the tasks, so don't change these
+ * registers until their contents are no longer needed.
*/
/* save sr */
sub.w r3,r3
stc ccr,r3l
- stc exr,r3h
mov.w r3,@(THREAD_CCR+2:16,er0)
/* disable interrupts */
@@ -291,41 +349,45 @@ SYMBOL_NAME_LABEL(resume)
mov.l @SYMBOL_NAME(sw_usp),er3
mov.l er3,@(THREAD_USP:16,er0)
mov.l sp,@(THREAD_KSP:16,er0)
-
+
/* Skip address space switching if they are the same. */
/* FIXME: what did we hack out of here, this does nothing! */
mov.l @(THREAD_USP:16,er1),er0
mov.l er0,@SYMBOL_NAME(sw_usp)
mov.l @(THREAD_KSP:16,er1),sp
-
+
/* restore status register */
mov.w @(THREAD_CCR+2:16,er1),r3
ldc r3l,ccr
- ldc r3h,exr
-
rts
SYMBOL_NAME_LABEL(trace_break)
- subs #4,sp /* dummy LVEC */
+ subs #4,sp
SAVE_ALL
sub.l er1,er1
dec.l #1,er1
- mov.l er1,@(LORIG,sp)
+ mov.l er1,@(LORIG,sp)
mov.l sp,er0
jsr @SYMBOL_NAME(set_esp0)
mov.l @SYMBOL_NAME(sw_usp),er0
mov.l @er0,er1
+ mov.w @(-2:16,er1),r2
+ cmp.w #0x5730,r2
+ beq 1f
subs #2,er1
- mov.l er1,@er0
+ mov.l er1,@er0
+1:
and.w #0xff,e1
mov.l er1,er0
jsr @SYMBOL_NAME(trace_trap)
- jmp @SYMBOL_NAME(ret_from_exception)
+ jmp @SYMBOL_NAME(ret_from_exception)
.section .bss
SYMBOL_NAME_LABEL(sw_ksp)
- .space 4
+ .space 4
SYMBOL_NAME_LABEL(sw_usp)
- .space 4
+ .space 4
+
+ .end
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
deleted file mode 100644
index 3e4f479271c9..000000000000
--- a/arch/h8300/kernel/ints.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * linux/arch/h8300/kernel/ints.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * Copyright 1996 Roman Zippel
- * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/bootmem.h>
-#include <linux/hardirq.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/errno.h>
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-typedef struct irq_handler {
- irqreturn_t (*handler)(int, void *, struct pt_regs *);
- int flags;
- int count;
- void *dev_id;
- const char *devname;
-} irq_handler_t;
-
-static irq_handler_t *irq_list[NR_IRQS];
-static int use_kmalloc;
-
-extern unsigned long *interrupt_redirect_table;
-extern const int h8300_saved_vectors[];
-extern const unsigned long h8300_trap_table[];
-int h8300_enable_irq_pin(unsigned int irq);
-void h8300_disable_irq_pin(unsigned int irq);
-
-#define CPU_VECTOR ((unsigned long *)0x000000)
-#define ADDR_MASK (0xffffff)
-
-#if defined(CONFIG_RAMKERNEL)
-static unsigned long __init *get_vector_address(void)
-{
- unsigned long *rom_vector = CPU_VECTOR;
- unsigned long base,tmp;
- int vec_no;
-
- base = rom_vector[EXT_IRQ0] & ADDR_MASK;
-
- /* check romvector format */
- for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
- if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
- return NULL;
- }
-
- /* ramvector base address */
- base -= EXT_IRQ0*4;
-
- /* writerble check */
- tmp = ~(*(volatile unsigned long *)base);
- (*(volatile unsigned long *)base) = tmp;
- if ((*(volatile unsigned long *)base) != tmp)
- return NULL;
- return (unsigned long *)base;
-}
-#endif
-
-void __init init_IRQ(void)
-{
-#if defined(CONFIG_RAMKERNEL)
- int i;
- unsigned long *ramvec,*ramvec_p;
- const unsigned long *trap_entry;
- const int *saved_vector;
-
- ramvec = get_vector_address();
- if (ramvec == NULL)
- panic("interrupt vector serup failed.");
- else
- printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
-
- /* create redirect table */
- ramvec_p = ramvec;
- trap_entry = h8300_trap_table;
- saved_vector = h8300_saved_vectors;
- for ( i = 0; i < NR_IRQS; i++) {
- if (i == *saved_vector) {
- ramvec_p++;
- saved_vector++;
- } else {
- if ( i < NR_TRAPS ) {
- if (*trap_entry)
- *ramvec_p = VECTOR(*trap_entry);
- ramvec_p++;
- trap_entry++;
- } else
- *ramvec_p++ = REDIRECT(interrupt_entry);
- }
- }
- interrupt_redirect_table = ramvec;
-#ifdef DUMP_VECTOR
- ramvec_p = ramvec;
- for (i = 0; i < NR_IRQS; i++) {
- if ((i % 8) == 0)
- printk(KERN_DEBUG "\n%p: ",ramvec_p);
- printk(KERN_DEBUG "%p ",*ramvec_p);
- ramvec_p++;
- }
- printk(KERN_DEBUG "\n");
-#endif
-#endif
-}
-
-int request_irq(unsigned int irq,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *devname, void *dev_id)
-{
- irq_handler_t *irq_handle;
- if (irq < 0 || irq >= NR_IRQS) {
- printk(KERN_ERR "Incorrect IRQ %d from %s\n", irq, devname);
- return -EINVAL;
- }
-
- if (irq_list[irq] || (h8300_enable_irq_pin(irq) == -EBUSY))
- return -EBUSY;
-
- if (use_kmalloc)
- irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
- else {
- /* use bootmem allocater */
- irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
- irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000);
- }
-
- if (irq_handle == NULL)
- return -ENOMEM;
-
- irq_handle->handler = handler;
- irq_handle->flags = flags;
- irq_handle->count = 0;
- irq_handle->dev_id = dev_id;
- irq_handle->devname = devname;
- irq_list[irq] = irq_handle;
-
- if (irq_handle->flags & IRQF_SAMPLE_RANDOM)
- rand_initialize_irq(irq);
-
- enable_irq(irq);
- return 0;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
- if (irq >= NR_IRQS)
- return;
-
- if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id)
- printk(KERN_WARNING "Removing probably wrong IRQ %d from %s\n",
- irq, irq_list[irq]->devname);
- disable_irq(irq);
- h8300_disable_irq_pin(irq);
- if (((unsigned long)irq_list[irq] & 0x80000000) == 0) {
- kfree(irq_list[irq]);
- irq_list[irq] = NULL;
- }
-}
-
-EXPORT_SYMBOL(free_irq);
-
-/*
- * Do we need these probe functions on the m68k?
- */
-unsigned long probe_irq_on (void)
-{
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off (unsigned long irqs)
-{
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-void enable_irq(unsigned int irq)
-{
- if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
- IER_REGS |= 1 << (irq - EXT_IRQ0);
-}
-
-void disable_irq(unsigned int irq)
-{
- if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS))
- IER_REGS &= ~(1 << (irq - EXT_IRQ0));
-}
-
-asmlinkage void process_int(int irq, struct pt_regs *fp)
-{
- irq_enter();
- h8300_clear_isr(irq);
- if (irq >= NR_TRAPS && irq < NR_IRQS) {
- if (irq_list[irq]) {
- irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp);
- irq_list[irq]->count++;
- if (irq_list[irq]->flags & IRQF_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- }
- } else {
- BUG();
- }
- irq_exit();
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
- int i = *(loff_t *) v;
-
- if ((i < NR_IRQS) && (irq_list[i]!=NULL)) {
- seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
- seq_printf(p, "%s\n", irq_list[i]->devname);
- }
-
- return 0;
-}
-
-void init_irq_proc(void)
-{
-}
-
-static int __init enable_kmalloc(void)
-{
- use_kmalloc = 1;
- return 0;
-}
-core_initcall(enable_kmalloc);
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 8f2411db7eaf..d32bbf02fc48 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -111,10 +111,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -219,7 +216,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret;
}
-asmlinkage void syscall_trace(void)
+asmlinkage void do_syscall_trace(void)
{
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 02955604d760..62ea12d339b9 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -547,3 +547,9 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
}
return 0;
}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
+{
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs, NULL);
+}
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile
index b24ea08aa0a7..c5096369ea50 100644
--- a/arch/h8300/platform/h8300h/Makefile
+++ b/arch/h8300/platform/h8300h/Makefile
@@ -4,4 +4,4 @@
# Reuse any files we can from the H8/300H
#
-obj-y := entry.o irq_pin.o ptrace_h8300h.o
+obj-y := irq_pin.o ptrace_h8300h.o
diff --git a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S
deleted file mode 100644
index f86ac3b5d4de..000000000000
--- a/arch/h8300/platform/h8300h/entry.S
+++ /dev/null
@@ -1,332 +0,0 @@
-/* -*- mode: asm -*-
- *
- * linux/arch/h8300/platform/h8300h/entry.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- * David McCullough <davidm@snapgear.com>
- *
- */
-
-/*
- * entry.S
- * include exception/interrupt gateway
- * system call entry
- */
-
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-
- .h8300h
-
-/* CPU context save/restore macros. */
-
- .macro SAVE_ALL
- mov.l er0,@-sp
-
- stc ccr,r0l /* check kernel mode */
- btst #4,r0l
- bne 5f
-
- mov.l sp,@SYMBOL_NAME(sw_usp) /* user mode */
- mov.l @sp,er0
- orc #0x10,ccr
- mov.l @SYMBOL_NAME(sw_ksp),sp
- sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
- mov.l er0,@-sp
- mov.l er1,@-sp
- mov.l @SYMBOL_NAME(sw_usp),er0
- mov.l @(8:16,er0),er1 /* copy the RET addr */
- mov.l er1,@(LRET-LER1:16,sp)
-
- mov.w e1,r1 /* e1 highbyte = ccr */
- and #0xef,r1h /* mask mode? flag */
- sub.w r0,r0
- mov.b r1h,r0l
- mov.w r0,@(LCCR-LER1:16,sp) /* copy ccr */
- mov.l @(LORIG-LER1:16,sp),er0
- mov.l er0,@(LER0-LER1:16,sp) /* copy ER0 */
- bra 6f
-5:
- mov.l @sp,er0 /* kernel mode */
- subs #2,sp /* dummy ccr */
- mov.l er0,@-sp
- mov.l er1,@-sp
- mov.w @(LRET-LER1:16,sp),r1 /* copy old ccr */
- mov.b r1h,r1l
- mov.b #0,r1h
- mov.w r1,@(LCCR-LER1:16,sp) /* set ccr */
-6:
- mov.l er2,@-sp
- mov.l er3,@-sp
- mov.l er6,@-sp /* syscall arg #6 */
- mov.l er5,@-sp /* syscall arg #5 */
- mov.l er4,@-sp /* syscall arg #4 */
- .endm
-
- .macro RESTORE_ALL
- mov.l @sp+,er4
- mov.l @sp+,er5
- mov.l @sp+,er6
- mov.l @sp+,er3
- mov.l @sp+,er2
- mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
- btst #4,r0l
- bne 7f
-
- orc #0x80,ccr
- mov.l @SYMBOL_NAME(sw_usp),er0
- mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */
- mov.l er1,@er0
- mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
- mov.b r1l,r1h
- mov.b @(LRET+1-LER1:16,sp),r1l
- mov.w r1,e1
- mov.w @(LRET+2-LER1:16,sp),r1
- mov.l er1,@(8:16,er0)
-
- mov.l @sp+,er1
- add.l #(LRET-LER1),sp /* remove LORIG - LRET */
- mov.l sp,@SYMBOL_NAME(sw_ksp)
- mov.l er0,sp
- bra 8f
-7:
- mov.l @sp+,er1
- adds #4,sp
- adds #2,sp
-8:
- mov.l @sp+,er0
- adds #4,sp /* remove the sw created LVEC */
- rte
- .endm
-
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(ret_from_exception)
-.globl SYMBOL_NAME(ret_from_fork)
-.globl SYMBOL_NAME(ret_from_interrupt)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
-.globl SYMBOL_NAME(resume)
-.globl SYMBOL_NAME(interrupt_redirect_table)
-.globl SYMBOL_NAME(interrupt_entry)
-.globl SYMBOL_NAME(system_call)
-.globl SYMBOL_NAME(trace_break)
-
-#if defined(CONFIG_ROMKERNEL)
-INTERRUPTS = 64
- .section .int_redirect,"ax"
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
- .rept 7
- .long 0
- .endr
- jsr @SYMBOL_NAME(interrupt_entry) /* NMI */
- jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */
- .long 0
- .long 0
- jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */
- .rept INTERRUPTS-12
- jsr @SYMBOL_NAME(interrupt_entry)
- .endr
-#endif
-#if defined(CONFIG_RAMKERNEL)
-.globl SYMBOL_NAME(interrupt_redirect_table)
- .section .bss
-SYMBOL_NAME_LABEL(interrupt_redirect_table)
- .space 4
-#endif
-
- .section .text
- .align 2
-SYMBOL_NAME_LABEL(interrupt_entry)
- SAVE_ALL
- mov.w @(LCCR,sp),r0
- btst #4,r0l
- bne 1f
- mov.l @SYMBOL_NAME(sw_usp),er0
- mov.l @(4:16,er0),er0
- bra 2f
-1:
- mov.l @(LVEC,sp),er0
-2:
-#if defined(CONFIG_ROMKERNEL)
- sub.l #SYMBOL_NAME(interrupt_redirect_table),er0
-#endif
-#if defined(CONFIG_RAMKERNEL)
- mov.l @SYMBOL_NAME(interrupt_redirect_table),er1
- sub.l er1,er0
-#endif
- shlr.l er0
- shlr.l er0
- dec.l #1,er0
- mov.l sp,er1
- subs #4,er1 /* adjust ret_pc */
- jsr @SYMBOL_NAME(do_IRQ)
- mov.l @SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
- beq 1f
- jsr @SYMBOL_NAME(do_softirq)
-1:
- jmp @SYMBOL_NAME(ret_from_interrupt)
-
-SYMBOL_NAME_LABEL(system_call)
- subs #4,sp /* dummy LVEC */
- SAVE_ALL
- mov.w @(LCCR:16,sp),r1
- bset #4,r1l
- ldc r1l,ccr
- mov.l er0,er4
- mov.l #-ENOSYS,er0
- mov.l er0,@(LER0:16,sp)
-
- /* save top of frame */
- mov.l sp,er0
- jsr @SYMBOL_NAME(set_esp0)
- cmp.l #NR_syscalls,er4
- bcc SYMBOL_NAME(ret_from_exception):16
- shll.l er4
- shll.l er4
- mov.l #SYMBOL_NAME(sys_call_table),er0
- add.l er4,er0
- mov.l @er0,er4
- beq SYMBOL_NAME(ret_from_exception):16
- mov.l sp,er2
- and.w #0xe000,r2
- mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
- btst #(TIF_SYSCALL_TRACE & 7),r2l
- bne 1f
- mov.l @(LER1:16,sp),er0
- mov.l @(LER2:16,sp),er1
- mov.l @(LER3:16,sp),er2
- jsr @er4
- mov.l er0,@(LER0:16,sp) /* save the return value */
-#if defined(CONFIG_SYSCALL_PRINT)
- jsr @SYMBOL_NAME(syscall_print)
-#endif
- bra SYMBOL_NAME(ret_from_exception):8
-1:
- jsr SYMBOL_NAME(syscall_trace)
- mov.l @(LER1:16,sp),er0
- mov.l @(LER2:16,sp),er1
- mov.l @(LER3:16,sp),er2
- jsr @er4
- mov.l er0,@(LER0:16,sp) /* save the return value */
- jsr @SYMBOL_NAME(syscall_trace)
- bra SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(ret_from_fork)
- mov.l er2,er0
- jsr @SYMBOL_NAME(schedule_tail)
- bra SYMBOL_NAME(ret_from_exception):8
-
-SYMBOL_NAME_LABEL(reschedule)
- /* save top of frame */
- mov.l sp,er0
- jsr @SYMBOL_NAME(set_esp0)
- jsr @SYMBOL_NAME(schedule)
-
-SYMBOL_NAME_LABEL(ret_from_exception)
-#if defined(CONFIG_PREEMPT)
- orc #0x80,ccr
-#endif
-SYMBOL_NAME_LABEL(ret_from_interrupt)
- mov.b @(LCCR+1:16,sp),r0l
- btst #4,r0l /* check if returning to kernel */
- bne done:8 /* if so, skip resched, signals */
- andc #0x7f,ccr
- mov.l sp,er4
- and.w #0xe000,r4
- mov.l @(TI_FLAGS:16,er4),er1
- and.l #_TIF_WORK_MASK,er1
- beq done:8
-1:
- mov.l @(TI_FLAGS:16,er4),er1
- btst #TIF_NEED_RESCHED,r1l
- bne SYMBOL_NAME(reschedule):16
- mov.l sp,er0
- subs #4,er0 /* adjust retpc */
- mov.l er2,er1
- jsr @SYMBOL_NAME(do_signal)
-#if defined(CONFIG_PREEMPT)
- bra done:8 /* userspace thoru */
-3:
- btst #4,r0l
- beq done:8 /* userspace thoru */
-4:
- mov.l @(TI_PRE_COUNT:16,er4),er1
- bne done:8
- mov.l @(TI_FLAGS:16,er4),er1
- btst #TIF_NEED_RESCHED,r1l
- beq done:8
- mov.b r0l,r0l
- bpl done:8 /* interrupt off (exception path?) */
- mov.l #PREEMPT_ACTIVE,er1
- mov.l er1,@(TI_PRE_COUNT:16,er4)
- andc #0x7f,ccr
- jsr @SYMBOL_NAME(schedule)
- sub.l er1,er1
- mov.l er1,@(TI_PRE_COUNT:16,er4)
- orc #0x80,ccr
- bra 4b:8
-#endif
-done:
- RESTORE_ALL /* Does RTE */
-
-SYMBOL_NAME_LABEL(resume)
- /*
- * Beware - when entering resume, offset of tss is in d1,
- * prev (the current task) is in a0, next (the new task)
- * is in a1 and d2.b is non-zero if the mm structure is
- * shared between the tasks, so don't change these
- * registers until their contents are no longer needed.
- */
-
- /* save sr */
- sub.w r3,r3
- stc ccr,r3l
- mov.w r3,@(THREAD_CCR+2:16,er0)
-
- /* disable interrupts */
- orc #0x80,ccr
- mov.l @SYMBOL_NAME(sw_usp),er3
- mov.l er3,@(THREAD_USP:16,er0)
- mov.l sp,@(THREAD_KSP:16,er0)
-
- /* Skip address space switching if they are the same. */
- /* FIXME: what did we hack out of here, this does nothing! */
-
- mov.l @(THREAD_USP:16,er1),er0
- mov.l er0,@SYMBOL_NAME(sw_usp)
- mov.l @(THREAD_KSP:16,er1),sp
-
- /* restore status register */
- mov.w @(THREAD_CCR+2:16,er1),r3
-
- ldc r3l,ccr
- rts
-
-SYMBOL_NAME_LABEL(trace_break)
- subs #4,sp
- SAVE_ALL
- sub.l er1,er1
- dec.l #1,er1
- mov.l er1,@(LORIG,sp)
- mov.l sp,er0
- jsr @SYMBOL_NAME(set_esp0)
- mov.l @SYMBOL_NAME(sw_usp),er0
- mov.l @er0,er1
- subs #2,er1
- mov.l er1,@er0
- and.w #0xff,e1
- mov.l er1,er0
- jsr @SYMBOL_NAME(trace_trap)
- jmp @SYMBOL_NAME(ret_from_exception)
-
- .section .bss
-SYMBOL_NAME_LABEL(sw_ksp)
- .space 4
-SYMBOL_NAME_LABEL(sw_usp)
- .space 4
diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile
index 0847b15d4256..bf1241883766 100644
--- a/arch/h8300/platform/h8s/Makefile
+++ b/arch/h8300/platform/h8s/Makefile
@@ -4,4 +4,4 @@
# Reuse any files we can from the H8S
#
-obj-y := entry.o ints_h8s.o ptrace_h8s.o
+obj-y := ints_h8s.o ptrace_h8s.o
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index b1b2b30b1b8e..c7c9c2a15fab 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1212,21 +1212,26 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-menu "Instrumentation Support"
+menuconfig INSTRUMENTATION
+ bool "Instrumentation Support"
depends on EXPERIMENTAL
+ default y
+
+if INSTRUMENTATION
source "arch/i386/oprofile/Kconfig"
config KPROBES
- bool "Kprobes (EXPERIMENTAL)"
- depends on KALLSYMS && EXPERIMENTAL && MODULES
+ bool "Kprobes"
+ depends on KALLSYMS && MODULES
help
Kprobes allows you to trap at almost any kernel address and
execute a callback function. register_kprobe() establishes
a probepoint and specifies the callback. Kprobes is useful
for kernel debugging, non-intrusive instrumentation and testing.
If in doubt, say "N".
-endmenu
+
+endif # INSTRUMENTATION
source "arch/i386/Kconfig.debug"
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index bd28f9f9b4b7..181cc29a7c4f 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -108,6 +108,7 @@ drivers-$(CONFIG_PCI) += arch/i386/pci/
# must be linked after kernel/
drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/
drivers-$(CONFIG_PM) += arch/i386/power/
+drivers-$(CONFIG_FB) += arch/i386/video/
CFLAGS += $(mflags-y)
AFLAGS += $(mflags-y)
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 4112afe712b9..47001d50a083 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -222,6 +222,7 @@
#include <linux/capability.h>
#include <linux/device.h>
#include <linux/kernel.h>
+#include <linux/freezer.h>
#include <linux/smp.h>
#include <linux/dmi.h>
#include <linux/suspend.h>
@@ -2311,7 +2312,6 @@ static int __init apm_init(void)
remove_proc_entry("apm", NULL);
return err;
}
- kapmd_task->flags |= PF_NOFREEZE;
wake_up_process(kapmd_task);
if (num_online_cpus() > 1 && !smp ) {
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index a1808022ea19..2452c6fbe992 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -278,7 +278,7 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg)
struct range {
unsigned long start;
unsigned long end;
- } prev, curr;
+ } uninitialized_var(prev), curr;
efi_memory_desc_t *md;
unsigned long start, end;
void *p;
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index f74dfc419b56..82714668d43b 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -168,6 +168,12 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
.section .init.text,"ax",@progbits
#endif
+ /* Do an early initialization of the fixmap area */
+ movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
+ movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
+ addl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
+ movl %eax, 4092(%edx)
+
#ifdef CONFIG_SMP
ENTRY(startup_32_smp)
cld
@@ -507,6 +513,8 @@ ENTRY(_stext)
.section ".bss.page_aligned","w"
ENTRY(swapper_pg_dir)
.fill 1024,4,0
+ENTRY(swapper_pg_pmd)
+ .fill 1024,4,0
ENTRY(empty_zero_page)
.fill 4096,1,0
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7f8b7af2b95f..21db8f56c9a1 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -667,6 +667,7 @@ static int balanced_irq(void *unused)
set_pending_irq(i, cpumask_of_cpu(0));
}
+ set_freezable();
for ( ; ; ) {
time_remaining = schedule_timeout_interruptible(time_remaining);
try_to_freeze();
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index fba121f7973f..03b7f5584d71 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -295,7 +295,7 @@ static unsigned int
last_irq_sums [NR_CPUS],
alert_counter [NR_CPUS];
-void touch_nmi_watchdog (void)
+void touch_nmi_watchdog(void)
{
if (nmi_watchdog > 0) {
unsigned cpu;
@@ -304,8 +304,10 @@ void touch_nmi_watchdog (void)
* Just reset the alert counters, (other CPUs might be
* spinning on locks we hold):
*/
- for_each_present_cpu (cpu)
- alert_counter[cpu] = 0;
+ for_each_present_cpu(cpu) {
+ if (alert_counter[cpu])
+ alert_counter[cpu] = 0;
+ }
}
/*
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 06dfa65ad180..6c49acb96982 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -538,8 +538,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
return 1;
}
-static noinline void __switch_to_xtra(struct task_struct *next_p,
- struct tss_struct *tss)
+#ifdef CONFIG_SECCOMP
+void hard_disable_TSC(void)
+{
+ write_cr4(read_cr4() | X86_CR4_TSD);
+}
+void disable_TSC(void)
+{
+ preempt_disable();
+ if (!test_and_set_thread_flag(TIF_NOTSC))
+ /*
+ * Must flip the CPU state synchronously with
+ * TIF_NOTSC in the current running context.
+ */
+ hard_disable_TSC();
+ preempt_enable();
+}
+void hard_enable_TSC(void)
+{
+ write_cr4(read_cr4() & ~X86_CR4_TSD);
+}
+#endif /* CONFIG_SECCOMP */
+
+static noinline void
+__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ struct tss_struct *tss)
{
struct thread_struct *next;
@@ -555,6 +578,17 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
set_debugreg(next->debugreg[7], 7);
}
+#ifdef CONFIG_SECCOMP
+ if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+ test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+ /* prev and next are different */
+ if (test_tsk_thread_flag(next_p, TIF_NOTSC))
+ hard_disable_TSC();
+ else
+ hard_enable_TSC();
+ }
+#endif
+
if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
/*
* Disable the bitmap via an invalid offset. We still cache
@@ -586,33 +620,6 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
}
/*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
- struct task_struct *next_p)
-{
- struct thread_info *prev, *next;
-
- /*
- * gcc should eliminate the ->thread_info dereference if
- * has_secure_computing returns 0 at compile time (SECCOMP=n).
- */
- prev = task_thread_info(prev_p);
- next = task_thread_info(next_p);
-
- if (has_secure_computing(prev) || has_secure_computing(next)) {
- /* slow path here */
- if (has_secure_computing(prev) &&
- !has_secure_computing(next)) {
- write_cr4(read_cr4() & ~X86_CR4_TSD);
- } else if (!has_secure_computing(prev) &&
- has_secure_computing(next))
- write_cr4(read_cr4() | X86_CR4_TSD);
- }
-}
-
-/*
* switch_to(x,yn) should switch tasks from x to y.
*
* We fsave/fwait so that an exception goes off at the right time
@@ -689,11 +696,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
/*
* Now maybe handle debug registers and/or IO bitmaps
*/
- if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
- || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
- __switch_to_xtra(next_p, tss);
-
- disable_tsc(prev_p, next_p);
+ if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
+ task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
+ __switch_to_xtra(prev_p, next_p, tss);
/*
* Leave lazy mode, flushing any hypercalls made here.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 0c0ceec5de00..1c075f58d1f9 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -358,17 +358,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp, datap);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -395,10 +387,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/i386/kernel/smpcommon.c b/arch/i386/kernel/smpcommon.c
index 1868ae18eb4d..bbfe85a0f699 100644
--- a/arch/i386/kernel/smpcommon.c
+++ b/arch/i386/kernel/smpcommon.c
@@ -47,7 +47,7 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
EXPORT_SYMBOL(smp_call_function);
/**
- * smp_call_function_single - Run a function on another CPU
+ * smp_call_function_single - Run a function on a specific CPU
* @cpu: The target CPU. Cannot be the calling CPU.
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
@@ -66,9 +66,11 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
int ret;
int me = get_cpu();
if (cpu == me) {
- WARN_ON(1);
+ local_irq_disable();
+ func(info);
+ local_irq_enable();
put_cpu();
- return -EBUSY;
+ return 0;
}
ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 90da0575fcff..18c1c285836d 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -390,7 +390,7 @@ void die(const char * str, struct pt_regs * regs, long err)
unsigned long esp;
unsigned short ss;
- report_bug(regs->eip);
+ report_bug(regs->eip, regs);
printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
@@ -433,6 +433,7 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
+ add_taint(TAINT_DIE);
spin_unlock_irqrestore(&die.lock, flags);
if (!regs)
diff --git a/arch/i386/video/Makefile b/arch/i386/video/Makefile
new file mode 100644
index 000000000000..2c447c94adcc
--- /dev/null
+++ b/arch/i386/video/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_FB) += fbdev.o
diff --git a/arch/i386/video/fbdev.c b/arch/i386/video/fbdev.c
new file mode 100644
index 000000000000..48fb38d7d2c0
--- /dev/null
+++ b/arch/i386/video/fbdev.c
@@ -0,0 +1,32 @@
+/*
+ * arch/i386/video/fbdev.c - i386 Framebuffer
+ *
+ * Copyright (C) 2007 Antonino Daplas <adaplas@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.
+ *
+ */
+#include <linux/fb.h>
+#include <linux/pci.h>
+
+int fb_is_primary_device(struct fb_info *info)
+{
+ struct device *device = info->device;
+ struct pci_dev *pci_dev = NULL;
+ struct resource *res = NULL;
+ int retval = 0;
+
+ if (device)
+ pci_dev = to_pci_dev(device);
+
+ if (pci_dev)
+ res = &pci_dev->resource[PCI_ROM_RESOURCE];
+
+ if (res && res->flags & IORESOURCE_ROM_SHADOW)
+ retval = 1;
+
+ return retval;
+}
+EXPORT_SYMBOL(fb_is_primary_device);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index db9ddff95841..616c96e73483 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -582,8 +582,8 @@ menu "Instrumentation Support"
source "arch/ia64/oprofile/Kconfig"
config KPROBES
- bool "Kprobes (EXPERIMENTAL)"
- depends on KALLSYMS && EXPERIMENTAL && MODULES
+ bool "Kprobes"
+ depends on KALLSYMS && MODULES
help
Kprobes allows you to trap at almost any kernel address and
execute a callback function. register_kprobe() establishes
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index c1dca226b479..cd4adf52f174 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -34,6 +34,7 @@
#include <linux/efi.h>
#include <linux/nodemask.h>
#include <linux/bitops.h> /* hweight64() */
+#include <linux/crash_dump.h>
#include <asm/delay.h> /* ia64_get_itc() */
#include <asm/io.h>
@@ -43,6 +44,8 @@
#include <asm/acpi-ext.h>
+extern int swiotlb_late_init_with_default_size (size_t size);
+
#define PFX "IOC: "
/*
@@ -2026,11 +2029,24 @@ sba_init(void)
if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
return 0;
+#if defined(CONFIG_IA64_GENERIC) && defined(CONFIG_CRASH_DUMP)
+ /* If we are booting a kdump kernel, the sba_iommu will
+ * cause devices that were not shutdown properly to MCA
+ * as soon as they are turned back on. Our only option for
+ * a successful kdump kernel boot is to use the swiotlb.
+ */
+ if (elfcorehdr_addr < ELFCORE_ADDR_MAX) {
+ if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
+ panic("Unable to initialize software I/O TLB:"
+ " Try machvec=dig boot option");
+ machvec_init("dig");
+ return 0;
+ }
+#endif
+
acpi_bus_register_driver(&acpi_sba_ioc_driver);
if (!ioc_list) {
#ifdef CONFIG_IA64_GENERIC
- extern int swiotlb_late_init_with_default_size (size_t size);
-
/*
* If we didn't find something sba_iommu can claim, we
* need to setup the swiotlb and switch to the dig machvec.
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
index 300acd913d9c..1189d035d316 100644
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ b/arch/ia64/hp/sim/boot/fw-emu.c
@@ -329,11 +329,6 @@ sys_fw_init (const char *args, int arglen)
strcpy(sal_systab->product_id, "HP-simulator");
#endif
-#ifdef CONFIG_IA64_SDV
- strcpy(sal_systab->oem_id, "Intel");
- strcpy(sal_systab->product_id, "SDV");
-#endif
-
/* fill in an entry point: */
sal_ed->type = SAL_DESC_ENTRY_POINT;
sal_ed->pal_proc = __pa(pal_desc[0]);
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 324ea7565e2c..ef252df50e1e 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -36,10 +36,6 @@
#include <asm/hw_irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_KDB
-# include <linux/kdb.h>
-#endif
-
#undef SIMSERIAL_DEBUG /* define this to get some debug information */
#define KEYBOARD_INTR 3 /* must match with simulator! */
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index c05bda662364..6f4d3d06f0ed 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -261,7 +261,7 @@ elf32_set_personality (void)
}
static unsigned long
-elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
{
unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 99b665e2b1d5..06efd1f9b800 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -304,7 +304,7 @@ ia32_syscall_table:
data8 sys_ni_syscall /* init_module */
data8 sys_ni_syscall /* delete_module */
data8 sys_ni_syscall /* get_kernel_syms */ /* 130 */
- data8 sys_quotactl
+ data8 sys32_quotactl
data8 sys_getpgid
data8 sys_fchdir
data8 sys_ni_syscall /* sys_bdflush */
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 75ec3478d8a2..73ca86d03810 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -28,6 +28,7 @@
#include <linux/time.h>
#include <linux/efi.h>
#include <linux/kexec.h>
+#include <linux/mm.h>
#include <asm/io.h>
#include <asm/kregs.h>
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 8589e84a27c6..3f926c2dc708 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -247,6 +247,9 @@ ENTRY(fsys_gettimeofday)
.time_redo:
.pred.rel.mutex p8,p9,p10
ld4.acq r28 = [r29] // xtime_lock.sequence. Must come first for locking purposes
+ ;;
+ and r28 = ~1,r28 // Make sequence even to force retry if odd
+ ;;
(p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!!
add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20
(p9) ld8 r2 = [r30] // readq(ti->address). Could also have latency issues..
@@ -284,7 +287,6 @@ EX(.fail_efault, probe.w.fault r31, 3) // This takes 5 cycles and we have spare
(p15) ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET
(p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful redo
// simulate tbit.nz.or p7,p0 = r28,0
- and r28 = ~1,r28 // Make sequence even to force retry if odd
getf.sig r2 = f8
mf
add r8 = r8,r18 // Add time interpolator offset
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 188fb73c6845..4d9864cc92c9 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -390,10 +390,6 @@ early_console_setup (char *cmdline)
if (!efi_setup_pcdp_console(cmdline))
earlycons++;
#endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (!early_serial_console_init(cmdline))
- earlycons++;
-#endif
return (earlycons) ? 0 : -1;
}
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 15ad85da15a9..3aeaf15e468b 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -69,6 +69,7 @@ die (const char *str, struct pt_regs *regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die.lock);
if (panic_on_oops)
diff --git a/arch/ia64/lib/checksum.c b/arch/ia64/lib/checksum.c
index 4411d9baeb21..9fc955026f86 100644
--- a/arch/ia64/lib/checksum.c
+++ b/arch/ia64/lib/checksum.c
@@ -60,6 +60,7 @@ csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len,
result = (result & 0xffffffff) + (result >> 32);
return (__force __wsum)result;
}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
extern unsigned long do_csum (const unsigned char *, long);
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 6da9854751cd..df8d5bed6119 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -750,9 +750,10 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
goto error;
} else
if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+ int cpuobj_index = 0;
+
memset(p, 0, a.sz);
for (i = 0; i < nobj; i++) {
- int cpuobj_index = 0;
if (!SN_HWPERF_IS_NODE(objs + i))
continue;
node = sn_hwperf_obj_to_cnode(objs + i);
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index c3bb8a755b00..8ccf3e47bff8 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -31,6 +31,9 @@ config GENERIC_IRQ_PROBE
config NO_IOPORT
def_bool y
+config NO_DMA
+ def_bool y
+
source "init/Kconfig"
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 5f02b3144875..57a92ef31a90 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -595,7 +595,6 @@ void ptrace_disable(struct task_struct *child)
static int
do_ptrace(long request, struct task_struct *child, long addr, long data)
{
- unsigned long tmp;
int ret;
switch (request) {
@@ -604,11 +603,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data)
*/
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (ret == sizeof(tmp))
- ret = put_user(tmp,(unsigned long __user *) data);
- else
- ret = -EIO;
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
/*
@@ -624,15 +619,9 @@ do_ptrace(long request, struct task_struct *child, long addr, long data)
*/
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = access_process_vm(child, addr, &data, sizeof(data), 1);
- if (ret == sizeof(data)) {
- ret = 0;
- if (request == PTRACE_POKETEXT) {
- invalidate_cache();
- }
- } else {
- ret = -EIO;
- }
+ ret = generic_ptrace_pokedata(child, addr, data);
+ if (ret == 0 && request == PTRACE_POKETEXT)
+ invalidate_cache();
break;
/*
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index cdba9fd6d82f..2cf0690b7882 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -128,10 +128,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
- i = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (i != sizeof(tmp))
- goto out_eio;
- ret = put_user(tmp, (unsigned long *)data);
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */
@@ -160,8 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
- goto out_eio;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index a27a4fa33296..4e2752a0e89b 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -1170,6 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
console_verbose();
printk("%s: %08x\n",str,nr);
show_registers(fp);
+ add_taint(TAINT_DIE);
do_exit(SIGSEGV);
}
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index cf6bb51945a2..6216f12a756b 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -422,3 +422,4 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
);
return(sum);
}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 941955dc3b7c..846f97534685 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -377,7 +377,7 @@ unsigned long get_wchan(struct task_struct *p)
fp = ((struct switch_stack *)p->thread.ksp)->a6;
do {
if (fp < stack_page+sizeof(struct thread_info) ||
- fp >= 8184+stack_page)
+ fp >= THREAD_SIZE-8+stack_page)
return 0;
pc = ((unsigned long *)fp)[1];
if (!in_sched_functions(pc))
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index f54b6a3dfecb..ef70ca070ce2 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -106,17 +106,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long *) data);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -159,10 +151,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 8133b1047353..80f4e9d74ac1 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -1,8 +1,8 @@
/*
* linux/arch/m68knommu/kernel/setup.c
*
- * Copyright (C) 1999-2004 Greg Ungerer (gerg@snapgear.com)
- * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@lineo.ca>
+ * Copyright (C) 1999-2007 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@uClinux.org>
* Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
* Copyright (C) 1995 Hamish Macdonald
@@ -20,17 +20,13 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/fs.h>
#include <linux/fb.h>
#include <linux/module.h>
#include <linux/console.h>
-#include <linux/genhd.h>
#include <linux/errno.h>
#include <linux/string.h>
-#include <linux/major.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <linux/init.h>
#include <asm/setup.h>
@@ -46,34 +42,19 @@ EXPORT_SYMBOL(memory_end);
char __initdata command_line[COMMAND_LINE_SIZE];
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
+void (*mach_trap_init)(void);
-void (*mach_sched_init) (irq_handler_t handler);
-void (*mach_tick)( void );
-/* machine dependent keyboard functions */
-int (*mach_keyb_init) (void);
-int (*mach_kbdrate) (struct kbd_repeat *);
-void (*mach_kbd_leds) (unsigned int);
-/* machine dependent irq functions */
-void (*mach_init_IRQ) (void);
-irq_handler_t mach_default_handler;
-int (*mach_get_irq_list) (struct seq_file *, void *);
-void (*mach_process_int) (int irq, struct pt_regs *fp);
-void (*mach_trap_init) (void);
/* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
-void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
-int (*mach_hwclk) (int, struct rtc_time*);
-int (*mach_set_clock_mmss) (unsigned long);
-void (*mach_mksound)( unsigned int count, unsigned int ticks );
-void (*mach_reset)( void );
-void (*waitbut)(void) = dummy_waitbut;
-void (*mach_debug_init)(void);
-void (*mach_halt)( void );
-void (*mach_power_off)( void );
+void (*mach_sched_init)(irq_handler_t handler);
+void (*mach_tick)(void);
+void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
+int (*mach_set_clock_mmss)(unsigned long);
+unsigned long (*mach_gettimeoffset)(void);
+
+/* machine dependent reboot functions */
+void (*mach_reset)(void);
+void (*mach_halt)(void);
+void (*mach_power_off)(void);
#ifdef CONFIG_M68000
@@ -134,13 +115,6 @@ void (*mach_power_off)( void );
#define CPU "UNKNOWN"
#endif
-/* (es) */
-/* note: why is this defined here? the must be a better place to put this */
-#if defined( CONFIG_TELOS) || defined( CONFIG_UCDIMM ) || defined( CONFIG_UCSIMM ) || defined(CONFIG_DRAGEN2) || (defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ))
-#define CAT_ROMARRAY
-#endif
-/* (/es) */
-
extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
extern int _ramstart, _ramend;
@@ -148,15 +122,8 @@ void setup_arch(char **cmdline_p)
{
int bootmap_size;
-#if defined(CAT_ROMARRAY) && defined(DEBUG)
- extern int __data_rom_start;
- extern int __data_start;
- int *romarray = (int *)((int) &__data_rom_start +
- (int)&_edata - (int)&__data_start);
-#endif
-
memory_start = PAGE_ALIGN(_ramstart);
- memory_end = _ramend; /* by now the stack is part of the init task */
+ memory_end = _ramend;
init_mm.start_code = (unsigned long) &_stext;
init_mm.end_code = (unsigned long) &_etext;
@@ -220,11 +187,7 @@ void setup_arch(char **cmdline_p)
(int) &_sbss, (int) &_ebss);
printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
"STACK=0x%06x-0x%06x\n",
-#ifdef CAT_ROMARRAY
- (int) romarray, ((int) romarray) + romarray[2],
-#else
(int) &_ebss, (int) memory_start,
-#endif
(int) memory_start, (int) memory_end,
(int) memory_end, (int) _ramend);
#endif
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index bed5f47bf568..fde04e1757f7 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -83,6 +83,7 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr)
printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
show_stack(NULL, (unsigned long *)fp);
+ add_taint(TAINT_DIE);
do_exit(SIGSEGV);
}
diff --git a/arch/m68knommu/mm/memory.c b/arch/m68knommu/mm/memory.c
index 411e45248e5c..1a66b71035a4 100644
--- a/arch/m68knommu/mm/memory.c
+++ b/arch/m68knommu/mm/memory.c
@@ -17,90 +17,14 @@
#include <linux/types.h>
#include <linux/slab.h>
-#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/io.h>
/*
- * cache_clear() semantics: Clear any cache entries for the area in question,
- * without writing back dirty entries first. This is useful if the data will
- * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
- * _physical_ address.
- */
-
-void cache_clear (unsigned long paddr, int len)
-{
-}
-
-
-/*
- * Define cache invalidate functions. The ColdFire 5407 is really
- * the only processor that needs to do some work here. Anything
- * that has separate data and instruction caches will be a problem.
- */
-#ifdef CONFIG_M5407
-
-static __inline__ void cache_invalidate_lines(unsigned long paddr, int len)
-{
- unsigned long sset, eset;
-
- sset = (paddr & 0x00000ff0);
- eset = ((paddr + len) & 0x0000ff0) + 0x10;
-
- __asm__ __volatile__ (
- "nop\n\t"
- "clrl %%d0\n\t"
- "1:\n\t"
- "movel %0,%%a0\n\t"
- "addl %%d0,%%a0\n\t"
- "2:\n\t"
- ".word 0xf4e8\n\t"
- "addl #0x10,%%a0\n\t"
- "cmpl %1,%%a0\n\t"
- "blt 2b\n\t"
- "addql #1,%%d0\n\t"
- "cmpil #4,%%d0\n\t"
- "bne 1b"
- : : "a" (sset), "a" (eset) : "d0", "a0" );
-}
-
-#else
-#define cache_invalidate_lines(a,b)
-#endif
-
-
-/*
- * cache_push() semantics: Write back any dirty cache data in the given area,
- * and invalidate the range in the instruction cache. It needs not (but may)
- * invalidate those entries also in the data cache. The range is defined by a
- * _physical_ address.
- */
-
-void cache_push (unsigned long paddr, int len)
-{
- cache_invalidate_lines(paddr, len);
-}
-
-
-/*
- * cache_push_v() semantics: Write back any dirty cache data in the given
- * area, and invalidate those entries at least in the instruction cache. This
- * is intended to be used after data has been written that can be executed as
- * code later. The range is defined by a _user_mode_ _virtual_ address (or,
- * more exactly, the space is defined by the %sfc/%dfc register.)
- */
-
-void cache_push_v (unsigned long vaddr, int len)
-{
- cache_invalidate_lines(vaddr, len);
-}
-
-/* Map some physical address range into the kernel address space. The
- * code is copied and adapted from map_chunk().
+ * Map some physical address range into the kernel address space.
+ * The code is copied and adapted from map_chunk().
*/
unsigned long kernel_map(unsigned long paddr, unsigned long size,
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index b5a7b46bbc49..893e7bccf226 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -174,17 +174,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long __user *) data);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* Read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -313,11 +305,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1)
- == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 37c562c4c817..ce277cb34dd0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -326,6 +326,7 @@ void __noreturn die(const char * str, struct pt_regs * regs)
#endif /* CONFIG_MIPS_MT_SMTC */
printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index bdaac34ae708..89f29233cae1 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -31,6 +31,7 @@
unsigned int sb1_pass;
unsigned int soc_pass;
unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
unsigned int periph_rev;
unsigned int zbbus_mhz;
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index f4a6169aa0a4..2d5c6d8b41f2 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -31,6 +31,7 @@
unsigned int sb1_pass;
unsigned int soc_pass;
unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
unsigned int periph_rev;
unsigned int zbbus_mhz;
EXPORT_SYMBOL(zbbus_mhz);
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 8a0db376e91e..26ec774c5027 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -87,10 +87,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
- int copied;
-
#ifdef CONFIG_64BIT
if (__is_compat_task(child)) {
+ int copied;
unsigned int tmp;
addr &= 0xffffffffL;
@@ -105,15 +104,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
else
#endif
- {
- unsigned long tmp;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- goto out_tsk;
- ret = put_user(tmp,(unsigned long *) data);
- }
+ ret = generic_ptrace_peekdata(child, addr, data);
goto out_tsk;
}
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index c3ec9f1ec0f3..bbf029a184ac 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -264,6 +264,7 @@ KERN_CRIT " || ||\n");
show_regs(regs);
dump_stack();
+ add_taint(TAINT_DIE);
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -302,7 +303,7 @@ static void handle_break(struct pt_regs *regs)
if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) {
/* check if a BUG() or WARN() trapped here. */
enum bug_trap_type tt;
- tt = report_bug(regs->iaoq[0] & ~3);
+ tt = report_bug(regs->iaoq[0] & ~3, regs);
if (tt == BUG_TRAP_TYPE_WARN) {
regs->iaoq[0] += 4;
regs->iaoq[1] += 4;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 322167737de7..cf780cb3b916 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -242,7 +242,7 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
#ifdef CONFIG_KALLSYMS
/* Handle some frequent special cases.... */
{
- char symname[KSYM_NAME_LEN+1];
+ char symname[KSYM_NAME_LEN];
char *modname;
kallsyms_lookup(info->ip, NULL, NULL, &modname,
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6beee32144c0..d860b640a140 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -4,17 +4,7 @@
mainmenu "Linux/PowerPC Kernel Configuration"
-config PPC64
- bool "64-bit kernel"
- default n
- help
- This option selects whether a 32-bit or a 64-bit kernel
- will be built.
-
-config PPC_PM_NEEDS_RTC_LIB
- bool
- select RTC_LIB
- default y if PM
+source "arch/powerpc/platforms/Kconfig.cputype"
config PPC32
bool
@@ -66,6 +56,9 @@ config GENERIC_FIND_NEXT_BIT
bool
default y
+config ARCH_NO_VIRT_TO_BUS
+ def_bool PPC64
+
config PPC
bool
default y
@@ -132,123 +125,6 @@ config PPC64_SWSUSP
depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
default y
-menu "Processor support"
-choice
- prompt "Processor Type"
- depends on PPC32
- default 6xx
-
-config CLASSIC32
- bool "52xx/6xx/7xx/74xx"
- select PPC_FPU
- select 6xx
- help
- There are four families of PowerPC chips supported. The more common
- types (601, 603, 604, 740, 750, 7400), the Motorola embedded
- versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
- embedded versions (403 and 405) and the high end 64 bit Power
- processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
-
- This option is the catch-all for 6xx types, including some of the
- embedded versions. Unless there is see an option for the specific
- chip family you are using, you want this option.
-
- You do not want this if you are building a kernel for a 64 bit
- IBM RS/6000 or an Apple G5, choose 6xx.
-
- If unsure, select this option
-
- Note that the kernel runs in 32-bit mode even on 64-bit chips.
-
-config PPC_82xx
- bool "Freescale 82xx"
- select 6xx
- select PPC_FPU
-
-config PPC_83xx
- bool "Freescale 83xx"
- select 6xx
- select FSL_SOC
- select 83xx
- select PPC_FPU
- select WANT_DEVICE_TREE
-
-config PPC_85xx
- bool "Freescale 85xx"
- select E500
- select FSL_SOC
- select 85xx
- select WANT_DEVICE_TREE
-
-config PPC_86xx
- bool "Freescale 86xx"
- select 6xx
- select FSL_SOC
- select FSL_PCIE
- select PPC_FPU
- select ALTIVEC
- help
- The Freescale E600 SoCs have 74xx cores.
-
-config PPC_8xx
- bool "Freescale 8xx"
- select FSL_SOC
- select 8xx
-
-config 40x
- bool "AMCC 40x"
- select PPC_DCR_NATIVE
-
-config 44x
- bool "AMCC 44x"
- select PPC_DCR_NATIVE
- select WANT_DEVICE_TREE
-
-config E200
- bool "Freescale e200"
-
-endchoice
-
-config POWER4_ONLY
- bool "Optimize for POWER4"
- depends on PPC64
- default n
- ---help---
- Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
- The resulting binary will not work on POWER3 or RS64 processors
- when compiled with binutils 2.15 or later.
-
-config POWER3
- bool
- depends on PPC64
- default y if !POWER4_ONLY
-
-config POWER4
- depends on PPC64
- def_bool y
-
-config 6xx
- bool
-
-# this is temp to handle compat with arch=ppc
-config 8xx
- bool
-
-# this is temp to handle compat with arch=ppc
-config 83xx
- bool
-
-# this is temp to handle compat with arch=ppc
-config 85xx
- bool
-
-config E500
- bool
-
-config PPC_FPU
- bool
- default y if PPC64
-
config PPC_DCR_NATIVE
bool
default n
@@ -267,134 +143,6 @@ config PPC_OF_PLATFORM_PCI
depends on PPC64 # not supported on 32 bits yet
default n
-config 4xx
- bool
- depends on 40x || 44x
- default y
-
-config BOOKE
- bool
- depends on E200 || E500 || 44x
- default y
-
-config FSL_BOOKE
- bool
- depends on E200 || E500
- default y
-
-config PTE_64BIT
- bool
- depends on 44x || E500
- default y if 44x
- default y if E500 && PHYS_64BIT
-
-config PHYS_64BIT
- bool 'Large physical address support' if E500
- depends on 44x || E500
- select RESOURCES_64BIT
- default y if 44x
- ---help---
- This option enables kernel support for larger than 32-bit physical
- addresses. This features is not be available on all e500 cores.
-
- If in doubt, say N here.
-
-config ALTIVEC
- bool "AltiVec Support"
- depends on CLASSIC32 || POWER4
- ---help---
- This option enables kernel support for the Altivec extensions to the
- PowerPC processor. The kernel currently supports saving and restoring
- altivec registers, and turning on the 'altivec enable' bit so user
- processes can execute altivec instructions.
-
- This option is only usefully if you have a processor that supports
- altivec (G4, otherwise known as 74xx series), but does not have
- any affect on a non-altivec cpu (it does, however add code to the
- kernel).
-
- If in doubt, say Y here.
-
-config SPE
- bool "SPE Support"
- depends on E200 || E500
- default y
- ---help---
- This option enables kernel support for the Signal Processing
- Extensions (SPE) to the PowerPC processor. The kernel currently
- supports saving and restoring SPE registers, and turning on the
- 'spe enable' bit so user processes can execute SPE instructions.
-
- This option is only useful if you have a processor that supports
- SPE (e500, otherwise known as 85xx series), but does not have any
- effect on a non-spe cpu (it does, however add code to the kernel).
-
- If in doubt, say Y here.
-
-config PPC_STD_MMU
- bool
- depends on 6xx || POWER3 || POWER4 || PPC64
- default y
-
-config PPC_STD_MMU_32
- def_bool y
- depends on PPC_STD_MMU && PPC32
-
-config PPC_MM_SLICES
- bool
- default y if HUGETLB_PAGE
- default n
-
-config VIRT_CPU_ACCOUNTING
- bool "Deterministic task and CPU time accounting"
- depends on PPC64
- default y
- help
- Select this option to enable more accurate task and CPU time
- accounting. This is done by reading a CPU counter on each
- kernel entry and exit and on transitions within the kernel
- between system, softirq and hardirq state, so there is a
- small performance impact. This also enables accounting of
- stolen time on logically-partitioned systems running on
- IBM POWER5-based machines.
-
- If in doubt, say Y here.
-
-config SMP
- depends on PPC_STD_MMU
- bool "Symmetric multi-processing support"
- ---help---
- This enables support for systems with more than one CPU. If you have
- a system with only one CPU, say N. If you have a system with more
- than one CPU, say Y. Note that the kernel does not currently
- support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
- since they have inadequate hardware support for multiprocessor
- operation.
-
- If you say N here, the kernel will run on single and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
- you say Y here, the kernel will run on single-processor machines.
- On a single-processor machine, the kernel will run faster if you say
- N here.
-
- If you don't know what to do here, say N.
-
-config NR_CPUS
- int "Maximum number of CPUs (2-128)"
- range 2 128
- depends on SMP
- default "32" if PPC64
- default "4"
-
-config NOT_COHERENT_CACHE
- bool
- depends on 4xx || 8xx || E200
- default y
-
-config CONFIG_CHECK_CACHE_COHERENCY
- bool
-endmenu
-
source "init/Kconfig"
source "arch/powerpc/platforms/Kconfig"
@@ -674,10 +422,6 @@ config SBUS
config FSL_SOC
bool
-config FSL_PCIE
- bool
- depends on PPC_86xx
-
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
@@ -685,10 +429,10 @@ config MCA
config PCI
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
- || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
- default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+ || PPC_PS3
+ default y if !40x && !CPM2 && !8xx && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
- default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
+ default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
default PCI_QSPAN if !4xx && !CPM2 && 8xx
select ARCH_SUPPORTS_MSI
help
@@ -896,8 +640,8 @@ menu "Instrumentation Support"
source "arch/powerpc/oprofile/Kconfig"
config KPROBES
- bool "Kprobes (EXPERIMENTAL)"
- depends on !BOOKE && !4xx && KALLSYMS && EXPERIMENTAL && MODULES
+ bool "Kprobes"
+ depends on !BOOKE && !4xx && KALLSYMS && MODULES
help
Kprobes allows you to trap at almost any kernel address and
execute a callback function. register_kprobe() establishes
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index fbafd965dcd2..187a39af3e1c 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE)
CPPFLAGS_vmlinux.lds := -Upowerpc
-BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage
+BOOT_TARGETS = zImage zImage.initrd uImage
PHONY += $(BOOT_TARGETS)
diff --git a/arch/powerpc/boot/44x.c b/arch/powerpc/boot/44x.c
index d51377d9024f..9f64e840bef6 100644
--- a/arch/powerpc/boot/44x.c
+++ b/arch/powerpc/boot/44x.c
@@ -38,3 +38,48 @@ void ibm44x_fixup_memsize(void)
dt_fixup_memory(0, memsize);
}
+
+#define SPRN_DBCR0 0x134
+#define DBCR0_RST_SYSTEM 0x30000000
+
+void ibm44x_dbcr_reset(void)
+{
+ unsigned long tmp;
+
+ asm volatile (
+ "mfspr %0,%1\n"
+ "oris %0,%0,%2@h\n"
+ "mtspr %1,%0"
+ : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
+ );
+
+}
+
+/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
+ * banks into the OPB address space */
+void ibm4xx_fixup_ebc_ranges(const char *ebc)
+{
+ void *devp;
+ u32 bxcr;
+ u32 ranges[EBC_NUM_BANKS*4];
+ u32 *p = ranges;
+ int i;
+
+ for (i = 0; i < EBC_NUM_BANKS; i++) {
+ mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
+ bxcr = mfdcr(DCRN_EBC0_CFGDATA);
+
+ if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
+ *p++ = i;
+ *p++ = 0;
+ *p++ = bxcr & EBC_BXCR_BAS;
+ *p++ = EBC_BXCR_BANK_SIZE(bxcr);
+ }
+ }
+
+ devp = finddevice(ebc);
+ if (! devp)
+ fatal("Couldn't locate EBC node %s\n\r", ebc);
+
+ setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
+}
diff --git a/arch/powerpc/boot/44x.h b/arch/powerpc/boot/44x.h
index 7b129ad043e1..577982c9a3cd 100644
--- a/arch/powerpc/boot/44x.h
+++ b/arch/powerpc/boot/44x.h
@@ -11,6 +11,9 @@
#define _PPC_BOOT_44X_H_
void ibm44x_fixup_memsize(void);
+void ibm4xx_fixup_ebc_ranges(const char *ebc);
+
+void ibm44x_dbcr_reset(void);
void ebony_init(void *mac0, void *mac1);
#endif /* _PPC_BOOT_44X_H_ */
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ff2701949ee1..61a6f34ca5ed 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
- gunzip_util.c elf_util.c $(zlib) devtree.c \
- 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
+ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
+ 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
- cuboot-ebony.c treeboot-ebony.c prpmc2800.c
+ cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
+ ps3-head.S ps3-hvcall.S ps3.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
$(obj)/empty.c:
@touch $@
-$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
- empty.c zImage.coff.lds zImage.lds
+ empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
quiet_cmd_bootcc = BOOTCC $@
cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -102,7 +103,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
- $(obj)/zImage.lds $(obj)/zImage.coff.lds
+ $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
wrapper :=$(srctree)/$(src)/wrapper
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@@ -132,7 +133,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries
image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
-image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf
+image-$(CONFIG_PPC_HOLLY) += zImage.holly
image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
image-$(CONFIG_PPC_ISERIES) += zImage.iseries
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
@@ -157,55 +158,43 @@ targets += $(image-y) $(initrd-y)
$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
-dts- := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-))
-dts-y := $(patsubst zImage%, zImage.dts%, $(image-y))
-dts-y := $(filter-out $(image-y), $(dts-y))
-targets += $(image-y) $(dts-y)
-
-dts_initrd- := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-))
-dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y))
-dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y))
-targets += $(image-y) $(dts_initrd-y)
-
-$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz
+# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
+# empty string, define 'dts' to be path to the dts
+# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
+ifeq ($(CONFIG_WANT_DEVICE_TREE),y)
+ifneq ($(CONFIG_DEVICE_TREE),"")
+dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
+ ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
+endif
+endif
# Don't put the ramdisk on the pattern rule; when its missing make will try
# the pattern rule with less dependencies that also matches (even with the
# hard dependency listed).
-$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz
+$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts)
$(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz)
-$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts)
+$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
$(call if_changed,wrap,$*,$(dts))
-$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
- $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
-
-$(obj)/zImage.%: vmlinux $(wrapperbits)
- $(call if_changed,wrap,$*)
-
-$(obj)/zImage.iseries: vmlinux
+# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+# prefix
+$(obj)/vmlinux.strip: vmlinux
$(STRIP) -s -R .comment $< -o $@
-$(obj)/zImage.ps3: vmlinux
+$(obj)/zImage.iseries: vmlinux
$(STRIP) -s -R .comment $< -o $@
-$(obj)/zImage.initrd.ps3: vmlinux
- @echo " WARNING zImage.initrd.ps3 not supported (yet)"
-
-$(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
- $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
+$(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
+ $(STRIP) -s -R .comment $< -o vmlinux.strip
+ $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
-$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz
- $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz)
+$(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
+ $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
-# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
-dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
- ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
-
$(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
$(call if_changed,wrap,cuboot-$*,$(dts))
@@ -215,22 +204,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits)
$(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
$(call if_changed,wrap,treeboot-$*,$(dts))
+# If there isn't a platform selected then just strip the vmlinux.
+ifeq (,$(image-y))
+image-y := vmlinux.strip
+endif
+
$(obj)/zImage: $(addprefix $(obj)/, $(image-y))
@rm -f $@; ln $< $@
$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
@rm -f $@; ln $< $@
-$(obj)/zImage.dts: $(addprefix $(obj)/, $(dts-y))
- @rm -f $@; ln $< $@
-$(obj)/zImage.dts_initrd: $(addprefix $(obj)/, $(dts_initrd-y))
- @rm -f $@; ln $< $@
-
install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
# anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
- treeImage.* zImage.dts zImage.dts_initrd
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+ otheros.bld
# clean up files cached by wrapper
clean-kernel := vmlinux.strip vmlinux.bin
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c
index 9af554eea54b..296025d8b295 100644
--- a/arch/powerpc/boot/cuboot-83xx.c
+++ b/arch/powerpc/boot/cuboot-83xx.c
@@ -12,12 +12,12 @@
#include "ops.h"
#include "stdio.h"
+#include "cuboot.h"
#define TARGET_83xx
#include "ppcboot.h"
static bd_t bd;
-extern char _end[];
extern char _dtb_start[], _dtb_end[];
static void platform_fixups(void)
@@ -52,16 +52,7 @@ static void platform_fixups(void)
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
- unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
- unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
- memcpy(&bd, (bd_t *)r3, sizeof(bd));
- loader_info.initrd_addr = r4;
- loader_info.initrd_size = r4 ? r5 - r4 : 0;
- loader_info.cmdline = (char *)r6;
- loader_info.cmdline_len = r7 - r6;
-
- simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+ CUBOOT_INIT();
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
serial_console_init();
platform_ops.fixups = platform_fixups;
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c
index e2560317f278..10f0f697c935 100644
--- a/arch/powerpc/boot/cuboot-85xx.c
+++ b/arch/powerpc/boot/cuboot-85xx.c
@@ -12,12 +12,12 @@
#include "ops.h"
#include "stdio.h"
+#include "cuboot.h"
#define TARGET_85xx
#include "ppcboot.h"
static bd_t bd;
-extern char _end[];
extern char _dtb_start[], _dtb_end[];
static void platform_fixups(void)
@@ -53,16 +53,7 @@ static void platform_fixups(void)
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
- unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
- unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
- memcpy(&bd, (bd_t *)r3, sizeof(bd));
- loader_info.initrd_addr = r4;
- loader_info.initrd_size = r4 ? r5 - r4 : 0;
- loader_info.cmdline = (char *)r6;
- loader_info.cmdline_len = r7 - r6;
-
- simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+ CUBOOT_INIT();
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
serial_console_init();
platform_ops.fixups = platform_fixups;
diff --git a/arch/powerpc/boot/cuboot-ebony.c b/arch/powerpc/boot/cuboot-ebony.c
index 4464c5f67acb..c5f37ce172ea 100644
--- a/arch/powerpc/boot/cuboot-ebony.c
+++ b/arch/powerpc/boot/cuboot-ebony.c
@@ -15,28 +15,16 @@
#include "ops.h"
#include "stdio.h"
#include "44x.h"
+#include "cuboot.h"
#define TARGET_44x
#include "ppcboot.h"
static bd_t bd;
-extern char _end[];
-
-BSS_STACK(4096);
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
- unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
- unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
- memcpy(&bd, (bd_t *)r3, sizeof(bd));
- loader_info.initrd_addr = r4;
- loader_info.initrd_size = r4 ? r5 : 0;
- loader_info.cmdline = (char *)r6;
- loader_info.cmdline_len = r7 - r6;
-
- simple_alloc_init(_end, avail_ram, 32, 64);
-
+ CUBOOT_INIT();
ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
}
diff --git a/arch/powerpc/boot/cuboot.c b/arch/powerpc/boot/cuboot.c
new file mode 100644
index 000000000000..65795468ad6f
--- /dev/null
+++ b/arch/powerpc/boot/cuboot.c
@@ -0,0 +1,35 @@
+/*
+ * Compatibility for old (not device tree aware) U-Boot versions
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+
+#include "ppcboot.h"
+
+extern char _end[];
+extern char _dtb_start[], _dtb_end[];
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ unsigned long end_of_ram)
+{
+ unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+
+ loader_info.initrd_addr = r4;
+ loader_info.initrd_size = r4 ? r5 - r4 : 0;
+ loader_info.cmdline = (char *)r6;
+ loader_info.cmdline_len = r7 - r6;
+
+ simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+}
diff --git a/arch/powerpc/boot/cuboot.h b/arch/powerpc/boot/cuboot.h
new file mode 100644
index 000000000000..cd2aa7f348f3
--- /dev/null
+++ b/arch/powerpc/boot/cuboot.h
@@ -0,0 +1,14 @@
+#ifndef _PPC_BOOT_CUBOOT_H_
+#define _PPC_BOOT_CUBOOT_H_
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ unsigned long end_of_ram);
+
+#define CUBOOT_INIT() \
+ do { \
+ memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
+ cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
+ } while (0)
+
+#endif /* _PPC_BOOT_CUBOOT_H_ */
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
index 877bc97b1e97..14b44aa96fea 100644
--- a/arch/powerpc/boot/dcr.h
+++ b/arch/powerpc/boot/dcr.h
@@ -26,6 +26,43 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C
#define SDRAM_CONFIG_BANK_SIZE(reg) \
(0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
+/* 440GP External Bus Controller (EBC) */
+#define DCRN_EBC0_CFGADDR 0x012
+#define DCRN_EBC0_CFGDATA 0x013
+#define EBC_NUM_BANKS 8
+#define EBC_B0CR 0x00
+#define EBC_B1CR 0x01
+#define EBC_B2CR 0x02
+#define EBC_B3CR 0x03
+#define EBC_B4CR 0x04
+#define EBC_B5CR 0x05
+#define EBC_B6CR 0x06
+#define EBC_B7CR 0x07
+#define EBC_BXCR(n) (n)
+#define EBC_BXCR_BAS 0xfff00000
+#define EBC_BXCR_BS 0x000e0000
+#define EBC_BXCR_BANK_SIZE(reg) \
+ (0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
+#define EBC_BXCR_BU 0x00018000
+#define EBC_BXCR_BU_OFF 0x00000000
+#define EBC_BXCR_BU_RO 0x00008000
+#define EBC_BXCR_BU_WO 0x00010000
+#define EBC_BXCR_BU_RW 0x00018000
+#define EBC_BXCR_BW 0x00006000
+#define EBC_B0AP 0x10
+#define EBC_B1AP 0x11
+#define EBC_B2AP 0x12
+#define EBC_B3AP 0x13
+#define EBC_B4AP 0x14
+#define EBC_B5AP 0x15
+#define EBC_B6AP 0x16
+#define EBC_B7AP 0x17
+#define EBC_BXAP(n) (0x10+(n))
+#define EBC_BEAR 0x20
+#define EBC_BESR 0x21
+#define EBC_CFG 0x23
+#define EBC_CID 0x24
+
/* 440GP Clock, PM, chip control */
#define DCRN_CPC0_SR 0x0b0
#define DCRN_CPC0_ER 0x0b1
diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
index 0ec02f4726b5..c5f99613fc7b 100644
--- a/arch/powerpc/boot/dts/ebony.dts
+++ b/arch/powerpc/boot/dts/ebony.dts
@@ -31,8 +31,8 @@
reg = <0>;
clock-frequency = <0>; // Filled in by zImage
timebase-frequency = <0>; // Filled in by zImage
- i-cache-line-size = <32>;
- d-cache-line-size = <32>;
+ i-cache-line-size = <20>;
+ d-cache-line-size = <20>;
i-cache-size = <8000>; /* 32 kB */
d-cache-size = <8000>; /* 32 kB */
dcr-controller;
@@ -135,11 +135,9 @@
#address-cells = <2>;
#size-cells = <1>;
clock-frequency = <0>; // Filled in by zImage
- ranges = <0 00000000 fff00000 100000
- 1 00000000 48000000 100000
- 2 00000000 ff800000 400000
- 3 00000000 48200000 100000
- 7 00000000 48300000 100000>;
+ // ranges property is supplied by zImage
+ // based on firmware's configuration of the
+ // EBC bridge
interrupts = <5 4>;
interrupt-parent = <&UIC1>;
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts
index 254499b107f4..80a4fab8ee37 100644
--- a/arch/powerpc/boot/dts/holly.dts
+++ b/arch/powerpc/boot/dts/holly.dts
@@ -46,7 +46,7 @@
tsi109@c0000000 {
device_type = "tsi-bridge";
- compatible = "tsi-bridge";
+ compatible = "tsi109-bridge", "tsi108-bridge";
#address-cells = <1>;
#size-cells = <1>;
ranges = <00000000 c0000000 00010000>;
@@ -54,52 +54,55 @@
i2c@7000 {
device_type = "i2c";
- compatible = "tsi-i2c";
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ compatible = "tsi109-i2c", "tsi108-i2c";
+ interrupt-parent = <&MPIC>;
interrupts = <e 2>;
reg = <7000 400>;
};
- mdio@6000 {
+ MDIO: mdio@6000 {
device_type = "mdio";
- compatible = "tsi-ethernet";
+ compatible = "tsi109-mdio", "tsi108-mdio";
+ reg = <6000 50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- PHY1: ethernet-phy@6000 {
- device_type = "ethernet-phy";
- compatible = "bcm54xx";
- reg = <6000 50>;
- phy-id = <1>;
+ PHY1: ethernet-phy@1 {
+ compatible = "bcm5461a";
+ reg = <1>;
+ txc-rxc-delay-disable;
};
- PHY2: ethernet-phy@6400 {
- device_type = "ethernet-phy";
- compatible = "bcm54xx";
- reg = <6000 50>;
- phy-id = <2>;
+ PHY2: ethernet-phy@2 {
+ compatible = "bcm5461a";
+ reg = <2>;
+ txc-rxc-delay-disable;
};
};
ethernet@6200 {
device_type = "network";
- compatible = "tsi-ethernet";
+ compatible = "tsi109-ethernet", "tsi108-ethernet";
#address-cells = <1>;
#size-cells = <0>;
reg = <6000 200>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ interrupt-parent = <&MPIC>;
interrupts = <10 2>;
+ mdio-handle = <&MDIO>;
phy-handle = <&PHY1>;
};
ethernet@6600 {
device_type = "network";
- compatible = "tsi-ethernet";
+ compatible = "tsi109-ethernet", "tsi108-ethernet";
#address-cells = <1>;
#size-cells = <0>;
reg = <6400 200>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ interrupt-parent = <&MPIC>;
interrupts = <11 2>;
+ mdio-handle = <&MDIO>;
phy-handle = <&PHY2>;
};
@@ -110,7 +113,7 @@
virtual-reg = <c0007808>;
clock-frequency = <3F9C6000>;
current-speed = <1c200>;
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ interrupt-parent = <&MPIC>;
interrupts = <c 2>;
};
@@ -121,7 +124,7 @@
virtual-reg = <c0007c08>;
clock-frequency = <3F9C6000>;
current-speed = <1c200>;
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ interrupt-parent = <&MPIC>;
interrupts = <d 2>;
};
@@ -136,7 +139,7 @@
pci@1000 {
device_type = "pci";
- compatible = "tsi109";
+ compatible = "tsi109-pci", "tsi108-pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@@ -150,7 +153,7 @@
ranges = <02000000 0 40000000 40000000 0 10000000
01000000 0 00000000 7e000000 0 00010000>;
clock-frequency = <7f28154>;
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ interrupt-parent = <&MPIC>;
interrupts = <17 2>;
interrupt-map-mask = <f800 0 0 7>;
/*----------------------------------------------------+
@@ -186,13 +189,12 @@
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <17 2>;
- interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+ interrupt-parent = <&MPIC>;
};
};
};
chosen {
linux,stdout-path = "/tsi109@c0000000/serial@7808";
- bootargs = "console=ttyS0,115200";
};
};
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 765c306ecf80..0e3d314a7158 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -45,7 +45,7 @@
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
- device_type = "tsi-bridge";
+ device_type = "tsi108-bridge";
ranges = <00000000 c0000000 00010000>;
reg = <c0000000 00010000>;
bus-frequency = <0>;
@@ -55,27 +55,26 @@
interrupts = <E 0>;
reg = <7000 400>;
device_type = "i2c";
- compatible = "tsi-i2c";
+ compatible = "tsi108-i2c";
};
- mdio@6000 {
+ MDIO: mdio@6000 {
device_type = "mdio";
- compatible = "tsi-ethernet";
+ compatible = "tsi108-mdio";
+ reg = <6000 50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- phy8: ethernet-phy@6000 {
+ phy8: ethernet-phy@8 {
interrupt-parent = <&mpic>;
interrupts = <2 1>;
- reg = <6000 50>;
- phy-id = <8>;
- device_type = "ethernet-phy";
+ reg = <8>;
};
- phy9: ethernet-phy@6400 {
+ phy9: ethernet-phy@9 {
interrupt-parent = <&mpic>;
interrupts = <2 1>;
- reg = <6000 50>;
- phy-id = <9>;
- device_type = "ethernet-phy";
+ reg = <9>;
};
};
@@ -83,12 +82,12 @@
ethernet@6200 {
#size-cells = <0>;
device_type = "network";
- model = "TSI-ETH";
- compatible = "tsi-ethernet";
+ compatible = "tsi108-ethernet";
reg = <6000 200>;
address = [ 00 06 D2 00 00 01 ];
interrupts = <10 2>;
interrupt-parent = <&mpic>;
+ mdio-handle = <&MDIO>;
phy-handle = <&phy8>;
};
@@ -96,12 +95,12 @@
#address-cells = <1>;
#size-cells = <0>;
device_type = "network";
- model = "TSI-ETH";
- compatible = "tsi-ethernet";
+ compatible = "tsi108-ethernet";
reg = <6400 200>;
address = [ 00 06 D2 00 00 02 ];
interrupts = <11 2>;
interrupt-parent = <&mpic>;
+ mdio-handle = <&MDIO>;
phy-handle = <&phy9>;
};
@@ -135,7 +134,7 @@
big-endian;
};
pci@1000 {
- compatible = "tsi10x";
+ compatible = "tsi108-pci";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
index 423eedcf634f..1934b800278e 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -14,12 +14,10 @@
compatible = "MPC8260ADS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8272@0 {
device_type = "cpu";
@@ -32,12 +30,10 @@
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
- linux,phandle = <201>;
};
};
- interrupt-controller@f8200000 {
- linux,phandle = <f8200000>;
+ pci_pic: interrupt-controller@f8200000 {
#address-cells = <0>;
#interrupt-cells = <2>;
interrupt-controller;
@@ -47,15 +43,13 @@
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 4000000 f4500000 00000020>;
};
chosen {
name = "chosen";
linux,platform = <0>;
- interrupt-controller = <10c00>;
- linux,phandle = <400>;
+ interrupt-controller = <&Cpm_pic>;
};
soc8272@f0000000 {
@@ -70,20 +64,17 @@
device_type = "mdio";
compatible = "fs_enet";
reg = <0 0>;
- linux,phandle = <24520>;
#address-cells = <1>;
#size-cells = <0>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <10c00>;
+ phy0:ethernet-phy@0 {
+ interrupt-parent = <&Cpm_pic>;
interrupts = <17 4>;
reg = <0>;
bitbang = [ 12 12 13 02 02 01 ];
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <10c00>;
+ phy1:ethernet-phy@1 {
+ interrupt-parent = <&Cpm_pic>;
interrupts = <17 4>;
bitbang = [ 12 12 13 02 02 01 ];
reg = <3>;
@@ -101,8 +92,8 @@
reg = <11300 20 8400 100 11380 30>;
mac-address = [ 00 11 2F 99 43 54 ];
interrupts = <20 2>;
- interrupt-parent = <10c00>;
- phy-handle = <2452000>;
+ interrupt-parent = <&Cpm_pic>;
+ phy-handle = <&Phy0>;
rx-clock = <13>;
tx-clock = <12>;
};
@@ -115,14 +106,13 @@
reg = <11320 20 8500 100 113b0 30>;
mac-address = [ 00 11 2F 99 44 54 ];
interrupts = <21 2>;
- interrupt-parent = <10c00>;
- phy-handle = <2452001>;
+ interrupt-parent = <&Cpm_pic>;
+ phy-handle = <&Phy1>;
rx-clock = <17>;
tx-clock = <18>;
};
cpm@f0000000 {
- linux,phandle = <f0000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@@ -142,7 +132,7 @@
reg = <11a00 20 8000 100>;
current-speed = <1c200>;
interrupts = <28 2>;
- interrupt-parent = <10c00>;
+ interrupt-parent = <&Cpm_pic>;
clock-setup = <0 00ffffff>;
rx-clock = <1>;
tx-clock = <1>;
@@ -156,15 +146,14 @@
reg = <11a60 20 8300 100>;
current-speed = <1c200>;
interrupts = <2b 2>;
- interrupt-parent = <10c00>;
+ interrupt-parent = <&Cpm_pic>;
clock-setup = <1b ffffff00>;
rx-clock = <4>;
tx-clock = <4>;
};
};
- interrupt-controller@10c00 {
- linux,phandle = <10c00>;
+ cpm_pic:interrupt-controller@10c00 {
#address-cells = <0>;
#interrupt-cells = <2>;
interrupt-controller;
@@ -174,7 +163,6 @@
compatible = "CPM2";
};
pci@0500 {
- linux,phandle = <0500>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@@ -202,7 +190,7 @@
c000 0 0 2 f8200000 43 8
c000 0 0 3 f8200000 40 8
c000 0 0 4 f8200000 41 8>;
- interrupt-parent = <10c00>;
+ interrupt-parent = <&Cpm_pic>;
interrupts = <14 8>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 40000000
@@ -216,7 +204,7 @@
compatible = "talitos";
reg = <30000 10000>;
interrupts = <b 2>;
- interrupt-parent = <10c00>;
+ interrupt-parent = <&Cpm_pic>;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <0000007e>;
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 112dd5198fe2..4fc0c4d34aa8 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -272,7 +272,13 @@
reg = <2200 200>;
interrupts = <22>;
interrupt-parent = < &qeic >;
- mac-address = [ 00 04 9f 00 23 23 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <19>;
tx-clock = <1a>;
phy-handle = < &phy3 >;
@@ -287,7 +293,13 @@
reg = <3000 200>;
interrupts = <23>;
interrupt-parent = < &qeic >;
- mac-address = [ 00 11 22 33 44 55 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <17>;
tx-clock = <18>;
phy-handle = < &phy4 >;
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index be4c35784e49..447c03ffabbc 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -231,7 +231,13 @@
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = <&qeic>;
- mac-address = [ 00 04 9f ef 03 02 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <20>;
tx-clock = <13>;
phy-handle = <&phy00>;
@@ -246,7 +252,13 @@
reg = <2200 200>;
interrupts = <22>;
interrupt-parent = <&qeic>;
- mac-address = [ 00 04 9f ef 03 01 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <19>;
tx-clock = <1a>;
phy-handle = <&phy04>;
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index db0d00303275..ae9bca575453 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -131,6 +131,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
@@ -145,6 +150,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index df773fafe9d1..310e877826b4 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -136,6 +136,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
@@ -150,6 +155,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 38c8594df3a4..1e914f31dd92 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -301,7 +301,13 @@
reg = <2000 200>;
interrupts = <20>;
interrupt-parent = < &qeic >;
- mac-address = [ 00 04 9f 00 23 23 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <19>;
phy-handle = < &phy0 >;
@@ -317,7 +323,13 @@
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = < &qeic >;
- mac-address = [ 00 11 22 33 44 55 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <14>;
phy-handle = < &phy1 >;
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index d91e81c009f5..364a969f5c2f 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -52,7 +52,7 @@
compatible = "fsl,8540-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -81,19 +81,19 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <35 1>;
+ interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <35 1>;
+ interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
- interrupts = <37 1>;
+ interrupts = <7 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@@ -106,9 +106,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
- address = [ 00 E0 0C 00 73 00 ];
- local-mac-address = [ 00 E0 0C 00 73 00 ];
- interrupts = <d 2 e 2 12 2>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@@ -120,9 +125,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
- address = [ 00 E0 0C 00 73 01 ];
- local-mac-address = [ 00 E0 0C 00 73 01 ];
- interrupts = <13 2 14 2 18 2>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@@ -134,9 +144,14 @@
model = "FEC";
compatible = "gianfar";
reg = <26000 1000>;
- address = [ 00 E0 0C 00 73 02 ];
- local-mac-address = [ 00 E0 0C 00 73 02 ];
- interrupts = <19 2>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <29 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
};
@@ -146,7 +161,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -155,7 +170,7 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
pci@8000 {
@@ -163,78 +178,78 @@
interrupt-map = <
/* IDSEL 0x02 */
- 1000 0 0 1 &mpic 31 1
- 1000 0 0 2 &mpic 32 1
- 1000 0 0 3 &mpic 33 1
- 1000 0 0 4 &mpic 34 1
+ 1000 0 0 1 &mpic 1 1
+ 1000 0 0 2 &mpic 2 1
+ 1000 0 0 3 &mpic 3 1
+ 1000 0 0 4 &mpic 4 1
/* IDSEL 0x03 */
- 1800 0 0 1 &mpic 34 1
- 1800 0 0 2 &mpic 31 1
- 1800 0 0 3 &mpic 32 1
- 1800 0 0 4 &mpic 33 1
+ 1800 0 0 1 &mpic 4 1
+ 1800 0 0 2 &mpic 1 1
+ 1800 0 0 3 &mpic 2 1
+ 1800 0 0 4 &mpic 3 1
/* IDSEL 0x04 */
- 2000 0 0 1 &mpic 33 1
- 2000 0 0 2 &mpic 34 1
- 2000 0 0 3 &mpic 31 1
- 2000 0 0 4 &mpic 32 1
+ 2000 0 0 1 &mpic 3 1
+ 2000 0 0 2 &mpic 4 1
+ 2000 0 0 3 &mpic 1 1
+ 2000 0 0 4 &mpic 2 1
/* IDSEL 0x05 */
- 2800 0 0 1 &mpic 32 1
- 2800 0 0 2 &mpic 33 1
- 2800 0 0 3 &mpic 34 1
- 2800 0 0 4 &mpic 31 1
+ 2800 0 0 1 &mpic 2 1
+ 2800 0 0 2 &mpic 3 1
+ 2800 0 0 3 &mpic 4 1
+ 2800 0 0 4 &mpic 1 1
/* IDSEL 0x0c */
- 6000 0 0 1 &mpic 31 1
- 6000 0 0 2 &mpic 32 1
- 6000 0 0 3 &mpic 33 1
- 6000 0 0 4 &mpic 34 1
+ 6000 0 0 1 &mpic 1 1
+ 6000 0 0 2 &mpic 2 1
+ 6000 0 0 3 &mpic 3 1
+ 6000 0 0 4 &mpic 4 1
/* IDSEL 0x0d */
- 6800 0 0 1 &mpic 34 1
- 6800 0 0 2 &mpic 31 1
- 6800 0 0 3 &mpic 32 1
- 6800 0 0 4 &mpic 33 1
+ 6800 0 0 1 &mpic 4 1
+ 6800 0 0 2 &mpic 1 1
+ 6800 0 0 3 &mpic 2 1
+ 6800 0 0 4 &mpic 3 1
/* IDSEL 0x0e */
- 7000 0 0 1 &mpic 33 1
- 7000 0 0 2 &mpic 34 1
- 7000 0 0 3 &mpic 31 1
- 7000 0 0 4 &mpic 32 1
+ 7000 0 0 1 &mpic 3 1
+ 7000 0 0 2 &mpic 4 1
+ 7000 0 0 3 &mpic 1 1
+ 7000 0 0 4 &mpic 2 1
/* IDSEL 0x0f */
- 7800 0 0 1 &mpic 32 1
- 7800 0 0 2 &mpic 33 1
- 7800 0 0 3 &mpic 34 1
- 7800 0 0 4 &mpic 31 1
+ 7800 0 0 1 &mpic 2 1
+ 7800 0 0 2 &mpic 3 1
+ 7800 0 0 3 &mpic 4 1
+ 7800 0 0 4 &mpic 1 1
/* IDSEL 0x12 */
- 9000 0 0 1 &mpic 31 1
- 9000 0 0 2 &mpic 32 1
- 9000 0 0 3 &mpic 33 1
- 9000 0 0 4 &mpic 34 1
+ 9000 0 0 1 &mpic 1 1
+ 9000 0 0 2 &mpic 2 1
+ 9000 0 0 3 &mpic 3 1
+ 9000 0 0 4 &mpic 4 1
/* IDSEL 0x13 */
- 9800 0 0 1 &mpic 34 1
- 9800 0 0 2 &mpic 31 1
- 9800 0 0 3 &mpic 32 1
- 9800 0 0 4 &mpic 33 1
+ 9800 0 0 1 &mpic 4 1
+ 9800 0 0 2 &mpic 1 1
+ 9800 0 0 3 &mpic 2 1
+ 9800 0 0 4 &mpic 3 1
/* IDSEL 0x14 */
- a000 0 0 1 &mpic 33 1
- a000 0 0 2 &mpic 34 1
- a000 0 0 3 &mpic 31 1
- a000 0 0 4 &mpic 32 1
+ a000 0 0 1 &mpic 3 1
+ a000 0 0 2 &mpic 4 1
+ a000 0 0 3 &mpic 1 1
+ a000 0 0 4 &mpic 2 1
/* IDSEL 0x15 */
- a800 0 0 1 &mpic 32 1
- a800 0 0 2 &mpic 33 1
- a800 0 0 3 &mpic 34 1
- a800 0 0 4 &mpic 31 1>;
+ a800 0 0 1 &mpic 2 1
+ a800 0 0 2 &mpic 3 1
+ a800 0 0 3 &mpic 4 1
+ a800 0 0 4 &mpic 1 1>;
interrupt-parent = <&mpic>;
- interrupts = <08 2>;
+ interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 4f2c3af2e052..070206fffe88 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -52,7 +52,7 @@
compatible = "fsl,8541-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -81,13 +81,13 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
@@ -100,8 +100,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 00 ];
- interrupts = <d 2 e 2 12 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@@ -113,8 +113,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 01 ];
- interrupts = <13 2 14 2 18 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@@ -124,7 +124,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -133,7 +133,7 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -142,49 +142,49 @@
interrupt-map = <
/* IDSEL 0x10 */
- 08000 0 0 1 &mpic 30 1
- 08000 0 0 2 &mpic 31 1
- 08000 0 0 3 &mpic 32 1
- 08000 0 0 4 &mpic 33 1
+ 08000 0 0 1 &mpic 0 1
+ 08000 0 0 2 &mpic 1 1
+ 08000 0 0 3 &mpic 2 1
+ 08000 0 0 4 &mpic 3 1
/* IDSEL 0x11 */
- 08800 0 0 1 &mpic 30 1
- 08800 0 0 2 &mpic 31 1
- 08800 0 0 3 &mpic 32 1
- 08800 0 0 4 &mpic 33 1
+ 08800 0 0 1 &mpic 0 1
+ 08800 0 0 2 &mpic 1 1
+ 08800 0 0 3 &mpic 2 1
+ 08800 0 0 4 &mpic 3 1
/* IDSEL 0x12 (Slot 1) */
- 09000 0 0 1 &mpic 30 1
- 09000 0 0 2 &mpic 31 1
- 09000 0 0 3 &mpic 32 1
- 09000 0 0 4 &mpic 33 1
+ 09000 0 0 1 &mpic 0 1
+ 09000 0 0 2 &mpic 1 1
+ 09000 0 0 3 &mpic 2 1
+ 09000 0 0 4 &mpic 3 1
/* IDSEL 0x13 (Slot 2) */
- 09800 0 0 1 &mpic 31 1
- 09800 0 0 2 &mpic 32 1
- 09800 0 0 3 &mpic 33 1
- 09800 0 0 4 &mpic 30 1
+ 09800 0 0 1 &mpic 1 1
+ 09800 0 0 2 &mpic 2 1
+ 09800 0 0 3 &mpic 3 1
+ 09800 0 0 4 &mpic 0 1
/* IDSEL 0x14 (Slot 3) */
- 0a000 0 0 1 &mpic 32 1
- 0a000 0 0 2 &mpic 33 1
- 0a000 0 0 3 &mpic 30 1
- 0a000 0 0 4 &mpic 31 1
+ 0a000 0 0 1 &mpic 2 1
+ 0a000 0 0 2 &mpic 3 1
+ 0a000 0 0 3 &mpic 0 1
+ 0a000 0 0 4 &mpic 1 1
/* IDSEL 0x15 (Slot 4) */
- 0a800 0 0 1 &mpic 33 1
- 0a800 0 0 2 &mpic 30 1
- 0a800 0 0 3 &mpic 31 1
- 0a800 0 0 4 &mpic 32 1
+ 0a800 0 0 1 &mpic 3 1
+ 0a800 0 0 2 &mpic 0 1
+ 0a800 0 0 3 &mpic 1 1
+ 0a800 0 0 4 &mpic 2 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
- 19000 0 0 1 &mpic 30 1
- 19000 0 0 2 &mpic 31 1
- 19000 0 0 3 &mpic 32 1
- 19000 0 0 4 &mpic 33 1>;
+ 19000 0 0 1 &mpic 0 1
+ 19000 0 0 2 &mpic 1 1
+ 19000 0 0 3 &mpic 2 1
+ 19000 0 0 4 &mpic 3 1>;
interrupt-parent = <&mpic>;
- interrupts = <08 2>;
+ interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
@@ -216,12 +216,12 @@
interrupt-map = <
/* IDSEL 0x15 */
- a800 0 0 1 &mpic 3b 1
- a800 0 0 2 &mpic 3b 1
- a800 0 0 3 &mpic 3b 1
- a800 0 0 4 &mpic 3b 1>;
+ a800 0 0 1 &mpic b 1
+ a800 0 0 2 &mpic b 1
+ a800 0 0 3 &mpic b 1
+ a800 0 0 4 &mpic b 1>;
interrupt-parent = <&mpic>;
- interrupts = <09 2>;
+ interrupts = <19 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 3033599e74e8..828592592460 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -52,7 +52,7 @@
compatible = "fsl,8544-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -81,13 +81,13 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <3a 1>;
+ interrupts = <a 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <3a 1>;
+ interrupts = <a 1>;
reg = <1>;
device_type = "ethernet-phy";
};
@@ -101,7 +101,7 @@
compatible = "gianfar";
reg = <24000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <d 2 e 2 12 2>;
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@@ -114,7 +114,7 @@
compatible = "gianfar";
reg = <26000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <f 2 10 2 11 2>;
+ interrupts = <1f 2 20 2 21 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@@ -124,7 +124,7 @@
compatible = "ns16550";
reg = <4500 100>;
clock-frequency = <0>;
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -133,7 +133,7 @@
compatible = "ns16550";
reg = <4600 100>;
clock-frequency = <0>;
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index ad96381033c0..9d0b84b66cd4 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -52,7 +52,7 @@
compatible = "fsl,8548-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <80000>; // L2, 512K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -81,25 +81,25 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@@ -112,8 +112,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <24000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 00 ];
- interrupts = <d 2 e 2 12 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@@ -125,8 +125,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <25000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 01 ];
- interrupts = <13 2 14 2 18 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@@ -139,8 +139,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <26000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 02 ];
- interrupts = <f 2 10 2 11 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1f 2 20 2 21 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy2>;
};
@@ -152,8 +152,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <27000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 03 ];
- interrupts = <15 2 16 2 17 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <25 2 26 2 27 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
};
@@ -164,7 +164,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -173,58 +173,64 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
+ global-utilities@e0000 { //global utilities reg
+ compatible = "fsl,mpc8548-guts";
+ reg = <e0000 1000>;
+ fsl,has-rstcr;
+ };
+
pci1: pci@8000 {
interrupt-map-mask = <1f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 */
- 08000 0 0 1 &mpic 30 1
- 08000 0 0 2 &mpic 31 1
- 08000 0 0 3 &mpic 32 1
- 08000 0 0 4 &mpic 33 1
+ 08000 0 0 1 &mpic 0 1
+ 08000 0 0 2 &mpic 1 1
+ 08000 0 0 3 &mpic 2 1
+ 08000 0 0 4 &mpic 3 1
/* IDSEL 0x11 */
- 08800 0 0 1 &mpic 30 1
- 08800 0 0 2 &mpic 31 1
- 08800 0 0 3 &mpic 32 1
- 08800 0 0 4 &mpic 33 1
+ 08800 0 0 1 &mpic 0 1
+ 08800 0 0 2 &mpic 1 1
+ 08800 0 0 3 &mpic 2 1
+ 08800 0 0 4 &mpic 3 1
/* IDSEL 0x12 (Slot 1) */
- 09000 0 0 1 &mpic 30 1
- 09000 0 0 2 &mpic 31 1
- 09000 0 0 3 &mpic 32 1
- 09000 0 0 4 &mpic 33 1
+ 09000 0 0 1 &mpic 0 1
+ 09000 0 0 2 &mpic 1 1
+ 09000 0 0 3 &mpic 2 1
+ 09000 0 0 4 &mpic 3 1
/* IDSEL 0x13 (Slot 2) */
- 09800 0 0 1 &mpic 31 1
- 09800 0 0 2 &mpic 32 1
- 09800 0 0 3 &mpic 33 1
- 09800 0 0 4 &mpic 30 1
+ 09800 0 0 1 &mpic 1 1
+ 09800 0 0 2 &mpic 2 1
+ 09800 0 0 3 &mpic 3 1
+ 09800 0 0 4 &mpic 0 1
/* IDSEL 0x14 (Slot 3) */
- 0a000 0 0 1 &mpic 32 1
- 0a000 0 0 2 &mpic 33 1
- 0a000 0 0 3 &mpic 30 1
- 0a000 0 0 4 &mpic 31 1
+ 0a000 0 0 1 &mpic 2 1
+ 0a000 0 0 2 &mpic 3 1
+ 0a000 0 0 3 &mpic 0 1
+ 0a000 0 0 4 &mpic 1 1
/* IDSEL 0x15 (Slot 4) */
- 0a800 0 0 1 &mpic 33 1
- 0a800 0 0 2 &mpic 30 1
- 0a800 0 0 3 &mpic 31 1
- 0a800 0 0 4 &mpic 32 1
+ 0a800 0 0 1 &mpic 3 1
+ 0a800 0 0 2 &mpic 0 1
+ 0a800 0 0 3 &mpic 1 1
+ 0a800 0 0 4 &mpic 2 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
- 19000 0 0 1 &mpic 30 1
- 19000 0 0 2 &mpic 31 1
- 19000 0 0 3 &mpic 32 1
- 19000 0 0 4 &mpic 33 1>;
+ 19000 0 0 1 &mpic 0 1
+ 19000 0 0 2 &mpic 1 1
+ 19000 0 0 3 &mpic 2 1
+ 19000 0 0 4 &mpic 3 1>;
interrupt-parent = <&mpic>;
- interrupts = <08 2>;
+ interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
@@ -256,12 +262,12 @@
interrupt-map = <
/* IDSEL 0x15 */
- a800 0 0 1 &mpic 3b 1
- a800 0 0 2 &mpic 3b 1
- a800 0 0 3 &mpic 3b 1
- a800 0 0 4 &mpic 3b 1>;
+ a800 0 0 1 &mpic b 1
+ a800 0 0 2 &mpic b 1
+ a800 0 0 3 &mpic b 1
+ a800 0 0 4 &mpic b 1>;
interrupt-parent = <&mpic>;
- interrupts = <09 2>;
+ interrupts = <19 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 951ed92f1154..17e45d9a382a 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -52,7 +52,7 @@
compatible = "fsl,8555-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -81,13 +81,13 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <35 0>;
+ interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
@@ -100,8 +100,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 00 ];
- interrupts = <0d 2 0e 2 12 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@@ -113,8 +113,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
- local-mac-address = [ 00 E0 0C 00 73 01 ];
- interrupts = <13 2 14 2 18 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@@ -124,7 +124,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -133,7 +133,7 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -142,49 +142,49 @@
interrupt-map = <
/* IDSEL 0x10 */
- 08000 0 0 1 &mpic 30 1
- 08000 0 0 2 &mpic 31 1
- 08000 0 0 3 &mpic 32 1
- 08000 0 0 4 &mpic 33 1
+ 08000 0 0 1 &mpic 0 1
+ 08000 0 0 2 &mpic 1 1
+ 08000 0 0 3 &mpic 2 1
+ 08000 0 0 4 &mpic 3 1
/* IDSEL 0x11 */
- 08800 0 0 1 &mpic 30 1
- 08800 0 0 2 &mpic 31 1
- 08800 0 0 3 &mpic 32 1
- 08800 0 0 4 &mpic 33 1
+ 08800 0 0 1 &mpic 0 1
+ 08800 0 0 2 &mpic 1 1
+ 08800 0 0 3 &mpic 2 1
+ 08800 0 0 4 &mpic 3 1
/* IDSEL 0x12 (Slot 1) */
- 09000 0 0 1 &mpic 30 1
- 09000 0 0 2 &mpic 31 1
- 09000 0 0 3 &mpic 32 1
- 09000 0 0 4 &mpic 33 1
+ 09000 0 0 1 &mpic 0 1
+ 09000 0 0 2 &mpic 1 1
+ 09000 0 0 3 &mpic 2 1
+ 09000 0 0 4 &mpic 3 1
/* IDSEL 0x13 (Slot 2) */
- 09800 0 0 1 &mpic 31 1
- 09800 0 0 2 &mpic 32 1
- 09800 0 0 3 &mpic 33 1
- 09800 0 0 4 &mpic 30 1
+ 09800 0 0 1 &mpic 1 1
+ 09800 0 0 2 &mpic 2 1
+ 09800 0 0 3 &mpic 3 1
+ 09800 0 0 4 &mpic 0 1
/* IDSEL 0x14 (Slot 3) */
- 0a000 0 0 1 &mpic 32 1
- 0a000 0 0 2 &mpic 33 1
- 0a000 0 0 3 &mpic 30 1
- 0a000 0 0 4 &mpic 31 1
+ 0a000 0 0 1 &mpic 2 1
+ 0a000 0 0 2 &mpic 3 1
+ 0a000 0 0 3 &mpic 0 1
+ 0a000 0 0 4 &mpic 1 1
/* IDSEL 0x15 (Slot 4) */
- 0a800 0 0 1 &mpic 33 1
- 0a800 0 0 2 &mpic 30 1
- 0a800 0 0 3 &mpic 31 1
- 0a800 0 0 4 &mpic 32 1
+ 0a800 0 0 1 &mpic 3 1
+ 0a800 0 0 2 &mpic 0 1
+ 0a800 0 0 3 &mpic 1 1
+ 0a800 0 0 4 &mpic 2 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
- 19000 0 0 1 &mpic 30 1
- 19000 0 0 2 &mpic 31 1
- 19000 0 0 3 &mpic 32 1
- 19000 0 0 4 &mpic 33 1>;
+ 19000 0 0 1 &mpic 0 1
+ 19000 0 0 2 &mpic 1 1
+ 19000 0 0 3 &mpic 2 1
+ 19000 0 0 4 &mpic 3 1>;
interrupt-parent = <&mpic>;
- interrupts = <08 2>;
+ interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
@@ -216,12 +216,12 @@
interrupt-map = <
/* IDSEL 0x15 */
- a800 0 0 1 &mpic 3b 1
- a800 0 0 2 &mpic 3b 1
- a800 0 0 3 &mpic 3b 1
- a800 0 0 4 &mpic 3b 1>;
+ a800 0 0 1 &mpic b 1
+ a800 0 0 2 &mpic b 1
+ a800 0 0 3 &mpic b 1
+ a800 0 0 4 &mpic b 1>;
interrupt-parent = <&mpic>;
- interrupts = <09 2>;
+ interrupts = <19 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 80682152b0cf..21ccaaa27993 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -52,7 +52,7 @@
compatible = "fsl,8540-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -61,7 +61,7 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
mdio@24520 {
@@ -72,25 +72,25 @@
#size-cells = <0>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <35 1>;
+ interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <35 1>;
+ interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
- interrupts = <37 1>;
+ interrupts = <7 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
- interrupts = <37 1>;
+ interrupts = <7 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@@ -101,8 +101,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
- address = [ 00 00 0C 00 00 FD ];
- interrupts = <d 2 e 2 12 2>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@@ -114,8 +120,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
- address = [ 00 00 0C 00 01 FD ];
- interrupts = <13 2 14 2 18 2>;
+ /*
+ * address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@@ -132,79 +144,79 @@
interrupt-map = <
/* IDSEL 0x2 */
- 1000 0 0 1 &mpic 31 1
- 1000 0 0 2 &mpic 32 1
- 1000 0 0 3 &mpic 33 1
- 1000 0 0 4 &mpic 34 1
+ 1000 0 0 1 &mpic 1 1
+ 1000 0 0 2 &mpic 2 1
+ 1000 0 0 3 &mpic 3 1
+ 1000 0 0 4 &mpic 4 1
/* IDSEL 0x3 */
- 1800 0 0 1 &mpic 34 1
- 1800 0 0 2 &mpic 31 1
- 1800 0 0 3 &mpic 32 1
- 1800 0 0 4 &mpic 33 1
+ 1800 0 0 1 &mpic 4 1
+ 1800 0 0 2 &mpic 1 1
+ 1800 0 0 3 &mpic 2 1
+ 1800 0 0 4 &mpic 3 1
/* IDSEL 0x4 */
- 2000 0 0 1 &mpic 33 1
- 2000 0 0 2 &mpic 34 1
- 2000 0 0 3 &mpic 31 1
- 2000 0 0 4 &mpic 32 1
+ 2000 0 0 1 &mpic 3 1
+ 2000 0 0 2 &mpic 4 1
+ 2000 0 0 3 &mpic 1 1
+ 2000 0 0 4 &mpic 2 1
/* IDSEL 0x5 */
- 2800 0 0 1 &mpic 32 1
- 2800 0 0 2 &mpic 33 1
- 2800 0 0 3 &mpic 34 1
- 2800 0 0 4 &mpic 31 1
+ 2800 0 0 1 &mpic 2 1
+ 2800 0 0 2 &mpic 3 1
+ 2800 0 0 3 &mpic 4 1
+ 2800 0 0 4 &mpic 1 1
/* IDSEL 12 */
- 6000 0 0 1 &mpic 31 1
- 6000 0 0 2 &mpic 32 1
- 6000 0 0 3 &mpic 33 1
- 6000 0 0 4 &mpic 34 1
+ 6000 0 0 1 &mpic 1 1
+ 6000 0 0 2 &mpic 2 1
+ 6000 0 0 3 &mpic 3 1
+ 6000 0 0 4 &mpic 4 1
/* IDSEL 13 */
- 6800 0 0 1 &mpic 34 1
- 6800 0 0 2 &mpic 31 1
- 6800 0 0 3 &mpic 32 1
- 6800 0 0 4 &mpic 33 1
+ 6800 0 0 1 &mpic 4 1
+ 6800 0 0 2 &mpic 1 1
+ 6800 0 0 3 &mpic 2 1
+ 6800 0 0 4 &mpic 3 1
/* IDSEL 14*/
- 7000 0 0 1 &mpic 33 1
- 7000 0 0 2 &mpic 34 1
- 7000 0 0 3 &mpic 31 1
- 7000 0 0 4 &mpic 32 1
+ 7000 0 0 1 &mpic 3 1
+ 7000 0 0 2 &mpic 4 1
+ 7000 0 0 3 &mpic 1 1
+ 7000 0 0 4 &mpic 2 1
/* IDSEL 15 */
- 7800 0 0 1 &mpic 32 1
- 7800 0 0 2 &mpic 33 1
- 7800 0 0 3 &mpic 34 1
- 7800 0 0 4 &mpic 31 1
+ 7800 0 0 1 &mpic 2 1
+ 7800 0 0 2 &mpic 3 1
+ 7800 0 0 3 &mpic 4 1
+ 7800 0 0 4 &mpic 1 1
/* IDSEL 18 */
- 9000 0 0 1 &mpic 31 1
- 9000 0 0 2 &mpic 32 1
- 9000 0 0 3 &mpic 33 1
- 9000 0 0 4 &mpic 34 1
+ 9000 0 0 1 &mpic 1 1
+ 9000 0 0 2 &mpic 2 1
+ 9000 0 0 3 &mpic 3 1
+ 9000 0 0 4 &mpic 4 1
/* IDSEL 19 */
- 9800 0 0 1 &mpic 34 1
- 9800 0 0 2 &mpic 31 1
- 9800 0 0 3 &mpic 32 1
- 9800 0 0 4 &mpic 33 1
+ 9800 0 0 1 &mpic 4 1
+ 9800 0 0 2 &mpic 1 1
+ 9800 0 0 3 &mpic 2 1
+ 9800 0 0 4 &mpic 3 1
/* IDSEL 20 */
- a000 0 0 1 &mpic 33 1
- a000 0 0 2 &mpic 34 1
- a000 0 0 3 &mpic 31 1
- a000 0 0 4 &mpic 32 1
+ a000 0 0 1 &mpic 3 1
+ a000 0 0 2 &mpic 4 1
+ a000 0 0 3 &mpic 1 1
+ a000 0 0 4 &mpic 2 1
/* IDSEL 21 */
- a800 0 0 1 &mpic 32 1
- a800 0 0 2 &mpic 33 1
- a800 0 0 3 &mpic 34 1
- a800 0 0 4 &mpic 31 1>;
+ a800 0 0 1 &mpic 2 1
+ a800 0 0 2 &mpic 3 1
+ a800 0 0 3 &mpic 4 1
+ a800 0 0 4 &mpic 1 1>;
interrupt-parent = <&mpic>;
- interrupts = <8 0>;
+ interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 01000000>;
@@ -234,7 +246,7 @@
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
- interrupts = <1e 0>;
+ interrupts = <2e 2>;
interrupt-parent = <&mpic>;
reg = <90c00 80>;
built-in;
@@ -275,7 +287,13 @@
model = "FCC";
device-id = <2>;
reg = <91320 20 88500 100 913a0 30>;
- mac-address = [ 00 00 0C 00 02 FD ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
clock-setup = <ff00ffff 250000>;
rx-clock = <15>;
tx-clock = <16>;
@@ -290,7 +308,13 @@
model = "FCC";
device-id = <3>;
reg = <91340 20 88600 100 913d0 30>;
- mac-address = [ 00 00 0C 00 03 FD ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
clock-setup = <ffff00ff 3700>;
rx-clock = <17>;
tx-clock = <18>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index a123ec9456bc..6bb18f2807a8 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -61,7 +61,7 @@
compatible = "fsl,8568-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
- interrupts = <2 2>;
+ interrupts = <12 2>;
};
l2-cache-controller@20000 {
@@ -70,14 +70,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <80000>; // L2, 512K
interrupt-parent = <&mpic>;
- interrupts = <0 2>;
+ interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -86,7 +86,7 @@
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3100 100>;
- interrupts = <1b 2>;
+ interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@@ -99,25 +99,25 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <31 1>;
+ interrupts = <1 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <32 1>;
+ interrupts = <2 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
- interrupts = <31 1>;
+ interrupts = <1 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
- interrupts = <32 1>;
+ interrupts = <2 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@@ -130,8 +130,14 @@
model = "eTSEC";
compatible = "gianfar";
reg = <24000 1000>;
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
mac-address = [ 00 00 00 00 00 00 ];
- interrupts = <d 2 e 2 12 2>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy2>;
};
@@ -143,8 +149,14 @@
model = "eTSEC";
compatible = "gianfar";
reg = <25000 1000>;
- mac-address = [ 00 00 00 00 00 00];
- interrupts = <13 2 14 2 18 2>;
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
};
@@ -154,7 +166,7 @@
compatible = "ns16550";
reg = <4500 100>;
clock-frequency = <0>;
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -163,7 +175,7 @@
compatible = "ns16550";
reg = <4600 100>;
clock-frequency = <0>;
- interrupts = <1a 2>;
+ interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@@ -172,7 +184,7 @@
model = "SEC2";
compatible = "talitos";
reg = <30000 f000>;
- interrupts = <1d 2>;
+ interrupts = <2d 2>;
interrupt-parent = <&mpic>;
num-channels = <4>;
channel-fifo-len = <18>;
@@ -300,7 +312,13 @@
reg = <2000 200>;
interrupts = <20>;
interrupt-parent = <&qeic>;
- mac-address = [ 00 04 9f 00 23 23 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <19>;
phy-handle = <&qe_phy0>;
@@ -316,7 +334,13 @@
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = <&qeic>;
- mac-address = [ 00 11 22 33 44 55 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <14>;
phy-handle = <&qe_phy1>;
@@ -335,25 +359,25 @@
* gianfar's MDIO bus */
qe_phy0: ethernet-phy@00 {
interrupt-parent = <&mpic>;
- interrupts = <31 1>;
+ interrupts = <1 1>;
reg = <0>;
device_type = "ethernet-phy";
};
qe_phy1: ethernet-phy@01 {
interrupt-parent = <&mpic>;
- interrupts = <32 1>;
+ interrupts = <2 1>;
reg = <1>;
device_type = "ethernet-phy";
};
qe_phy2: ethernet-phy@02 {
interrupt-parent = <&mpic>;
- interrupts = <31 1>;
+ interrupts = <1 1>;
reg = <2>;
device_type = "ethernet-phy";
};
qe_phy3: ethernet-phy@03 {
interrupt-parent = <&mpic>;
- interrupts = <32 1>;
+ interrupts = <2 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@@ -367,7 +391,7 @@
reg = <80 80>;
built-in;
big-endian;
- interrupts = <1e 2 1e 2>; //high:30 low:30
+ interrupts = <2e 2 2e 2>; //high:30 low:30
interrupt-parent = <&mpic>;
};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 260b264c869e..db56a02b748f 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -56,8 +56,12 @@
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
- ranges = <0 f8000000 00100000>;
- reg = <f8000000 00100000>; // CCSRBAR 1M
+ ranges = <00001000 f8001000 000ff000
+ 80000000 80000000 20000000
+ e2000000 e2000000 00100000
+ a0000000 a0000000 20000000
+ e3000000 e3000000 00100000>;
+ reg = <f8000000 00001000>; // CCSRBAR
bus-frequency = <0>;
i2c@3000 {
@@ -86,25 +90,25 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
- interrupts = <4a 1>;
+ interrupts = <a 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
- interrupts = <4a 1>;
+ interrupts = <a 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
- interrupts = <4a 1>;
+ interrupts = <a 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
- interrupts = <4a 1>;
+ interrupts = <a 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@@ -117,7 +121,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
- mac-address = [ 00 E0 0C 00 73 00 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
@@ -130,7 +140,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
- mac-address = [ 00 E0 0C 00 73 01 ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
@@ -143,7 +159,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <26000 1000>;
- mac-address = [ 00 E0 0C 00 02 FD ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1F 2 20 2 21 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy2>;
@@ -156,7 +178,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <27000 1000>;
- mac-address = [ 00 E0 0C 00 03 FD ];
+ /*
+ * mac-address is deprecated and will be removed
+ * in 2.6.25. Only recent versions of
+ * U-Boot support local-mac-address, however.
+ */
+ mac-address = [ 00 00 00 00 00 00 ];
+ local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <25 2 26 2 27 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
@@ -186,7 +214,7 @@
#size-cells = <2>;
#address-cells = <3>;
reg = <8000 1000>;
- bus-range = <0 fe>;
+ bus-range = <0 ff>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
clock-frequency = <1fca055>;
@@ -285,17 +313,84 @@
f800 0 0 3 &i8259 0 0
f800 0 0 4 &i8259 0 0
>;
- i8259: i8259@4d0 {
- clock-frequency = <0>;
- interrupt-controller;
- device_type = "interrupt-controller";
- #address-cells = <0>;
- #interrupt-cells = <2>;
- built-in;
- compatible = "chrp,iic";
- big-endian;
- interrupts = <49 2>;
- interrupt-parent = <&mpic>;
+ uli1575@0 {
+ reg = <0 0 0 0 0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ ranges = <02000000 0 80000000
+ 02000000 0 80000000
+ 0 20000000
+ 01000000 0 00000000
+ 01000000 0 00000000
+ 0 00100000>;
+
+ pci_bridge@0 {
+ reg = <0 0 0 0 0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ ranges = <02000000 0 80000000
+ 02000000 0 80000000
+ 0 20000000
+ 01000000 0 00000000
+ 01000000 0 00000000
+ 0 00100000>;
+
+ isa@1e {
+ device_type = "isa";
+ #interrupt-cells = <2>;
+ #size-cells = <1>;
+ #address-cells = <2>;
+ reg = <f000 0 0 0 0>;
+ ranges = <1 0 01000000 0 0
+ 00001000>;
+ interrupt-parent = <&i8259>;
+
+ i8259: interrupt-controller@20 {
+ reg = <1 20 2
+ 1 a0 2
+ 1 4d0 2>;
+ clock-frequency = <0>;
+ interrupt-controller;
+ device_type = "interrupt-controller";
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ built-in;
+ compatible = "chrp,iic";
+ interrupts = <9 2>;
+ interrupt-parent =
+ <&mpic>;
+ };
+
+ i8042@60 {
+ #size-cells = <0>;
+ #address-cells = <1>;
+ reg = <1 60 1 1 64 1>;
+ interrupts = <1 3 c 3>;
+ interrupt-parent =
+ <&i8259>;
+
+ keyboard@0 {
+ reg = <0>;
+ compatible = "pnpPNP,303";
+ };
+
+ mouse@1 {
+ reg = <1>;
+ compatible = "pnpPNP,f03";
+ };
+ };
+
+ rtc@70 {
+ compatible =
+ "pnpPNP,b00";
+ reg = <1 70 2>;
+ };
+
+ gpio@400 {
+ reg = <1 400 80>;
+ };
+ };
+ };
};
};
@@ -316,10 +411,10 @@
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x0 */
- 0000 0 0 1 &mpic 44 1
- 0000 0 0 2 &mpic 45 1
- 0000 0 0 3 &mpic 46 1
- 0000 0 0 4 &mpic 47 1
+ 0000 0 0 1 &mpic 4 1
+ 0000 0 0 2 &mpic 5 1
+ 0000 0 0 3 &mpic 6 1
+ 0000 0 0 4 &mpic 7 1
>;
};
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index c0d06fd12927..e5e7726ddb03 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -15,12 +15,10 @@
compatible = "mpc8xx";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,866@0 {
device_type = "cpu";
@@ -34,14 +32,12 @@
clock-frequency = <0>;
32-bit;
interrupts = <f 2>; // decrementer interrupt
- interrupt-parent = <ff000000>;
- linux,phandle = <201>;
+ interrupt-parent = <&Mpc8xx_pic>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 800000>;
};
@@ -57,11 +53,9 @@
device_type = "mdio";
compatible = "fs_enet";
reg = <e80 8>;
- linux,phandle = <e80>;
#address-cells = <1>;
#size-cells = <0>;
- ethernet-phy@f {
- linux,phandle = <e800f>;
+ phy: ethernet-phy@f {
reg = <f>;
device_type = "ethernet-phy";
};
@@ -75,12 +69,11 @@
reg = <e00 188>;
mac-address = [ 00 00 0C 00 01 FD ];
interrupts = <3 1>;
- interrupt-parent = <ff000000>;
- phy-handle = <e800f>;
+ interrupt-parent = <&Mpc8xx_pic>;
+ phy-handle = <&Phy>;
};
- pic@ff000000 {
- linux,phandle = <ff000000>;
+ mpc8xx_pic: pic@ff000000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@@ -91,7 +84,6 @@
};
cpm@ff000000 {
- linux,phandle = <ff000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@@ -102,15 +94,14 @@
command-proc = <9c0>;
brg-frequency = <0>;
interrupts = <0 2>; // cpm error interrupt
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
- pic@930 {
- linux,phandle = <930>;
+ cpm_pic: pic@930 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <5 2 0 2>;
- interrupt-parent = <ff000000>;
+ interrupt-parent = <&Mpc8xx_pic>;
reg = <930 20>;
built-in;
device_type = "cpm-pic";
@@ -128,7 +119,7 @@
tx-clock = <1>;
current-speed = <0>;
interrupts = <4 3>;
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
};
smc@a90 {
@@ -142,7 +133,7 @@
tx-clock = <2>;
current-speed = <0>;
interrupts = <3 3>;
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
};
scc@a00 {
@@ -153,7 +144,7 @@
reg = <a00 18 3c00 80>;
mac-address = [ 00 00 0C 00 03 FD ];
interrupts = <1e 3>;
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
};
};
};
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 110bf6170603..dc7ab9c80611 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -15,12 +15,10 @@
compatible = "mpc8xx";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,885@0 {
device_type = "cpu";
@@ -34,14 +32,12 @@
clock-frequency = <0>;
32-bit;
interrupts = <f 2>; // decrementer interrupt
- interrupt-parent = <ff000000>;
- linux,phandle = <201>;
+ interrupt-parent = <&Mpc8xx_pic>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 800000>;
};
@@ -57,21 +53,17 @@
device_type = "mdio";
compatible = "fs_enet";
reg = <e80 8>;
- linux,phandle = <e80>;
#address-cells = <1>;
#size-cells = <0>;
- ethernet-phy@0 {
- linux,phandle = <e8000>;
+ Phy0: ethernet-phy@0 {
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <e8001>;
+ Phy1: ethernet-phy@1 {
reg = <1>;
device_type = "ethernet-phy";
};
- ethernet-phy@2 {
- linux,phandle = <e8002>;
+ Phy2: ethernet-phy@2 {
reg = <2>;
device_type = "ethernet-phy";
};
@@ -85,8 +77,8 @@
reg = <e00 188>;
mac-address = [ 00 00 0C 00 01 FD ];
interrupts = <3 1>;
- interrupt-parent = <ff000000>;
- phy-handle = <e8000>;
+ interrupt-parent = <&Mpc8xx_pic>;
+ phy-handle = <&Phy1>;
};
fec@1e00 {
@@ -97,12 +89,11 @@
reg = <1e00 188>;
mac-address = [ 00 00 0C 00 02 FD ];
interrupts = <7 1>;
- interrupt-parent = <ff000000>;
- phy-handle = <e8001>;
+ interrupt-parent = <&Mpc8xx_pic>;
+ phy-handle = <&Phy2>;
};
- pic@ff000000 {
- linux,phandle = <ff000000>;
+ Mpc8xx_pic: pic@ff000000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@@ -112,8 +103,18 @@
compatible = "CPM";
};
+ pcmcia@0080 {
+ #address-cells = <3>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ compatible = "fsl,pq-pcmcia";
+ device_type = "pcmcia";
+ reg = <80 80>;
+ interrupt-parent = <&Mpc8xx_pic>;
+ interrupts = <d 1>;
+ };
+
cpm@ff000000 {
- linux,phandle = <ff000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@@ -124,15 +125,14 @@
command-proc = <9c0>;
brg-frequency = <0>;
interrupts = <0 2>; // cpm error interrupt
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
- pic@930 {
- linux,phandle = <930>;
+ Cpm_pic: pic@930 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <5 2 0 2>;
- interrupt-parent = <ff000000>;
+ interrupt-parent = <&Mpc8xx_pic>;
reg = <930 20>;
built-in;
device_type = "cpm-pic";
@@ -150,7 +150,7 @@
tx-clock = <1>;
current-speed = <0>;
interrupts = <4 3>;
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
};
smc@a90 {
@@ -164,7 +164,7 @@
tx-clock = <2>;
current-speed = <0>;
interrupts = <3 3>;
- interrupt-parent = <930>;
+ interrupt-parent = <&Cpm_pic>;
};
scc@a40 {
@@ -175,8 +175,8 @@
reg = <a40 18 3e00 80>;
mac-address = [ 00 00 0C 00 03 FD ];
interrupts = <1c 3>;
- interrupt-parent = <930>;
- phy-handle = <e8002>;
+ interrupt-parent = <&Cpm_pic>;
+ phy-handle = <&Phy2>;
};
};
};
diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts
index 568965a022b9..699d0df574d5 100644
--- a/arch/powerpc/boot/dts/prpmc2800.dts
+++ b/arch/powerpc/boot/dts/prpmc2800.dts
@@ -309,7 +309,7 @@
};
chosen {
- bootargs = "ip=on console=ttyMM0";
+ bootargs = "ip=on";
linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
};
};
diff --git a/arch/powerpc/boot/dts/ps3.dts b/arch/powerpc/boot/dts/ps3.dts
new file mode 100644
index 000000000000..379ded282d5e
--- /dev/null
+++ b/arch/powerpc/boot/dts/ps3.dts
@@ -0,0 +1,68 @@
+/*
+ * PS3 Game Console device tree.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/ {
+ model = "SonyPS3";
+ compatible = "sony,ps3";
+ #size-cells = <2>;
+ #address-cells = <2>;
+
+ chosen {
+ };
+
+ /*
+ * We'll get the size of the bootmem block from lv1 after startup,
+ * so we'll put a null entry here.
+ */
+
+ memory {
+ device_type = "memory";
+ reg = <0 0 0 0>;
+ };
+
+ /*
+ * The boot cpu is always zero for PS3.
+ *
+ * dtc expects a clock-frequency and timebase-frequency entries, so
+ * we'll put a null entries here. These will be initialized after
+ * startup with data from lv1.
+ *
+ * Seems the only way currently to indicate a processor has multiple
+ * threads is with an ibm,ppc-interrupt-server#s entry. We'll put one
+ * here so we can bring up both of ours. See smp_setup_cpu_maps().
+ */
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ ibm,ppc-interrupt-server#s = <0 1>;
+ clock-frequency = <0>;
+ timebase-frequency = <0>;
+ i-cache-size = <8000>;
+ d-cache-size = <8000>;
+ i-cache-line-size = <80>;
+ d-cache-line-size = <80>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
index b1251ee7a102..75daedafd0a4 100644
--- a/arch/powerpc/boot/ebony.c
+++ b/arch/powerpc/boot/ebony.c
@@ -100,28 +100,13 @@ static void ebony_fixups(void)
ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
ibm44x_fixup_memsize();
dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
-}
-
-#define SPRN_DBCR0 0x134
-#define DBCR0_RST_SYSTEM 0x30000000
-
-static void ebony_exit(void)
-{
- unsigned long tmp;
-
- asm volatile (
- "mfspr %0,%1\n"
- "oris %0,%0,%2@h\n"
- "mtspr %1,%0"
- : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
- );
-
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
}
void ebony_init(void *mac0, void *mac1)
{
platform_ops.fixups = ebony_fixups;
- platform_ops.exit = ebony_exit;
+ platform_ops.exit = ibm44x_dbcr_reset;
ebony_mac0 = mac0;
ebony_mac1 = mac1;
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 56b56a8d4b23..416dc3857bfe 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -36,8 +36,6 @@ struct addr_range {
unsigned long size;
};
-typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
-
#undef DEBUG
static struct addr_range prep_kernel(void)
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index d16ee3e3f868..385e08b83b7e 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -15,8 +15,7 @@
#include "page.h"
#include "ops.h"
-typedef void *ihandle;
-typedef void *phandle;
+#include "of.h"
extern char _end[];
@@ -25,154 +24,10 @@ extern char _end[];
#define RAM_END (512<<20) /* Fixme: use OF */
#define ONE_MB 0x100000
-int (*prom) (void *);
static unsigned long claim_base;
-static int call_prom(const char *service, int nargs, int nret, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, nret);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- return (nret > 0)? args.args[nargs]: 0;
-}
-
-static int call_prom_ret(const char *service, int nargs, int nret,
- unsigned int *rets, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, rets);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- if (rets != (void *) 0)
- for (i = 1; i < nret; ++i)
- rets[i-1] = args.args[nargs+i];
-
- return (nret > 0)? args.args[nargs]: 0;
-}
-
-/*
- * Older OF's require that when claiming a specific range of addresses,
- * we claim the physical space in the /memory node and the virtual
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
- for (; *s2; ++s2)
- if (*s1++ != *s2)
- return 0;
- return 1;
-}
-
-static int check_of_version(void)
-{
- phandle oprom, chosen;
- char version[64];
-
- oprom = finddevice("/openprom");
- if (oprom == (phandle) -1)
- return 0;
- if (getprop(oprom, "model", version, sizeof(version)) <= 0)
- return 0;
- version[sizeof(version)-1] = 0;
- printf("OF version = '%s'\r\n", version);
- if (!string_match(version, "Open Firmware, 1.")
- && !string_match(version, "FirmWorks,3."))
- return 0;
- chosen = finddevice("/chosen");
- if (chosen == (phandle) -1) {
- chosen = finddevice("/chosen@0");
- if (chosen == (phandle) -1) {
- printf("no chosen\n");
- return 0;
- }
- }
- if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
- printf("no mmu\n");
- return 0;
- }
- memory = (ihandle) call_prom("open", 1, 1, "/memory");
- if (memory == (ihandle) -1) {
- memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
- if (memory == (ihandle) -1) {
- printf("no memory node\n");
- return 0;
- }
- }
- printf("old OF detected\r\n");
- return 1;
-}
-
-static void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
- int ret;
- unsigned int result;
-
- if (need_map < 0)
- need_map = check_of_version();
- if (align || !need_map)
- return (void *) call_prom("claim", 3, 1, virt, size, align);
-
- ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
- align, size, virt);
- if (ret != 0 || result == -1)
- return (void *) -1;
- ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
- align, size, virt);
- /* 0x12 == coherent + read/write */
- ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
- 0x12, size, virt, virt);
- return (void *) virt;
-}
-
static void *of_try_claim(unsigned long size)
{
unsigned long addr = 0;
@@ -184,7 +39,7 @@ static void *of_try_claim(unsigned long size)
#ifdef DEBUG
printf(" trying: 0x%08lx\n\r", claim_base);
#endif
- addr = (unsigned long)claim(claim_base, size, 0);
+ addr = (unsigned long)of_claim(claim_base, size, 0);
if ((void *)addr != (void *)-1)
break;
}
@@ -208,64 +63,6 @@ static void of_image_hdr(const void *hdr)
}
}
-static void *of_vmlinux_alloc(unsigned long size)
-{
- void *p = malloc(size);
-
- if (!p)
- fatal("Can't allocate memory for kernel image!\n\r");
-
- return p;
-}
-
-static void of_exit(void)
-{
- call_prom("exit", 0, 0);
-}
-
-/*
- * OF device tree routines
- */
-static void *of_finddevice(const char *name)
-{
- return (phandle) call_prom("finddevice", 1, 1, name);
-}
-
-static int of_getprop(const void *phandle, const char *name, void *buf,
- const int buflen)
-{
- return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-}
-
-static int of_setprop(const void *phandle, const char *name, const void *buf,
- const int buflen)
-{
- return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
-}
-
-/*
- * OF console routines
- */
-static void *of_stdout_handle;
-
-static int of_console_open(void)
-{
- void *devp;
-
- if (((devp = finddevice("/chosen")) != NULL)
- && (getprop(devp, "stdout", &of_stdout_handle,
- sizeof(of_stdout_handle))
- == sizeof(of_stdout_handle)))
- return 0;
-
- return -1;
-}
-
-static void of_console_write(char *buf, int len)
-{
- call_prom("write", 3, 1, of_stdout_handle, buf, len);
-}
-
void platform_init(unsigned long a1, unsigned long a2, void *promptr)
{
platform_ops.image_hdr = of_image_hdr;
@@ -277,10 +74,9 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr)
dt_ops.getprop = of_getprop;
dt_ops.setprop = of_setprop;
- console_ops.open = of_console_open;
- console_ops.write = of_console_write;
+ of_console_init();
- prom = (int (*)(void *))promptr;
+ of_init(promptr);
loader_info.promptr = promptr;
if (a1 && a2 && a2 != 0xdeadbeef) {
loader_info.initrd_addr = a1;
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
new file mode 100644
index 000000000000..e4c68f7391c5
--- /dev/null
+++ b/arch/powerpc/boot/of.h
@@ -0,0 +1,21 @@
+#ifndef _PPC_BOOT_OF_H_
+#define _PPC_BOOT_OF_H_
+
+typedef void *phandle;
+typedef void *ihandle;
+
+void of_init(void *promptr);
+int of_call_prom(const char *service, int nargs, int nret, ...);
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
+void *of_vmlinux_alloc(unsigned long size);
+void of_exit(void);
+void *of_finddevice(const char *name);
+int of_getprop(const void *phandle, const char *name, void *buf,
+ const int buflen);
+int of_setprop(const void *phandle, const char *name, const void *buf,
+ const int buflen);
+
+/* Console functions */
+void of_console_init(void);
+
+#endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c
new file mode 100644
index 000000000000..ce0e02424453
--- /dev/null
+++ b/arch/powerpc/boot/ofconsole.c
@@ -0,0 +1,45 @@
+/*
+ * OF console routines
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static void *of_stdout_handle;
+
+static int of_console_open(void)
+{
+ void *devp;
+
+ if (((devp = of_finddevice("/chosen")) != NULL)
+ && (of_getprop(devp, "stdout", &of_stdout_handle,
+ sizeof(of_stdout_handle))
+ == sizeof(of_stdout_handle)))
+ return 0;
+
+ return -1;
+}
+
+static void of_console_write(const char *buf, int len)
+{
+ of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
+}
+
+void of_console_init(void)
+{
+ console_ops.open = of_console_open;
+ console_ops.write = of_console_write;
+}
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
new file mode 100644
index 000000000000..95b8fd69a403
--- /dev/null
+++ b/arch/powerpc/boot/oflib.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static int (*prom) (void *);
+
+void of_init(void *promptr)
+{
+ prom = (int (*)(void *))promptr;
+}
+
+int of_call_prom(const char *service, int nargs, int nret, ...)
+{
+ int i;
+ struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, nret);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int of_call_prom_ret(const char *service, int nargs, int nret,
+ unsigned int *rets, ...)
+{
+ int i;
+ struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, rets);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ if (rets != (void *) 0)
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = args.args[nargs+i];
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+ for (; *s2; ++s2)
+ if (*s1++ != *s2)
+ return 0;
+ return 1;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+static int check_of_version(void)
+{
+ phandle oprom, chosen;
+ char version[64];
+
+ oprom = of_finddevice("/openprom");
+ if (oprom == (phandle) -1)
+ return 0;
+ if (of_getprop(oprom, "model", version, sizeof(version)) <= 0)
+ return 0;
+ version[sizeof(version)-1] = 0;
+ printf("OF version = '%s'\r\n", version);
+ if (!string_match(version, "Open Firmware, 1.")
+ && !string_match(version, "FirmWorks,3."))
+ return 0;
+ chosen = of_finddevice("/chosen");
+ if (chosen == (phandle) -1) {
+ chosen = of_finddevice("/chosen@0");
+ if (chosen == (phandle) -1) {
+ printf("no chosen\n");
+ return 0;
+ }
+ }
+ if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+ printf("no mmu\n");
+ return 0;
+ }
+ memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
+ if (memory == (ihandle) -1) {
+ memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
+ if (memory == (ihandle) -1) {
+ printf("no memory node\n");
+ return 0;
+ }
+ }
+ printf("old OF detected\r\n");
+ return 1;
+}
+
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+ int ret;
+ unsigned int result;
+
+ if (need_map < 0)
+ need_map = check_of_version();
+ if (align || !need_map)
+ return (void *) of_call_prom("claim", 3, 1, virt, size, align);
+
+ ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+ align, size, virt);
+ if (ret != 0 || result == -1)
+ return (void *) -1;
+ ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+ align, size, virt);
+ /* 0x12 == coherent + read/write */
+ ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
+ 0x12, size, virt, virt);
+ return (void *) virt;
+}
+
+void *of_vmlinux_alloc(unsigned long size)
+{
+ void *p = malloc(size);
+
+ if (!p)
+ fatal("Can't allocate memory for kernel image!\n\r");
+
+ return p;
+}
+
+void of_exit(void)
+{
+ of_call_prom("exit", 0, 0);
+}
+
+/*
+ * OF device tree routines
+ */
+void *of_finddevice(const char *name)
+{
+ return (phandle) of_call_prom("finddevice", 1, 1, name);
+}
+
+int of_getprop(const void *phandle, const char *name, void *buf,
+ const int buflen)
+{
+ return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
+int of_setprop(const void *phandle, const char *name, const void *buf,
+ const int buflen)
+{
+ return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 959124f3f9af..86077066cd7c 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -19,6 +19,8 @@
#define MAX_PATH_LEN 256
#define MAX_PROP_LEN 256 /* What should this be? */
+typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
+
/* Platform specific operations */
struct platform_ops {
void (*fixups)(void);
@@ -51,7 +53,7 @@ extern struct dt_ops dt_ops;
/* Console operations */
struct console_ops {
int (*open)(void);
- void (*write)(char *buf, int len);
+ void (*write)(const char *buf, int len);
void (*edit_cmdline)(char *buf, int len);
void (*close)(void);
void *data;
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
new file mode 100644
index 000000000000..1a6d64a68df5
--- /dev/null
+++ b/arch/powerpc/boot/ps3-head.S
@@ -0,0 +1,80 @@
+/*
+ * PS3 bootwrapper entry.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ppc_asm.h"
+
+ .text
+
+/*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+ * The bootwraper build script copies the 0x100 bytes at symbol
+ * __system_reset_overlay to offset 0x100 of the rom image.
+ *
+ * The PS3 has a single processor with two threads.
+ */
+
+ .globl __system_reset_overlay
+__system_reset_overlay:
+
+ /* Switch to 32-bit mode. */
+
+ mfmsr r9
+ clrldi r9,r9,1
+ mtmsrd r9
+ nop
+
+ /* Get thread number in r3 and branch. */
+
+ mfspr r3, 0x88
+ cntlzw. r3, r3
+ li r4, 0
+ li r5, 0
+ beq 1f
+
+ /* Secondary goes to __secondary_hold in kernel. */
+
+ li r4, 0x60
+ mtctr r4
+ bctr
+
+ /* Primary delays then goes to _zimage_start in wrapper. */
+1:
+ or 31, 31, 31 /* db16cyc */
+ or 31, 31, 31 /* db16cyc */
+
+ lis r4, _zimage_start@ha
+ addi r4, r4, _zimage_start@l
+ mtctr r4
+ bctr
+
+/*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+ * The bootwrapper build script copies 0x100 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel. At runtime
+ * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+ * to ram address 0x100. This symbol must occupy 0x100 bytes.
+ */
+
+ .globl __system_reset_kernel
+__system_reset_kernel:
+
+ . = __system_reset_kernel + 0x100
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S
new file mode 100644
index 000000000000..c8b7df3210d1
--- /dev/null
+++ b/arch/powerpc/boot/ps3-hvcall.S
@@ -0,0 +1,184 @@
+/*
+ * PS3 bootwrapper hvcalls.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ppc_asm.h"
+
+/*
+ * The PS3 hypervisor uses a 64 bit "C" language calling convention.
+ * The routines here marshal arguments between the 32 bit wrapper
+ * program and the 64 bit hvcalls.
+ *
+ * wrapper lv1
+ * 32-bit (h,l) 64-bit
+ *
+ * 1: r3,r4 <-> r3
+ * 2: r5,r6 <-> r4
+ * 3: r7,r8 <-> r5
+ * 4: r9,r10 <-> r6
+ * 5: 8(r1),12(r1) <-> r7
+ * 6: 16(r1),20(r1) <-> r8
+ * 7: 24(r1),28(r1) <-> r9
+ * 8: 32(r1),36(r1) <-> r10
+ *
+ */
+
+.macro GLOBAL name
+ .section ".text"
+ .balign 4
+ .globl \name
+\name:
+.endm
+
+.macro NO_SUPPORT name
+ GLOBAL \name
+ b ps3_no_support
+.endm
+
+.macro HVCALL num
+ li r11, \num
+ .long 0x44000022
+ extsw r3, r3
+.endm
+
+.macro SAVE_LR offset=4
+ mflr r0
+ stw r0, \offset(r1)
+.endm
+
+.macro LOAD_LR offset=4
+ lwz r0, \offset(r1)
+ mtlr r0
+.endm
+
+.macro LOAD_64_REG target,high,low
+ sldi r11, \high, 32
+ or \target, r11, \low
+.endm
+
+.macro LOAD_64_STACK target,offset
+ ld \target, \offset(r1)
+.endm
+
+.macro LOAD_R3
+ LOAD_64_REG r3,r3,r4
+.endm
+
+.macro LOAD_R4
+ LOAD_64_REG r4,r5,r6
+.endm
+
+.macro LOAD_R5
+ LOAD_64_REG r5,r7,r8
+.endm
+
+.macro LOAD_R6
+ LOAD_64_REG r6,r9,r10
+.endm
+
+.macro LOAD_R7
+ LOAD_64_STACK r7,8
+.endm
+
+.macro LOAD_R8
+ LOAD_64_STACK r8,16
+.endm
+
+.macro LOAD_R9
+ LOAD_64_STACK r9,24
+.endm
+
+.macro LOAD_R10
+ LOAD_64_STACK r10,32
+.endm
+
+.macro LOAD_REGS_0
+ stwu 1,-16(1)
+ stw 3, 8(1)
+.endm
+
+.macro LOAD_REGS_5
+ LOAD_R3
+ LOAD_R4
+ LOAD_R5
+ LOAD_R6
+ LOAD_R7
+.endm
+
+.macro LOAD_REGS_6
+ LOAD_REGS_5
+ LOAD_R8
+.endm
+
+.macro LOAD_REGS_8
+ LOAD_REGS_6
+ LOAD_R9
+ LOAD_R10
+.endm
+
+.macro STORE_REGS_0_1
+ lwz r11, 8(r1)
+ std r4, 0(r11)
+ mr r4, r3
+ li r3, 0
+ addi r1,r1,16
+.endm
+
+.macro STORE_REGS_5_2
+ lwz r11, 16(r1)
+ std r4, 0(r11)
+ lwz r11, 24(r1)
+ std r5, 0(r11)
+.endm
+
+.macro STORE_REGS_6_1
+ lwz r11, 24(r1)
+ std r4, 0(r11)
+.endm
+
+GLOBAL lv1_get_logical_ppe_id
+ SAVE_LR
+ LOAD_REGS_0
+ HVCALL 69
+ STORE_REGS_0_1
+ LOAD_LR
+ blr
+
+GLOBAL lv1_get_logical_partition_id
+ SAVE_LR
+ LOAD_REGS_0
+ HVCALL 74
+ STORE_REGS_0_1
+ LOAD_LR
+ blr
+
+GLOBAL lv1_get_repository_node_value
+ SAVE_LR
+ LOAD_REGS_5
+ HVCALL 91
+ STORE_REGS_5_2
+ LOAD_LR
+ blr
+
+GLOBAL lv1_panic
+ SAVE_LR
+ LOAD_REGS_8
+ HVCALL 255
+ LOAD_LR
+ blr
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
new file mode 100644
index 000000000000..893d59339c26
--- /dev/null
+++ b/arch/powerpc/boot/ps3.c
@@ -0,0 +1,161 @@
+/*
+ * PS3 bootwrapper support.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+extern s64 lv1_panic(u64 in_1);
+extern s64 lv1_get_logical_partition_id(u64 *out_1);
+extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+ u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+#ifdef DEBUG
+#define DBG(fmt...) printf(fmt)
+#else
+static inline int __attribute__ ((format (printf, 1, 2))) DBG(
+ const char *fmt, ...) {return 0;}
+#endif
+
+BSS_STACK(4096);
+
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char cmdline[COMMAND_LINE_SIZE]
+ __attribute__((__section__("__builtin_cmdline")));
+
+static void prep_cmdline(void *chosen)
+{
+ if (cmdline[0] == '\0')
+ getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+ else
+ setprop_str(chosen, "bootargs", cmdline);
+
+ printf("cmdline: '%s'\n", cmdline);
+}
+
+static void ps3_console_write(const char *buf, int len)
+{
+}
+
+static void ps3_exit(void)
+{
+ printf("ps3_exit\n");
+
+ /* lv1_panic will shutdown the lpar. */
+
+ lv1_panic(0); /* zero = do not reboot */
+ while (1);
+}
+
+static int ps3_repository_read_rm_size(u64 *rm_size)
+{
+ s64 result;
+ u64 lpar_id;
+ u64 ppe_id;
+ u64 v2;
+
+ result = lv1_get_logical_partition_id(&lpar_id);
+
+ if (result)
+ return -1;
+
+ result = lv1_get_logical_ppe_id(&ppe_id);
+
+ if (result)
+ return -1;
+
+ /*
+ * n1: 0000000062690000 : ....bi..
+ * n2: 7075000000000000 : pu......
+ * n3: 0000000000000001 : ........
+ * n4: 726d5f73697a6500 : rm_size.
+ */
+
+ result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
+ 0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
+ &v2);
+
+ printf("%s:%d: ppe_id %lu \n", __func__, __LINE__,
+ (unsigned long)ppe_id);
+ printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
+ (unsigned long)lpar_id);
+ printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
+
+ return result ? -1 : 0;
+}
+
+void ps3_copy_vectors(void)
+{
+ extern char __system_reset_kernel[];
+
+ memcpy((void *)0x100, __system_reset_kernel, 0x100);
+ flush_cache((void *)0x100, 0x100);
+}
+
+void platform_init(void)
+{
+ extern char _end[];
+ extern char _dtb_start[];
+ extern char _initrd_start[];
+ extern char _initrd_end[];
+ const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+ void *chosen;
+ unsigned long ft_addr;
+ u64 rm_size;
+
+ console_ops.write = ps3_console_write;
+ platform_ops.exit = ps3_exit;
+
+ printf("\n-- PS3 bootwrapper --\n");
+
+ simple_alloc_init(_end, heapsize, 32, 64);
+ ft_init(_dtb_start, 0, 4);
+
+ chosen = finddevice("/chosen");
+
+ ps3_repository_read_rm_size(&rm_size);
+ dt_fixup_memory(0, rm_size);
+
+ if (_initrd_end > _initrd_start) {
+ setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
+ setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
+ }
+
+ prep_cmdline(chosen);
+
+ ft_addr = dt_ops.finalize();
+
+ ps3_copy_vectors();
+
+ printf(" flat tree at 0x%lx\n\r", ft_addr);
+
+ ((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+ ps3_exit();
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index 7fd32330a9a5..eaa0d3ae3518 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -27,7 +27,7 @@ static int serial_open(void)
return scdp->open();
}
-static void serial_write(char *buf, int len)
+static void serial_write(const char *buf, int len)
{
struct serial_console_data *scdp = console_ops.data;
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 0a9feeb98342..5b57800bbc67 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt, va_list args)
/* get the conversion qualifier */
qualifier = -1;
- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+ if (*fmt == 'l' && *(fmt + 1) == 'l') {
+ qualifier = 'q';
+ fmt += 2;
+ } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
+ || *fmt == 'Z') {
qualifier = *fmt;
++fmt;
}
@@ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt, va_list args)
num = va_arg(args, unsigned long);
if (flags & SIGN)
num = (signed long) num;
+ } else if (qualifier == 'q') {
+ num = va_arg(args, unsigned long long);
+ if (flags & SIGN)
+ num = (signed long long) num;
} else if (qualifier == 'Z') {
num = va_arg(args, size_t);
} else if (qualifier == 'h') {
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
index 79d26e708677..31393d17a9c1 100644
--- a/arch/powerpc/boot/types.h
+++ b/arch/powerpc/boot/types.h
@@ -7,6 +7,10 @@ typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
+typedef signed char s8;
+typedef short s16;
+typedef int s32;
+typedef long long s64;
#define min(x,y) ({ \
typeof(x) _x = (x); \
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index da77adc73078..65f685479175 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -144,6 +144,15 @@ miboot|uboot)
cuboot*)
gzip=
;;
+ps3)
+ platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
+ lds=$object/zImage.ps3.lds
+ gzip=
+ ext=bin
+ objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
+ ksection=.kernel:vmlinux.bin
+ isection=.kernel:initrd
+ ;;
esac
vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@@ -239,4 +248,50 @@ treeboot*)
fi
exit 0
;;
+ps3)
+ # The ps3's loader supports loading gzipped binary images from flash
+ # rom to addr zero. The loader enters the image at addr 0x100. A
+ # bootwrapper overlay is use to arrange for the kernel to be loaded
+ # to addr zero and to have a suitable bootwrapper entry at 0x100.
+ # To construct the rom image, 0x100 bytes from offset 0x100 in the
+ # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+ # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+ # then copied to offset 0x100. At runtime the bootwrapper program
+ # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
+
+ system_reset_overlay=0x`${CROSS}nm "$ofile" \
+ | grep ' __system_reset_overlay$' \
+ | cut -d' ' -f1`
+ system_reset_overlay=`printf "%d" $system_reset_overlay`
+ system_reset_kernel=0x`${CROSS}nm "$ofile" \
+ | grep ' __system_reset_kernel$' \
+ | cut -d' ' -f1`
+ system_reset_kernel=`printf "%d" $system_reset_kernel`
+ overlay_dest="256"
+ overlay_size="256"
+
+ rm -f "$object/otheros.bld"
+
+ ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+ msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+ skip=$overlay_dest seek=$system_reset_kernel \
+ count=$overlay_size bs=1 2>&1)
+
+ if [ $? -ne "0" ]; then
+ echo $msg
+ exit 1
+ fi
+
+ msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+ skip=$system_reset_overlay seek=$overlay_dest \
+ count=$overlay_size bs=1 2>&1)
+
+ if [ $? -ne "0" ]; then
+ echo $msg
+ exit 2
+ fi
+
+ gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+ ;;
esac
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S
new file mode 100644
index 000000000000..aaa469c1e60d
--- /dev/null
+++ b/arch/powerpc/boot/zImage.ps3.lds.S
@@ -0,0 +1,50 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_zimage_start)
+EXTERN(_zimage_start)
+SECTIONS
+{
+ _vmlinux_start = .;
+ .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
+ _vmlinux_end = .;
+
+ . = ALIGN(4096);
+ _dtb_start = .;
+ .kernel:dtb : { *(.kernel:dtb) }
+ _dtb_end = .;
+
+ . = ALIGN(4096);
+ _initrd_start = .;
+ .kernel:initrd : { *(.kernel:initrd) }
+ _initrd_end = .;
+
+ _start = .;
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+ }
+ _etext = .;
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.rodata*)
+ *(.data*)
+ *(.sdata*)
+ __got2_start = .;
+ *(.got2)
+ __got2_end = .;
+ }
+
+ . = ALIGN(4096);
+ _edata = .;
+
+ . = ALIGN(4096);
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss)
+ *(.bss)
+ }
+ . = ALIGN(4096);
+ _end = . ;
+}
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
index 32781849ad4c..04b94f884aae 100644
--- a/arch/powerpc/configs/holly_defconfig
+++ b/arch/powerpc/configs/holly_defconfig
@@ -190,10 +190,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
-# CONFIG_WANT_DEVICE_TREE is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE="holly.dts"
CONFIG_ISA_DMA_API=y
#
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 956d1df61e0f..d0b43df44426 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -156,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20
CONFIG_PS3_USE_LPAR_ADDR=y
CONFIG_PS3_VUART=y
CONFIG_PS3_PS3AV=y
-CONFIG_PS3_SYS_MANAGER=y
+CONFIG_PS3_SYS_MANAGER=m
+CONFIG_PS3_STORAGE=y
+CONFIG_PS3_DISK=y
+CONFIG_PS3_ROM=y
+CONFIG_PS3_FLASH=y
CONFIG_PPC_CELL=y
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
@@ -335,7 +339,7 @@ CONFIG_BT=m
CONFIG_BT_L2CAP=m
CONFIG_BT_SCO=m
CONFIG_BT_RFCOMM=m
-# CONFIG_BT_RFCOMM_TTY is not set
+CONFIG_BT_RFCOMM_TTY=y
# CONFIG_BT_BNEP is not set
CONFIG_BT_HIDP=m
@@ -344,7 +348,9 @@ CONFIG_BT_HIDP=m
#
CONFIG_BT_HCIUSB=m
CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
# CONFIG_BT_HCIBCM203X is not set
# CONFIG_BT_HCIBPA10X is not set
# CONFIG_BT_HCIBFUSB is not set
@@ -435,7 +441,7 @@ CONFIG_CHR_DEV_SG=m
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
@@ -479,6 +485,7 @@ CONFIG_NETDEVICES=y
CONFIG_MII=m
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
+CONFIG_GELIC_NET=y
#
# Wireless LAN
@@ -546,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -563,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -1086,7 +1113,7 @@ CONFIG_HAS_DMA=y
#
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
@@ -1116,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUGGER is not set
CONFIG_IRQSTACKS=y
# CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
#
# Security options
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3e779f07f21b..42c42ecad00c 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,7 +12,8 @@ endif
obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
irq.o align.o signal_32.o pmc.o vdso.o \
- init_task.o process.o systbl.o idle.o
+ init_task.o process.o systbl.o idle.o \
+ signal.o
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o \
@@ -65,9 +66,9 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y)
-pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
+pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o isa-bridge.o
pci32-$(CONFIG_PPC32) := pci_32.o
-obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
+obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) pci-common.o
obj-$(CONFIG_PCI_MSI) += msi.o
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
kexec-$(CONFIG_PPC32) := machine_kexec_32.o
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index b2b5d664d328..b1f8000952f3 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -294,6 +294,21 @@ static struct cpu_spec cpu_specs[] = {
.oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5",
},
+ { /* Power5++ */
+ .pvr_mask = 0xffffff00,
+ .pvr_value = 0x003b0300,
+ .cpu_name = "POWER5+ (gs)",
+ .cpu_features = CPU_FTRS_POWER5,
+ .cpu_user_features = COMMON_USER_POWER5_PLUS,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 6,
+ .oprofile_cpu_type = "ppc64/power5++",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_mmcra_sihv = MMCRA_SIHV,
+ .oprofile_mmcra_sipr = MMCRA_SIPR,
+ .platform = "power5+",
+ },
{ /* Power5 GS */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003b0000,
@@ -1178,8 +1193,8 @@ static struct cpu_spec cpu_specs[] = {
.platform = "ppc440",
},
{ /* 440SP Rev. A */
- .pvr_mask = 0xff000fff,
- .pvr_value = 0x53000891,
+ .pvr_mask = 0xfff00fff,
+ .pvr_value = 0x53200891,
.cpu_name = "440SP Rev. A",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
@@ -1188,9 +1203,19 @@ static struct cpu_spec cpu_specs[] = {
.platform = "ppc440",
},
{ /* 440SPe Rev. A */
- .pvr_mask = 0xff000fff,
- .pvr_value = 0x53000890,
- .cpu_name = "440SPe Rev. A",
+ .pvr_mask = 0xfff00fff,
+ .pvr_value = 0x53400890,
+ .cpu_name = "440SPe Rev. A",
+ .cpu_features = CPU_FTRS_44X,
+ .cpu_user_features = COMMON_USER_BOOKE,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .platform = "ppc440",
+ },
+ { /* 440SPe Rev. B */
+ .pvr_mask = 0xfff00fff,
+ .pvr_value = 0x53400891,
+ .cpu_name = "440SPe Rev. B",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index c897203198b1..7d73a13450b0 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -9,7 +9,6 @@
* rewritten by Paul Mackerras.
* Copyright (C) 1996 Paul Mackerras.
* MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* This file contains the low-level support and setup for the
* PowerPC platform, including trap and interrupt dispatch.
@@ -32,10 +31,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
-#ifdef CONFIG_APUS
-#include <asm/amigappc.h>
-#endif
-
/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, reg, RA, RB) \
/* see the comment for clear_bats() -- Cort */ \
@@ -92,11 +87,6 @@ _start:
* r4: virtual address of boot_infos_t
* r5: 0
*
- * APUS
- * r3: 'APUS'
- * r4: physical address of memory base
- * Linux/m68k style BootInfo structure at &_end.
- *
* PREP
* This is jumped to on prep systems right after the kernel is relocated
* to its proper place in memory by the boot loader. The expected layout
@@ -150,14 +140,6 @@ __start:
*/
bl early_init
-#ifdef CONFIG_APUS
-/* On APUS the __va/__pa constants need to be set to the correct
- * values before continuing.
- */
- mr r4,r30
- bl fix_mem_constants
-#endif /* CONFIG_APUS */
-
/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
* the physical address we are running at, returned by early_init()
*/
@@ -167,7 +149,7 @@ __after_mmu_off:
bl flush_tlbs
bl initial_bats
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#if defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
@@ -183,7 +165,6 @@ __after_mmu_off:
#endif /* CONFIG_6xx */
-#ifndef CONFIG_APUS
/*
* We need to run with _start at physical address 0.
* On CHRP, we are loaded at 0x10000 since OF on CHRP uses
@@ -196,7 +177,6 @@ __after_mmu_off:
addis r4,r3,KERNELBASE@h /* current address of _start */
cmpwi 0,r4,0 /* are we already running at 0? */
bne relocate_kernel
-#endif /* CONFIG_APUS */
/*
* we now have the 1st 16M of ram mapped with the bats.
* prep needs the mmu to be turned on here, but pmac already has it on.
@@ -881,85 +861,6 @@ _GLOBAL(copy_and_flush)
addi r6,r6,4
blr
-#ifdef CONFIG_APUS
-/*
- * On APUS the physical base address of the kernel is not known at compile
- * time, which means the __pa/__va constants used are incorrect. In the
- * __init section is recorded the virtual addresses of instructions using
- * these constants, so all that has to be done is fix these before
- * continuing the kernel boot.
- *
- * r4 = The physical address of the kernel base.
- */
-fix_mem_constants:
- mr r10,r4
- addis r10,r10,-KERNELBASE@h /* virt_to_phys constant */
- neg r11,r10 /* phys_to_virt constant */
-
- lis r12,__vtop_table_begin@h
- ori r12,r12,__vtop_table_begin@l
- add r12,r12,r10 /* table begin phys address */
- lis r13,__vtop_table_end@h
- ori r13,r13,__vtop_table_end@l
- add r13,r13,r10 /* table end phys address */
- subi r12,r12,4
- subi r13,r13,4
-1: lwzu r14,4(r12) /* virt address of instruction */
- add r14,r14,r10 /* phys address of instruction */
- lwz r15,0(r14) /* instruction, now insert top */
- rlwimi r15,r10,16,16,31 /* half of vp const in low half */
- stw r15,0(r14) /* of instruction and restore. */
- dcbst r0,r14 /* write it to memory */
- sync
- icbi r0,r14 /* flush the icache line */
- cmpw r12,r13
- bne 1b
- sync /* additional sync needed on g4 */
- isync
-
-/*
- * Map the memory where the exception handlers will
- * be copied to when hash constants have been patched.
- */
-#ifdef CONFIG_APUS_FAST_EXCEPT
- lis r8,0xfff0
-#else
- lis r8,0
-#endif
- ori r8,r8,0x2 /* 128KB, supervisor */
- mtspr SPRN_DBAT3U,r8
- mtspr SPRN_DBAT3L,r8
-
- lis r12,__ptov_table_begin@h
- ori r12,r12,__ptov_table_begin@l
- add r12,r12,r10 /* table begin phys address */
- lis r13,__ptov_table_end@h
- ori r13,r13,__ptov_table_end@l
- add r13,r13,r10 /* table end phys address */
- subi r12,r12,4
- subi r13,r13,4
-1: lwzu r14,4(r12) /* virt address of instruction */
- add r14,r14,r10 /* phys address of instruction */
- lwz r15,0(r14) /* instruction, now insert top */
- rlwimi r15,r11,16,16,31 /* half of pv const in low half*/
- stw r15,0(r14) /* of instruction and restore. */
- dcbst r0,r14 /* write it to memory */
- sync
- icbi r0,r14 /* flush the icache line */
- cmpw r12,r13
- bne 1b
-
- sync /* additional sync needed on g4 */
- isync /* No speculative loading until now */
- blr
-
-/***********************************************************************
- * Please note that on APUS the exception handlers are located at the
- * physical address 0xfff0000. For this reason, the exception handlers
- * cannot use relative branches to access the code below.
- ***********************************************************************/
-#endif /* CONFIG_APUS */
-
#ifdef CONFIG_SMP
#ifdef CONFIG_GEMINI
.globl __secondary_start_gemini
@@ -1135,19 +1036,6 @@ start_here:
bl __save_cpu_setup
bl MMU_init
-#ifdef CONFIG_APUS
- /* Copy exception code to exception vector base on APUS. */
- lis r4,KERNELBASE@h
-#ifdef CONFIG_APUS_FAST_EXCEPT
- lis r3,0xfff0 /* Copy to 0xfff00000 */
-#else
- lis r3,0 /* Copy to 0x00000000 */
-#endif
- li r5,0x4000 /* # bytes of memory to copy */
- li r6,0
- bl copy_and_flush /* copy the first 0x4000 bytes */
-#endif /* CONFIG_APUS */
-
/*
* Go back to running unmapped so we can load up new values
* for SDR1 (hash table pointer) and the segment registers
@@ -1324,11 +1212,7 @@ initial_bats:
#else
ori r8,r8,2 /* R/W access */
#endif /* CONFIG_SMP */
-#ifdef CONFIG_APUS
- ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */
-#else
ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
-#endif /* CONFIG_APUS */
mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
@@ -1338,7 +1222,7 @@ initial_bats:
blr
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#ifdef CONFIG_BOOTX_TEXT
setup_disp_bat:
/*
* setup the display bat prepared for us in prom.c
@@ -1362,7 +1246,7 @@ setup_disp_bat:
1: mtspr SPRN_IBAT3L,r8
mtspr SPRN_IBAT3U,r11
blr
-#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+#endif /* CONFIG_BOOTX_TEXT */
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 1111fcec7673..8cdd48ea4391 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -103,8 +103,8 @@ __secondary_hold_acknowledge:
. = 0x60
/*
- * The following code is used on pSeries to hold secondary processors
- * in a spin loop after they have been freed from OpenFirmware, but
+ * The following code is used to hold secondary processors
+ * in a spin loop after they have entered the kernel, but
* before the bulk of the kernel has been relocated. This code
* is relocated to physical address 0x60 before prom_init is run.
* All of it must fit below the first exception vector at 0x100.
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c
index 34ae11494ddc..e31aca9208eb 100644
--- a/arch/powerpc/kernel/io.c
+++ b/arch/powerpc/kernel/io.c
@@ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count)
asm volatile("sync");
do {
tmp = *port;
- asm volatile("eieio");
+ eieio();
*tbuf++ = tmp;
} while (--count != 0);
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
asm volatile("sync");
do {
tmp = *port;
- asm volatile("eieio");
+ eieio();
*tbuf++ = tmp;
} while (--count != 0);
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
asm volatile("sync");
do {
tmp = *port;
- asm volatile("eieio");
+ eieio();
*tbuf++ = tmp;
} while (--count != 0);
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src,
__asm__ __volatile__ ("sync" : : : "memory");
while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
- __asm__ __volatile__ ("eieio" : : : "memory");
+ eieio();
vsrc++;
dest++;
n--;
}
while(n > 4) {
*((u32 *)dest) = *((volatile u32 *)vsrc);
- __asm__ __volatile__ ("eieio" : : : "memory");
+ eieio();
vsrc += 4;
dest += 4;
n -= 4;
}
while(n) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
- __asm__ __volatile__ ("eieio" : : : "memory");
+ eieio();
vsrc++;
dest++;
n--;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index c2b84c64db20..2fc87862146c 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -7,7 +7,6 @@
* Copyright (C) 1996-2001 Cort Dougan
* Adapted for Power Macintosh by Paul Mackerras
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -337,7 +336,8 @@ void do_IRQ(struct pt_regs *regs)
void __init init_IRQ(void)
{
- ppc_md.init_IRQ();
+ if (ppc_md.init_IRQ)
+ ppc_md.init_IRQ();
#ifdef CONFIG_PPC64
irq_ctx_init();
#endif
@@ -597,6 +597,49 @@ static void irq_radix_rdunlock(unsigned long flags)
local_irq_restore(flags);
}
+static int irq_setup_virq(struct irq_host *host, unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ /* Clear IRQ_NOREQUEST flag */
+ get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
+
+ /* map it */
+ smp_wmb();
+ irq_map[virq].hwirq = hwirq;
+ smp_mb();
+
+ if (host->ops->map(host, virq, hwirq)) {
+ pr_debug("irq: -> mapping failed, freeing\n");
+ irq_free_virt(virq, 1);
+ return -1;
+ }
+
+ return 0;
+}
+
+unsigned int irq_create_direct_mapping(struct irq_host *host)
+{
+ unsigned int virq;
+
+ if (host == NULL)
+ host = irq_default_host;
+
+ BUG_ON(host == NULL);
+ WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
+
+ virq = irq_alloc_virt(host, 1, 0);
+ if (virq == NO_IRQ) {
+ pr_debug("irq: create_direct virq allocation failed\n");
+ return NO_IRQ;
+ }
+
+ pr_debug("irq: create_direct obtained virq %d\n", virq);
+
+ if (irq_setup_virq(host, virq, virq))
+ return NO_IRQ;
+
+ return virq;
+}
unsigned int irq_create_mapping(struct irq_host *host,
irq_hw_number_t hwirq)
@@ -645,18 +688,9 @@ unsigned int irq_create_mapping(struct irq_host *host,
}
pr_debug("irq: -> obtained virq %d\n", virq);
- /* Clear IRQ_NOREQUEST flag */
- get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
-
- /* map it */
- smp_wmb();
- irq_map[virq].hwirq = hwirq;
- smp_mb();
- if (host->ops->map(host, virq, hwirq)) {
- pr_debug("irq: -> mapping failed, freeing\n");
- irq_free_virt(virq, 1);
+ if (irq_setup_virq(host, virq, hwirq))
return NO_IRQ;
- }
+
return virq;
}
EXPORT_SYMBOL_GPL(irq_create_mapping);
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
new file mode 100644
index 000000000000..f0f49d1be3d5
--- /dev/null
+++ b/arch/powerpc/kernel/isa-bridge.c
@@ -0,0 +1,271 @@
+/*
+ * Routines for tracking a legacy ISA bridge
+ *
+ * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * Some bits and pieces moved over from pci_64.c
+ *
+ * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
+ *
+ * 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.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+unsigned long isa_io_base; /* NULL if no ISA bus */
+EXPORT_SYMBOL(isa_io_base);
+
+/* Cached ISA bridge dev. */
+static struct device_node *isa_bridge_devnode;
+struct pci_dev *isa_bridge_pcidev;
+EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+ unsigned long phb_io_base_phys)
+{
+ /* We should get some saner parsing here and remove these structs */
+ struct pci_address {
+ u32 a_hi;
+ u32 a_mid;
+ u32 a_lo;
+ };
+
+ struct isa_address {
+ u32 a_hi;
+ u32 a_lo;
+ };
+
+ struct isa_range {
+ struct isa_address isa_addr;
+ struct pci_address pci_addr;
+ unsigned int size;
+ };
+
+ const struct isa_range *range;
+ unsigned long pci_addr;
+ unsigned int isa_addr;
+ unsigned int size;
+ int rlen = 0;
+
+ range = of_get_property(isa_node, "ranges", &rlen);
+ if (range == NULL || (rlen < sizeof(struct isa_range)))
+ goto inval_range;
+
+ /* From "ISA Binding to 1275"
+ * The ranges property is laid out as an array of elements,
+ * each of which comprises:
+ * cells 0 - 1: an ISA address
+ * cells 2 - 4: a PCI address
+ * (size depending on dev->n_addr_cells)
+ * cell 5: the size of the range
+ */
+ if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
+ range++;
+ rlen -= sizeof(struct isa_range);
+ if (rlen < sizeof(struct isa_range))
+ goto inval_range;
+ }
+ if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
+ goto inval_range;
+
+ isa_addr = range->isa_addr.a_lo;
+ pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
+ range->pci_addr.a_lo;
+
+ /* Assume these are both zero. Note: We could fix that and
+ * do a proper parsing instead ... oh well, that will do for
+ * now as nobody uses fancy mappings for ISA bridges
+ */
+ if ((pci_addr != 0) || (isa_addr != 0)) {
+ printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+ __FUNCTION__);
+ return;
+ }
+
+ /* Align size and make sure it's cropped to 64K */
+ size = PAGE_ALIGN(range->size);
+ if (size > 0x10000)
+ size = 0x10000;
+
+ printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+ "mapping 64k\n");
+
+ __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+ size, _PAGE_NO_CACHE|_PAGE_GUARDED);
+ return;
+
+inval_range:
+ printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+ "mapping 64k\n");
+ __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+ 0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
+}
+
+
+/**
+ * isa_bridge_find_early - Find and map the ISA IO space early before
+ * main PCI discovery. This is optionally called by
+ * the arch code when adding PCI PHBs to get early
+ * access to ISA IO ports
+ */
+void __init isa_bridge_find_early(struct pci_controller *hose)
+{
+ struct device_node *np, *parent = NULL, *tmp;
+
+ /* If we already have an ISA bridge, bail off */
+ if (isa_bridge_devnode != NULL)
+ return;
+
+ /* For each "isa" node in the system. Note : we do a search by
+ * type and not by name. It might be better to do by name but that's
+ * what the code used to do and I don't want to break too much at
+ * once. We can look into changing that separately
+ */
+ for_each_node_by_type(np, "isa") {
+ /* Look for our hose being a parent */
+ for (parent = of_get_parent(np); parent;) {
+ if (parent == hose->arch_data) {
+ of_node_put(parent);
+ break;
+ }
+ tmp = parent;
+ parent = of_get_parent(parent);
+ of_node_put(tmp);
+ }
+ if (parent != NULL)
+ break;
+ }
+ if (np == NULL)
+ return;
+ isa_bridge_devnode = np;
+
+ /* Now parse the "ranges" property and setup the ISA mapping */
+ pci_process_ISA_OF_ranges(np, hose->io_base_phys);
+
+ /* Set the global ISA io base to indicate we have an ISA bridge */
+ isa_io_base = ISA_IO_BASE;
+
+ pr_debug("ISA bridge (early) is %s\n", np->full_name);
+}
+
+/**
+ * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
+ * a new ISA bridge
+ */
+static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
+ struct device_node *devnode)
+{
+ struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+ /* Store ISA device node and PCI device */
+ isa_bridge_devnode = of_node_get(devnode);
+ isa_bridge_pcidev = pdev;
+
+ /* Now parse the "ranges" property and setup the ISA mapping */
+ pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
+
+ /* Set the global ISA io base to indicate we have an ISA bridge */
+ isa_io_base = ISA_IO_BASE;
+
+ pr_debug("ISA bridge (late) is %s on %s\n",
+ devnode->full_name, pci_name(pdev));
+}
+
+/**
+ * isa_bridge_remove - Remove/unmap an ISA bridge
+ */
+static void isa_bridge_remove(void)
+{
+ pr_debug("ISA bridge removed !\n");
+
+ /* Clear the global ISA io base to indicate that we have no more
+ * ISA bridge. Note that drivers don't quite handle that, though
+ * we should probably do something about it. But do we ever really
+ * have ISA bridges being removed on machines using legacy devices ?
+ */
+ isa_io_base = ISA_IO_BASE;
+
+ /* Clear references to the bridge */
+ of_node_put(isa_bridge_devnode);
+ isa_bridge_devnode = NULL;
+ isa_bridge_pcidev = NULL;
+
+ /* Unmap the ISA area */
+ __iounmap_at((void *)ISA_IO_BASE, 0x10000);
+}
+
+/**
+ * isa_bridge_notify - Get notified of PCI devices addition/removal
+ */
+static int __devinit isa_bridge_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct device_node *devnode = pci_device_to_OF_node(pdev);
+
+ switch(action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ /* Check if we have an early ISA device, without PCI dev */
+ if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
+ !isa_bridge_pcidev) {
+ pr_debug("ISA bridge PCI attached: %s\n",
+ pci_name(pdev));
+ isa_bridge_pcidev = pdev;
+ }
+
+ /* Check if we have no ISA device, and this happens to be one,
+ * register it as such if it has an OF device
+ */
+ if (!isa_bridge_devnode && devnode && devnode->type &&
+ !strcmp(devnode->type, "isa"))
+ isa_bridge_find_late(pdev, devnode);
+
+ return 0;
+ case BUS_NOTIFY_DEL_DEVICE:
+ /* Check if this our existing ISA device */
+ if (pdev == isa_bridge_pcidev ||
+ (devnode && devnode == isa_bridge_devnode))
+ isa_bridge_remove();
+ return 0;
+ }
+ return 0;
+}
+
+static struct notifier_block isa_bridge_notifier = {
+ .notifier_call = isa_bridge_notify
+};
+
+/**
+ * isa_bridge_init - register to be notified of ISA bridge addition/removal
+ *
+ */
+static int __init isa_bridge_init(void)
+{
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+ bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
+ return 0;
+}
+arch_initcall(isa_bridge_init);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 98decf8ebff4..e708ab7ca9e8 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -392,7 +392,7 @@ BEGIN_FTR_SECTION
mtspr SPRN_L1CSR0,r3
isync
blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
mfspr r3,SPRN_L1CSR1
ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
mtspr SPRN_L1CSR1,r3
@@ -419,7 +419,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
_GLOBAL(__flush_icache_range)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
li r5,L1_CACHE_BYTES-1
andc r3,r3,r5
subf r4,r3,r4
@@ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range)
*/
_GLOBAL(__flush_dcache_icache)
BEGIN_FTR_SECTION
- blr /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+ blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
mtctr r4
@@ -543,7 +543,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
_GLOBAL(__flush_dcache_icache_phys)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
mfmsr r10
rlwinm r0,r10,0,28,26 /* clear DR */
mtmsr r0
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 519861da0423..bbb3ba54c51c 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -646,6 +646,19 @@ _GLOBAL(kexec_sequence)
/* turn off mmu */
bl real_mode
+ /* copy 0x100 bytes starting at start to 0 */
+ li r3,0
+ mr r4,r30 /* start, aka phys mem offset */
+ li r5,0x100
+ li r6,0
+ bl .copy_and_flush /* (dest, src, copy limit, start offset) */
+1: /* assume normal blr return */
+
+ /* release other cpus to the new kernel secondary start at 0x60 */
+ mflr r5
+ li r6,1
+ stw r6,kexec_flag-1b(5)
+
/* clear out hardware hash page table and tlb */
ld r5,0(r27) /* deref function descriptor */
mtctr r5
@@ -676,19 +689,6 @@ _GLOBAL(kexec_sequence)
* are the boot cpu ?????
* other device tree differences (prop sizes, va vs pa, etc)...
*/
-
- /* copy 0x100 bytes starting at start to 0 */
- li r3,0
- mr r4,r30
- li r5,0x100
- li r6,0
- bl .copy_and_flush /* (dest, src, copy limit, start offset) */
-1: /* assume normal blr return */
-
- /* release other cpus to the new kernel secondary start at 0x60 */
- mflr r5
- li r6,1
- stw r6,kexec_flag-1b(5)
mr r3,r25 # my phys cpu
mr r4,r30 # start, aka phys mem offset
mtlr 4
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index d454f61c9c7c..9536ed7f247c 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -427,14 +427,6 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
/* Process "ranges" property */
pci_process_bridge_OF_ranges(phb, dev->node, 0);
- /* Setup IO space. We use the non-dynamic version of that code here,
- * which doesn't quite support unplugging. Next kernel release will
- * have a better fix for this.
- * Note also that we don't do ISA, this will also be fixed with a
- * more massive rework.
- */
- pci_setup_phb_io(phb, pci_io_base == 0);
-
/* Init pci_dn data structures */
pci_devs_phb_init_dynamic(phb);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
new file mode 100644
index 000000000000..faf5ef3e90d0
--- /dev/null
+++ b/arch/powerpc/kernel/pci-common.c
@@ -0,0 +1,454 @@
+/*
+ * Contains common pci routines for ALL ppc platform
+ * (based on pci_32.c and pci_64.c)
+ *
+ * Port for PPC64 David Engebretsen, IBM Corp.
+ * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
+ *
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Rework, based on alpha PCI code.
+ *
+ * Common pmac/prep/chrp pci routines. -- Cort
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/syscalls.h>
+#include <linux/irq.h>
+#include <linux/vmalloc.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static DEFINE_SPINLOCK(hose_spinlock);
+
+/* XXX kill that some day ... */
+int global_phb_number; /* Global phb counter */
+
+extern struct list_head hose_list;
+
+/*
+ * pci_controller(phb) initialized common variables.
+ */
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+{
+ memset(hose, 0, sizeof(struct pci_controller));
+
+ spin_lock(&hose_spinlock);
+ hose->global_number = global_phb_number++;
+ list_add_tail(&hose->list_node, &hose_list);
+ spin_unlock(&hose_spinlock);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+ struct pci_controller *phb;
+
+ if (mem_init_done)
+ phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+ else
+ phb = alloc_bootmem(sizeof (struct pci_controller));
+ if (phb == NULL)
+ return NULL;
+ pci_setup_pci_controller(phb);
+ phb->arch_data = dev;
+ phb->is_dynamic = mem_init_done;
+#ifdef CONFIG_PPC64
+ if (dev) {
+ int nid = of_node_to_nid(dev);
+
+ if (nid < 0 || !node_online(nid))
+ nid = -1;
+
+ PHB_SET_NODE(phb, nid);
+ }
+#endif
+ return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+ spin_lock(&hose_spinlock);
+ list_del(&phb->list_node);
+ spin_unlock(&hose_spinlock);
+
+ if (phb->is_dynamic)
+ kfree(phb);
+}
+
+/*
+ * Return the domain number for this bus.
+ */
+int pci_domain_nr(struct pci_bus *bus)
+{
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+ else {
+ struct pci_controller *hose = pci_bus_to_host(bus);
+
+ return hose->global_number;
+ }
+}
+
+EXPORT_SYMBOL(pci_domain_nr);
+
+#ifdef CONFIG_PPC_OF
+
+/* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+ * to set pci_assign_all_buses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+ if (!have_of)
+ return NULL;
+ while(node) {
+ struct pci_controller *hose, *tmp;
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ if (hose->arch_data == node)
+ return hose;
+ node = node->parent;
+ }
+ return NULL;
+}
+
+static ssize_t pci_show_devspec(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev;
+ struct device_node *np;
+
+ pdev = to_pci_dev (dev);
+ np = pci_device_to_OF_node(pdev);
+ if (np == NULL || np->full_name == NULL)
+ return 0;
+ return sprintf(buf, "%s", np->full_name);
+}
+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+#endif /* CONFIG_PPC_OF */
+
+/* Add sysfs properties */
+void pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PPC_OF
+ device_create_file(&pdev->dev, &dev_attr_devspec);
+#endif /* CONFIG_PPC_OF */
+}
+
+char __init *pcibios_setup(char *str)
+{
+ return str;
+}
+
+/*
+ * Reads the interrupt pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ */
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+ struct of_irq oirq;
+ unsigned int virq;
+
+ DBG("Try to map irq for %s...\n", pci_name(pci_dev));
+
+#ifdef DEBUG
+ memset(&oirq, 0xff, sizeof(oirq));
+#endif
+ /* Try to get a mapping from the device-tree */
+ if (of_irq_map_pci(pci_dev, &oirq)) {
+ u8 line, pin;
+
+ /* If that fails, lets fallback to what is in the config
+ * space and map that through the default controller. We
+ * also set the type to level low since that's what PCI
+ * interrupts are. If your platform does differently, then
+ * either provide a proper interrupt tree or don't use this
+ * function.
+ */
+ if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+ return -1;
+ if (pin == 0)
+ return -1;
+ if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+ line == 0xff) {
+ return -1;
+ }
+ DBG(" -> no map ! Using irq line %d from PCI config\n", line);
+
+ virq = irq_create_mapping(NULL, line);
+ if (virq != NO_IRQ)
+ set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+ } else {
+ DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+ oirq.size, oirq.specifier[0], oirq.specifier[1],
+ oirq.controller->full_name);
+
+ virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+ oirq.size);
+ }
+ if(virq == NO_IRQ) {
+ DBG(" -> failed to map !\n");
+ return -1;
+ }
+
+ DBG(" -> mapped to linux irq %d\n", virq);
+
+ pci_dev->irq = virq;
+
+ return 0;
+}
+EXPORT_SYMBOL(pci_read_irq_line);
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ * -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap. They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+ resource_size_t *offset,
+ enum pci_mmap_state mmap_state)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ unsigned long io_offset = 0;
+ int i, res_bit;
+
+ if (hose == 0)
+ return NULL; /* should never happen */
+
+ /* If memory, add on the PCI bridge address offset */
+ if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
+ *offset += hose->pci_mem_offset;
+#endif
+ res_bit = IORESOURCE_MEM;
+ } else {
+ io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ *offset += io_offset;
+ res_bit = IORESOURCE_IO;
+ }
+
+ /*
+ * Check that the offset requested corresponds to one of the
+ * resources of the device.
+ */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &dev->resource[i];
+ int flags = rp->flags;
+
+ /* treat ROM as memory (should be already) */
+ if (i == PCI_ROM_RESOURCE)
+ flags |= IORESOURCE_MEM;
+
+ /* Active and same type? */
+ if ((flags & res_bit) == 0)
+ continue;
+
+ /* In the range of this resource? */
+ if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
+ continue;
+
+ /* found it! construct the final physical address */
+ if (mmap_state == pci_mmap_io)
+ *offset += hose->io_base_phys - io_offset;
+ return rp;
+ }
+
+ return NULL;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
+ pgprot_t protection,
+ enum pci_mmap_state mmap_state,
+ int write_combine)
+{
+ unsigned long prot = pgprot_val(protection);
+
+ /* Write combine is always 0 on non-memory space mappings. On
+ * memory space, if the user didn't pass 1, we check for a
+ * "prefetchable" resource. This is a bit hackish, but we use
+ * this to workaround the inability of /sysfs to provide a write
+ * combine bit
+ */
+ if (mmap_state != pci_mmap_mem)
+ write_combine = 0;
+ else if (write_combine == 0) {
+ if (rp->flags & IORESOURCE_PREFETCH)
+ write_combine = 1;
+ }
+
+ /* XXX would be nice to have a way to ask for write-through */
+ prot |= _PAGE_NO_CACHE;
+ if (write_combine)
+ prot &= ~_PAGE_GUARDED;
+ else
+ prot |= _PAGE_GUARDED;
+
+ return __pgprot(prot);
+}
+
+/*
+ * This one is used by /dev/mem and fbdev who have no clue about the
+ * PCI device, it tries to find the PCI device first and calls the
+ * above routine
+ */
+pgprot_t pci_phys_mem_access_prot(struct file *file,
+ unsigned long pfn,
+ unsigned long size,
+ pgprot_t protection)
+{
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
+ unsigned long offset = pfn << PAGE_SHIFT;
+ int i;
+
+ if (page_is_ram(pfn))
+ return __pgprot(prot);
+
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+ for_each_pci_dev(pdev) {
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &pdev->resource[i];
+ int flags = rp->flags;
+
+ /* Active and same type? */
+ if ((flags & IORESOURCE_MEM) == 0)
+ continue;
+ /* In the range of this resource? */
+ if (offset < (rp->start & PAGE_MASK) ||
+ offset > rp->end)
+ continue;
+ found = rp;
+ break;
+ }
+ if (found)
+ break;
+ }
+ if (found) {
+ if (found->flags & IORESOURCE_PREFETCH)
+ prot &= ~_PAGE_GUARDED;
+ pci_dev_put(pdev);
+ }
+
+ DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
+
+ return __pgprot(prot);
+}
+
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture. The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
+ struct resource *rp;
+ int ret;
+
+ rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+ if (rp == NULL)
+ return -EINVAL;
+
+ vma->vm_pgoff = offset >> PAGE_SHIFT;
+ vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
+ vma->vm_page_prot,
+ mmap_state, write_combine);
+
+ ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+ return ret;
+}
+
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ resource_size_t *start, resource_size_t *end)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ resource_size_t offset = 0;
+
+ if (hose == NULL)
+ return;
+
+ if (rsrc->flags & IORESOURCE_IO)
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+ /* We pass a fully fixed up address to userland for MMIO instead of
+ * a BAR value because X is lame and expects to be able to use that
+ * to pass to /dev/mem !
+ *
+ * That means that we'll have potentially 64 bits values where some
+ * userland apps only expect 32 (like X itself since it thinks only
+ * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+ * 32 bits CHRPs :-(
+ *
+ * Hopefully, the sysfs insterface is immune to that gunk. Once X
+ * has been fixed (and the fix spread enough), we can re-enable the
+ * 2 lines below and pass down a BAR value to userland. In that case
+ * we'll also have to re-enable the matching code in
+ * __pci_mmap_make_offset().
+ *
+ * BenH.
+ */
+#if 0
+ else if (rsrc->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+#endif
+
+ *start = rsrc->start - offset;
+ *end = rsrc->end - offset;
+}
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 86982112b0dd..0adf077f3f3a 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -55,8 +55,7 @@ static u8* pci_to_OF_bus_map;
*/
int pci_assign_all_buses;
-struct pci_controller* hose_head;
-struct pci_controller** hose_tail = &hose_head;
+LIST_HEAD(hose_list);
static int pci_bus_count;
@@ -573,58 +572,6 @@ pcibios_assign_resources(void)
}
}
-
-int
-pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
- u16 cmd, old_cmd;
- int idx;
- struct resource *r;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for (idx=0; idx<6; idx++) {
- /* Only set up the requested stuff */
- if (!(mask & (1<<idx)))
- continue;
-
- r = &dev->resource[idx];
- if (r->flags & IORESOURCE_UNSET) {
- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (dev->resource[PCI_ROM_RESOURCE].start)
- cmd |= PCI_COMMAND_MEMORY;
- if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- return 0;
-}
-
-static int next_controller_index;
-
-struct pci_controller * __init
-pcibios_alloc_controller(void)
-{
- struct pci_controller *hose;
-
- hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
- memset(hose, 0, sizeof(struct pci_controller));
-
- *hose_tail = hose;
- hose_tail = &hose->next;
-
- hose->index = next_controller_index++;
-
- return hose;
-}
-
#ifdef CONFIG_PPC_OF
/*
* Functions below are used on OpenFirmware machines.
@@ -670,7 +617,7 @@ void
pcibios_make_OF_bus_map(void)
{
int i;
- struct pci_controller* hose;
+ struct pci_controller *hose, *tmp;
struct property *map_prop;
struct device_node *dn;
@@ -687,7 +634,7 @@ pcibios_make_OF_bus_map(void)
pci_to_OF_bus_map[i] = 0xff;
/* For each hose, we begin searching bridges */
- for(hose=hose_head; hose; hose=hose->next) {
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
struct device_node* node;
node = (struct device_node *)hose->arch_data;
if (!node)
@@ -765,7 +712,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
/* Are we a root bus ? */
if (bus->self == NULL || bus->parent == NULL) {
- struct pci_controller *hose = pci_bus_to_hose(bus->number);
+ struct pci_controller *hose = pci_bus_to_host(bus);
if (hose == NULL)
return NULL;
return of_node_get(hose->arch_data);
@@ -818,27 +765,6 @@ pci_device_to_OF_node(struct pci_dev *dev)
}
EXPORT_SYMBOL(pci_device_to_OF_node);
-/* This routine is meant to be used early during boot, when the
- * PCI bus numbers have not yet been assigned, and you need to
- * issue PCI config cycles to an OF device.
- * It could also be used to "fix" RTAS config cycles if you want
- * to set pci_assign_all_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
- if (!have_of)
- return NULL;
- while(node) {
- struct pci_controller* hose;
- for (hose=hose_head;hose;hose=hose->next)
- if (hose->arch_data == node)
- return hose;
- node=node->parent;
- }
- return NULL;
-}
-
static int
find_OF_pci_device_filter(struct device_node* node, void* data)
{
@@ -1027,34 +953,12 @@ pci_create_OF_bus_map(void)
}
}
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct pci_dev *pdev;
- struct device_node *np;
-
- pdev = to_pci_dev (dev);
- np = pci_device_to_OF_node(pdev);
- if (np == NULL || np->full_name == NULL)
- return 0;
- return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
#else /* CONFIG_PPC_OF */
void pcibios_make_OF_bus_map(void)
{
}
#endif /* CONFIG_PPC_OF */
-/* Add sysfs properties */
-int pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-#ifdef CONFIG_PPC_OF
- return device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_OF */
-}
-
-
#ifdef CONFIG_PPC_PMAC
/*
* This set of routines checks for PCI<->PCI bridges that have closed
@@ -1269,14 +1173,14 @@ pcibios_fixup_p2p_bridges(void)
static int __init
pcibios_init(void)
{
- struct pci_controller *hose;
+ struct pci_controller *hose, *tmp;
struct pci_bus *bus;
- int next_busno;
+ int next_busno = 0;
printk(KERN_INFO "PCI: Probing PCI hardware\n");
/* Scan all of the recorded PCI controllers. */
- for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
if (pci_assign_all_buses)
hose->first_busno = next_busno;
hose->last_busno = 0xff;
@@ -1319,12 +1223,6 @@ pcibios_init(void)
subsys_initcall(pcibios_init);
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
- unsigned long start, unsigned long size)
-{
- return start;
-}
-
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -1342,7 +1240,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
if (!res->flags) {
if (io_offset)
printk(KERN_ERR "I/O resource not set for host"
- " bridge %d\n", hose->index);
+ " bridge %d\n", hose->global_number);
res->start = 0;
res->end = IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
@@ -1356,7 +1254,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
if (i > 0)
continue;
printk(KERN_ERR "Memory resource not set for "
- "host bridge %d\n", hose->index);
+ "host bridge %d\n", hose->global_number);
res->start = hose->pci_mem_offset;
res->end = ~0U;
res->flags = IORESOURCE_MEM;
@@ -1370,7 +1268,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
for (i = 0; i < 4; ++i) {
if ((res = bus->resource[i]) == NULL)
continue;
- if (!res->flags)
+ if (!res->flags || bus->self->transparent)
continue;
if (io_offset && (res->flags & IORESOURCE_IO)) {
res->start += io_offset;
@@ -1395,11 +1293,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
}
}
-char __init *pcibios_setup(char *str)
-{
- return str;
-}
-
/* the next one is stolen from the alpha port... */
void __init
pcibios_update_irq(struct pci_dev *dev, int irq)
@@ -1408,64 +1301,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
/* XXX FIXME - update OF device tree node interrupt property */
}
-#ifdef CONFIG_PPC_MERGE
-/* XXX This is a copy of the ppc64 version. This is temporary until we start
- * merging the 2 PCI layers
- */
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
- struct of_irq oirq;
- unsigned int virq;
-
- DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
- /* Try to get a mapping from the device-tree */
- if (of_irq_map_pci(pci_dev, &oirq)) {
- u8 line, pin;
-
- /* If that fails, lets fallback to what is in the config
- * space and map that through the default controller. We
- * also set the type to level low since that's what PCI
- * interrupts are. If your platform does differently, then
- * either provide a proper interrupt tree or don't use this
- * function.
- */
- if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
- return -1;
- if (pin == 0)
- return -1;
- if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
- line == 0xff) {
- return -1;
- }
- DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
- virq = irq_create_mapping(NULL, line);
- if (virq != NO_IRQ)
- set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
- } else {
- DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
- oirq.size, oirq.specifier[0], oirq.controller->full_name);
-
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
- }
- if(virq == NO_IRQ) {
- DBG(" -> failed to map !\n");
- return -1;
- }
- pci_dev->irq = virq;
-
- return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-#endif /* CONFIG_PPC_MERGE */
-
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
@@ -1497,281 +1332,17 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}
-struct pci_controller*
+static struct pci_controller*
pci_bus_to_hose(int bus)
{
- struct pci_controller* hose = hose_head;
+ struct pci_controller *hose, *tmp;
- for (; hose; hose = hose->next)
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
if (bus >= hose->first_busno && bus <= hose->last_busno)
return hose;
return NULL;
}
-void __iomem *
-pci_bus_io_base(unsigned int bus)
-{
- struct pci_controller *hose;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return NULL;
- return hose->io_base_virt;
-}
-
-unsigned long
-pci_bus_io_base_phys(unsigned int bus)
-{
- struct pci_controller *hose;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return 0;
- return hose->io_base_phys;
-}
-
-unsigned long
-pci_bus_mem_base_phys(unsigned int bus)
-{
- struct pci_controller *hose;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return 0;
- return hose->pci_mem_offset;
-}
-
-unsigned long
-pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
-{
- /* Hack alert again ! See comments in chrp_pci.c
- */
- struct pci_controller* hose =
- (struct pci_controller *)pdev->sysdata;
- if (hose && res->flags & IORESOURCE_MEM)
- return res->start - hose->pci_mem_offset;
- /* We may want to do something with IOs here... */
- return res->start;
-}
-
-
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- resource_size_t *offset,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- unsigned long io_offset = 0;
- int i, res_bit;
-
- if (hose == 0)
- return NULL; /* should never happen */
-
- /* If memory, add on the PCI bridge address offset */
- if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
- *offset += hose->pci_mem_offset;
-#endif
- res_bit = IORESOURCE_MEM;
- } else {
- io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
- *offset += io_offset;
- res_bit = IORESOURCE_IO;
- }
-
- /*
- * Check that the offset requested corresponds to one of the
- * resources of the device.
- */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &dev->resource[i];
- int flags = rp->flags;
-
- /* treat ROM as memory (should be already) */
- if (i == PCI_ROM_RESOURCE)
- flags |= IORESOURCE_MEM;
-
- /* Active and same type? */
- if ((flags & res_bit) == 0)
- continue;
-
- /* In the range of this resource? */
- if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
- continue;
-
- /* found it! construct the final physical address */
- if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - io_offset;
- return rp;
- }
-
- return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
- pgprot_t protection,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
- unsigned long prot = pgprot_val(protection);
-
- /* Write combine is always 0 on non-memory space mappings. On
- * memory space, if the user didn't pass 1, we check for a
- * "prefetchable" resource. This is a bit hackish, but we use
- * this to workaround the inability of /sysfs to provide a write
- * combine bit
- */
- if (mmap_state != pci_mmap_mem)
- write_combine = 0;
- else if (write_combine == 0) {
- if (rp->flags & IORESOURCE_PREFETCH)
- write_combine = 1;
- }
-
- /* XXX would be nice to have a way to ask for write-through */
- prot |= _PAGE_NO_CACHE;
- if (write_combine)
- prot &= ~_PAGE_GUARDED;
- else
- prot |= _PAGE_GUARDED;
-
- return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
- unsigned long pfn,
- unsigned long size,
- pgprot_t protection)
-{
- struct pci_dev *pdev = NULL;
- struct resource *found = NULL;
- unsigned long prot = pgprot_val(protection);
- unsigned long offset = pfn << PAGE_SHIFT;
- int i;
-
- if (page_is_ram(pfn))
- return __pgprot(prot);
-
- prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
- for_each_pci_dev(pdev) {
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &pdev->resource[i];
- int flags = rp->flags;
-
- /* Active and same type? */
- if ((flags & IORESOURCE_MEM) == 0)
- continue;
- /* In the range of this resource? */
- if (offset < (rp->start & PAGE_MASK) ||
- offset > rp->end)
- continue;
- found = rp;
- break;
- }
- if (found)
- break;
- }
- if (found) {
- if (found->flags & IORESOURCE_PREFETCH)
- prot &= ~_PAGE_GUARDED;
- pci_dev_put(pdev);
- }
-
- DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
- return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture. The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
- resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
- struct resource *rp;
- int ret;
-
- rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
- if (rp == NULL)
- return -EINVAL;
-
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
- vma->vm_page_prot,
- mmap_state, write_combine);
-
- ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
- return ret;
-}
-
-/* Obsolete functions. Should be removed once the symbios driver
- * is fixed
- */
-unsigned long
-phys_to_bus(unsigned long pa)
-{
- struct pci_controller *hose;
- int i;
-
- for (hose = hose_head; hose; hose = hose->next) {
- for (i = 0; i < 3; ++i) {
- if (pa >= hose->mem_resources[i].start
- && pa <= hose->mem_resources[i].end) {
- /*
- * XXX the hose->pci_mem_offset really
- * only applies to mem_resources[0].
- * We need a way to store an offset for
- * the others. -- paulus
- */
- if (i == 0)
- pa -= hose->pci_mem_offset;
- return pa;
- }
- }
- }
- /* hmmm, didn't find it */
- return 0;
-}
-
-unsigned long
-pci_phys_to_bus(unsigned long pa, int busnr)
-{
- struct pci_controller* hose = pci_bus_to_hose(busnr);
- if (!hose)
- return pa;
- return pa - hose->pci_mem_offset;
-}
-
-unsigned long
-pci_bus_to_phys(unsigned int ba, int busnr)
-{
- struct pci_controller* hose = pci_bus_to_hose(busnr);
- if (!hose)
- return ba;
- return ba + hose->pci_mem_offset;
-}
-
/* Provide information on locations of various I/O regions in physical
* memory. Do this on a per-card basis so that we choose the right
* root bridge.
@@ -1814,62 +1385,11 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
return result;
}
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
- const struct resource *rsrc,
- resource_size_t *start, resource_size_t *end)
-{
- struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- resource_size_t offset = 0;
-
- if (hose == NULL)
- return;
-
- if (rsrc->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
- /* We pass a fully fixed up address to userland for MMIO instead of
- * a BAR value because X is lame and expects to be able to use that
- * to pass to /dev/mem !
- *
- * That means that we'll have potentially 64 bits values where some
- * userland apps only expect 32 (like X itself since it thinks only
- * Sparc has 64 bits MMIO) but if we don't do that, we break it on
- * 32 bits CHRPs :-(
- *
- * Hopefully, the sysfs insterface is immune to that gunk. Once X
- * has been fixed (and the fix spread enough), we can re-enable the
- * 2 lines below and pass down a BAR value to userland. In that case
- * we'll also have to re-enable the matching code in
- * __pci_mmap_make_offset().
- *
- * BenH.
- */
-#if 0
- else if (rsrc->flags & IORESOURCE_MEM)
- offset = hose->pci_mem_offset;
-#endif
-
- *start = rsrc->start - offset;
- *end = rsrc->end - offset;
-}
-
-void __init pci_init_resource(struct resource *res, resource_size_t start,
- resource_size_t end, int flags, char *name)
-{
- res->start = start;
- res->end = end;
- res->flags = flags;
- res->name = name;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
-}
-
unsigned long pci_address_to_pio(phys_addr_t address)
{
- struct pci_controller* hose = hose_head;
+ struct pci_controller *hose, *tmp;
- for (; hose; hose = hose->next) {
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
unsigned int size = hose->io_resource.end -
hose->io_resource.start + 1;
if (address >= hose->io_base_phys &&
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index e3009a43ac56..a97e23ac1976 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -22,6 +22,7 @@
#include <linux/list.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
+#include <linux/vmalloc.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -41,35 +42,23 @@
unsigned long pci_probe_only = 1;
int pci_assign_all_buses = 0;
-static int pci_initial_scan_done;
static void fixup_resource(struct resource *res, struct pci_dev *dev);
static void do_bus_setup(struct pci_bus *bus);
-static void phbs_remap_io(void);
/* pci_io_base -- the base address from which io bars are offsets.
* This is the lowest I/O base address (so bar values are always positive),
* and it *must* be the start of ISA space if an ISA bus exists because
- * ISA drivers use hard coded offsets. If no ISA bus exists a dummy
- * page is mapped and isa_io_limit prevents access to it.
+ * ISA drivers use hard coded offsets. If no ISA bus exists nothing
+ * is mapped on the first 64K of IO space
*/
-unsigned long isa_io_base; /* NULL if no ISA bus */
-EXPORT_SYMBOL(isa_io_base);
-unsigned long pci_io_base;
+unsigned long pci_io_base = ISA_IO_BASE;
EXPORT_SYMBOL(pci_io_base);
-void iSeries_pcibios_init(void);
-
LIST_HEAD(hose_list);
static struct dma_mapping_ops *pci_dma_ops;
-int global_phb_number; /* Global phb counter */
-
-/* Cached ISA bridge dev. */
-struct pci_dev *ppc64_isabridge_dev = NULL;
-EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
-
void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
{
pci_dma_ops = dma_ops;
@@ -100,7 +89,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region
return;
if (res->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - pci_io_base;
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
if (res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
@@ -119,7 +108,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
return;
if (res->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - pci_io_base;
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
if (res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
@@ -156,7 +145,7 @@ void pcibios_align_resource(void *data, struct resource *res,
if (res->flags & IORESOURCE_IO) {
unsigned long offset = (unsigned long)hose->io_base_virt -
- pci_io_base;
+ _IO_BASE;
/* Make sure we start at our min on all hoses */
if (start - offset < PCIBIOS_MIN_IO)
start = PCIBIOS_MIN_IO + offset;
@@ -180,55 +169,6 @@ void pcibios_align_resource(void *data, struct resource *res,
res->start = start;
}
-static DEFINE_SPINLOCK(hose_spinlock);
-
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
- memset(hose, 0, sizeof(struct pci_controller));
-
- spin_lock(&hose_spinlock);
- hose->global_number = global_phb_number++;
- list_add_tail(&hose->list_node, &hose_list);
- spin_unlock(&hose_spinlock);
-}
-
-struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
-{
- struct pci_controller *phb;
-
- if (mem_init_done)
- phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
- else
- phb = alloc_bootmem(sizeof (struct pci_controller));
- if (phb == NULL)
- return NULL;
- pci_setup_pci_controller(phb);
- phb->arch_data = dev;
- phb->is_dynamic = mem_init_done;
- if (dev) {
- int nid = of_node_to_nid(dev);
-
- if (nid < 0 || !node_online(nid))
- nid = -1;
-
- PHB_SET_NODE(phb, nid);
- }
- return phb;
-}
-
-void pcibios_free_controller(struct pci_controller *phb)
-{
- spin_lock(&hose_spinlock);
- list_del(&phb->list_node);
- spin_unlock(&hose_spinlock);
-
- if (phb->is_dynamic)
- kfree(phb);
-}
-
void __devinit pcibios_claim_one_bus(struct pci_bus *b)
{
struct pci_dev *dev;
@@ -291,7 +231,6 @@ static unsigned int pci_parse_of_flags(u32 addr0)
return flags;
}
-#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
{
@@ -310,8 +249,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
flags = pci_parse_of_flags(addrs[0]);
if (!flags)
continue;
- base = GET_64BIT(addrs, 1);
- size = GET_64BIT(addrs, 3);
+ base = of_read_number(&addrs[1], 2);
+ size = of_read_number(&addrs[3], 2);
if (!size)
continue;
i = addrs[0] & 0xff;
@@ -479,7 +418,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
flags = pci_parse_of_flags(ranges[0]);
- size = GET_64BIT(ranges, 6);
+ size = of_read_number(&ranges[6], 2);
if (flags == 0 || size == 0)
continue;
if (flags & IORESOURCE_IO) {
@@ -498,7 +437,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
res = bus->resource[i];
++i;
}
- res->start = GET_64BIT(ranges, 1);
+ res->start = of_read_number(&ranges[1], 2);
res->end = res->start + size - 1;
res->flags = flags;
fixup_resource(res, dev);
@@ -537,10 +476,16 @@ void __devinit scan_phb(struct pci_controller *hose)
bus->secondary = hose->first_busno;
hose->bus = bus;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ pcibios_map_io_space(bus);
+
bus->resource[0] = res = &hose->io_resource;
- if (res->flags && request_resource(&ioport_resource, res))
+ if (res->flags && request_resource(&ioport_resource, res)) {
printk(KERN_ERR "Failed to request PCI IO region "
"on PCI domain %04x\n", hose->global_number);
+ DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
+ res->start, res->end);
+ }
for (i = 0; i < 3; ++i) {
res = &hose->mem_resources[i];
@@ -598,17 +543,6 @@ static int __init pcibios_init(void)
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
- /* Cache the location of the ISA bridge (if we have one) */
- ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
- if (ppc64_isabridge_dev != NULL)
- printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
-
- if (!firmware_has_feature(FW_FEATURE_ISERIES))
- /* map in PCI I/O space */
- phbs_remap_io();
-
- pci_initial_scan_done = 1;
-
printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
return 0;
@@ -616,11 +550,6 @@ static int __init pcibios_init(void)
subsys_initcall(pcibios_init);
-char __init *pcibios_setup(char *str)
-{
- return str;
-}
-
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, oldcmd;
@@ -651,22 +580,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}
-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- return 0;
- else {
- struct pci_controller *hose = pci_bus_to_host(bus);
-
- return hose->global_number;
- }
-}
-
-EXPORT_SYMBOL(pci_domain_nr);
-
/* Decide whether to display the domain number in /proc */
int pci_proc_domain(struct pci_bus *bus)
{
@@ -678,281 +591,6 @@ int pci_proc_domain(struct pci_bus *bus)
}
}
-/*
- * Platform support for /proc/bus/pci/X/Y mmap()s,
- * modelled on the sparc64 implementation by Dave Miller.
- * -- paulus.
- */
-
-/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap. They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- resource_size_t *offset,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned long io_offset = 0;
- int i, res_bit;
-
- if (hose == 0)
- return NULL; /* should never happen */
-
- /* If memory, add on the PCI bridge address offset */
- if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
- *offset += hose->pci_mem_offset;
-#endif
- res_bit = IORESOURCE_MEM;
- } else {
- io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
- *offset += io_offset;
- res_bit = IORESOURCE_IO;
- }
-
- /*
- * Check that the offset requested corresponds to one of the
- * resources of the device.
- */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &dev->resource[i];
- int flags = rp->flags;
-
- /* treat ROM as memory (should be already) */
- if (i == PCI_ROM_RESOURCE)
- flags |= IORESOURCE_MEM;
-
- /* Active and same type? */
- if ((flags & res_bit) == 0)
- continue;
-
- /* In the range of this resource? */
- if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
- continue;
-
- /* found it! construct the final physical address */
- if (mmap_state == pci_mmap_io)
- *offset += hose->io_base_phys - io_offset;
- return rp;
- }
-
- return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
- pgprot_t protection,
- enum pci_mmap_state mmap_state,
- int write_combine)
-{
- unsigned long prot = pgprot_val(protection);
-
- /* Write combine is always 0 on non-memory space mappings. On
- * memory space, if the user didn't pass 1, we check for a
- * "prefetchable" resource. This is a bit hackish, but we use
- * this to workaround the inability of /sysfs to provide a write
- * combine bit
- */
- if (mmap_state != pci_mmap_mem)
- write_combine = 0;
- else if (write_combine == 0) {
- if (rp->flags & IORESOURCE_PREFETCH)
- write_combine = 1;
- }
-
- /* XXX would be nice to have a way to ask for write-through */
- prot |= _PAGE_NO_CACHE;
- if (write_combine)
- prot &= ~_PAGE_GUARDED;
- else
- prot |= _PAGE_GUARDED;
-
- return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
- unsigned long pfn,
- unsigned long size,
- pgprot_t protection)
-{
- struct pci_dev *pdev = NULL;
- struct resource *found = NULL;
- unsigned long prot = pgprot_val(protection);
- unsigned long offset = pfn << PAGE_SHIFT;
- int i;
-
- if (page_is_ram(pfn))
- return __pgprot(prot);
-
- prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
- for_each_pci_dev(pdev) {
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *rp = &pdev->resource[i];
- int flags = rp->flags;
-
- /* Active and same type? */
- if ((flags & IORESOURCE_MEM) == 0)
- continue;
- /* In the range of this resource? */
- if (offset < (rp->start & PAGE_MASK) ||
- offset > rp->end)
- continue;
- found = rp;
- break;
- }
- if (found)
- break;
- }
- if (found) {
- if (found->flags & IORESOURCE_PREFETCH)
- prot &= ~_PAGE_GUARDED;
- pci_dev_put(pdev);
- }
-
- DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
- return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture. The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine)
-{
- resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
- struct resource *rp;
- int ret;
-
- rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
- if (rp == NULL)
- return -EINVAL;
-
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
- vma->vm_page_prot,
- mmap_state, write_combine);
-
- ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
- return ret;
-}
-
-static ssize_t pci_show_devspec(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pci_dev *pdev;
- struct device_node *np;
-
- pdev = to_pci_dev (dev);
- np = pci_device_to_OF_node(pdev);
- if (np == NULL || np->full_name == NULL)
- return 0;
- return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
-int pcibios_add_platform_entries(struct pci_dev *pdev)
-{
- return device_create_file(&pdev->dev, &dev_attr_devspec);
-}
-
-#define ISA_SPACE_MASK 0x1
-#define ISA_SPACE_IO 0x1
-
-static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
- unsigned long phb_io_base_phys,
- void __iomem * phb_io_base_virt)
-{
- /* Remove these asap */
-
- struct pci_address {
- u32 a_hi;
- u32 a_mid;
- u32 a_lo;
- };
-
- struct isa_address {
- u32 a_hi;
- u32 a_lo;
- };
-
- struct isa_range {
- struct isa_address isa_addr;
- struct pci_address pci_addr;
- unsigned int size;
- };
-
- const struct isa_range *range;
- unsigned long pci_addr;
- unsigned int isa_addr;
- unsigned int size;
- int rlen = 0;
-
- range = of_get_property(isa_node, "ranges", &rlen);
- if (range == NULL || (rlen < sizeof(struct isa_range))) {
- printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
- "mapping 64k\n");
- __ioremap_explicit(phb_io_base_phys,
- (unsigned long)phb_io_base_virt,
- 0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
- return;
- }
-
- /* From "ISA Binding to 1275"
- * The ranges property is laid out as an array of elements,
- * each of which comprises:
- * cells 0 - 1: an ISA address
- * cells 2 - 4: a PCI address
- * (size depending on dev->n_addr_cells)
- * cell 5: the size of the range
- */
- if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
- isa_addr = range->isa_addr.a_lo;
- pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
- range->pci_addr.a_lo;
-
- /* Assume these are both zero */
- if ((pci_addr != 0) || (isa_addr != 0)) {
- printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
- __FUNCTION__);
- return;
- }
-
- size = PAGE_ALIGN(range->size);
-
- __ioremap_explicit(phb_io_base_phys,
- (unsigned long) phb_io_base_virt,
- size, _PAGE_NO_CACHE | _PAGE_GUARDED);
- }
-}
-
void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev, int prim)
{
@@ -1047,155 +685,122 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
}
}
-void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
+#ifdef CONFIG_HOTPLUG
+
+int pcibios_unmap_io_space(struct pci_bus *bus)
{
- unsigned long size = hose->pci_io_size;
- unsigned long io_virt_offset;
- struct resource *res;
- struct device_node *isa_dn;
+ struct pci_controller *hose;
- if (size == 0)
- return;
+ WARN_ON(bus == NULL);
- hose->io_base_virt = reserve_phb_iospace(size);
- DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
- hose->global_number, hose->io_base_phys,
- (unsigned long) hose->io_base_virt);
-
- if (primary) {
- pci_io_base = (unsigned long)hose->io_base_virt;
- isa_dn = of_find_node_by_type(NULL, "isa");
- if (isa_dn) {
- isa_io_base = pci_io_base;
- pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
- hose->io_base_virt);
- of_node_put(isa_dn);
- }
- }
+ /* If this is not a PHB, we only flush the hash table over
+ * the area mapped by this bridge. We don't play with the PTE
+ * mappings since we might have to deal with sub-page alignemnts
+ * so flushing the hash table is the only sane way to make sure
+ * that no hash entries are covering that removed bridge area
+ * while still allowing other busses overlapping those pages
+ */
+ if (bus->self) {
+ struct resource *res = bus->resource[0];
- io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
- res = &hose->io_resource;
- res->start += io_virt_offset;
- res->end += io_virt_offset;
+ DBG("IO unmapping for PCI-PCI bridge %s\n",
+ pci_name(bus->self));
- /* If this is called after the initial PCI scan, then we need to
- * proceed to IO mappings now
- */
- if (pci_initial_scan_done)
- __ioremap_explicit(hose->io_base_phys,
- (unsigned long)hose->io_base_virt,
- hose->pci_io_size,
- _PAGE_NO_CACHE | _PAGE_GUARDED);
-}
+ __flush_hash_table_range(&init_mm, res->start + _IO_BASE,
+ res->end - res->start + 1);
+ return 0;
+ }
-void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
- int primary)
-{
- unsigned long size = hose->pci_io_size;
- unsigned long io_virt_offset;
- struct resource *res;
+ /* Get the host bridge */
+ hose = pci_bus_to_host(bus);
- if (size == 0)
- return;
+ /* Check if we have IOs allocated */
+ if (hose->io_base_alloc == 0)
+ return 0;
- hose->io_base_virt = __ioremap(hose->io_base_phys, size,
- _PAGE_NO_CACHE | _PAGE_GUARDED);
- DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
- hose->global_number, hose->io_base_phys,
- (unsigned long) hose->io_base_virt);
+ DBG("IO unmapping for PHB %s\n",
+ ((struct device_node *)hose->arch_data)->full_name);
+ DBG(" alloc=0x%p\n", hose->io_base_alloc);
- if (primary)
- pci_io_base = (unsigned long)hose->io_base_virt;
+ /* This is a PHB, we fully unmap the IO area */
+ vunmap(hose->io_base_alloc);
- io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
- res = &hose->io_resource;
- res->start += io_virt_offset;
- res->end += io_virt_offset;
+ return 0;
}
+EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
+#endif /* CONFIG_HOTPLUG */
-static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
- unsigned long *start_virt, unsigned long *size)
+int __devinit pcibios_map_io_space(struct pci_bus *bus)
{
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct resource *res;
-
- if (bus->self)
- res = bus->resource[0];
- else
- /* Root Bus */
- res = &hose->io_resource;
-
- if (res->end == 0 && res->start == 0)
- return 1;
+ struct vm_struct *area;
+ unsigned long phys_page;
+ unsigned long size_page;
+ unsigned long io_virt_offset;
+ struct pci_controller *hose;
- *start_virt = pci_io_base + res->start;
- *start_phys = *start_virt + hose->io_base_phys
- - (unsigned long) hose->io_base_virt;
+ WARN_ON(bus == NULL);
- if (res->end > res->start)
- *size = res->end - res->start + 1;
- else {
- printk("%s(): unexpected region 0x%lx->0x%lx\n",
- __FUNCTION__, res->start, res->end);
- return 1;
+ /* If this not a PHB, nothing to do, page tables still exist and
+ * thus HPTEs will be faulted in when needed
+ */
+ if (bus->self) {
+ DBG("IO mapping for PCI-PCI bridge %s\n",
+ pci_name(bus->self));
+ DBG(" virt=0x%016lx...0x%016lx\n",
+ bus->resource[0]->start + _IO_BASE,
+ bus->resource[0]->end + _IO_BASE);
+ return 0;
}
- return 0;
-}
-
-int unmap_bus_range(struct pci_bus *bus)
-{
- unsigned long start_phys;
- unsigned long start_virt;
- unsigned long size;
+ /* Get the host bridge */
+ hose = pci_bus_to_host(bus);
+ phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
+ size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
- if (!bus) {
- printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
- return 1;
- }
-
- if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
- return 1;
- if (__iounmap_explicit((void __iomem *) start_virt, size))
- return 1;
-
- return 0;
-}
-EXPORT_SYMBOL(unmap_bus_range);
+ /* Make sure IO area address is clear */
+ hose->io_base_alloc = NULL;
-int remap_bus_range(struct pci_bus *bus)
-{
- unsigned long start_phys;
- unsigned long start_virt;
- unsigned long size;
+ /* If there's no IO to map on that bus, get away too */
+ if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
+ return 0;
- if (!bus) {
- printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
- return 1;
- }
-
-
- if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
- return 1;
- if (start_phys == 0)
- return 1;
- printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
- if (__ioremap_explicit(start_phys, start_virt, size,
- _PAGE_NO_CACHE | _PAGE_GUARDED))
- return 1;
+ /* Let's allocate some IO space for that guy. We don't pass
+ * VM_IOREMAP because we don't care about alignment tricks that
+ * the core does in that case. Maybe we should due to stupid card
+ * with incomplete address decoding but I'd rather not deal with
+ * those outside of the reserved 64K legacy region.
+ */
+ area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
+ if (area == NULL)
+ return -ENOMEM;
+ hose->io_base_alloc = area->addr;
+ hose->io_base_virt = (void __iomem *)(area->addr +
+ hose->io_base_phys - phys_page);
+
+ DBG("IO mapping for PHB %s\n",
+ ((struct device_node *)hose->arch_data)->full_name);
+ DBG(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+ hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
+ DBG(" size=0x%016lx (alloc=0x%016lx)\n",
+ hose->pci_io_size, size_page);
+
+ /* Establish the mapping */
+ if (__ioremap_at(phys_page, area->addr, size_page,
+ _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
+ return -ENOMEM;
+
+ /* Fixup hose IO resource */
+ io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ hose->io_resource.start += io_virt_offset;
+ hose->io_resource.end += io_virt_offset;
+
+ DBG(" hose->io_resource=0x%016lx...0x%016lx\n",
+ hose->io_resource.start, hose->io_resource.end);
return 0;
}
-EXPORT_SYMBOL(remap_bus_range);
-
-static void phbs_remap_io(void)
-{
- struct pci_controller *hose, *tmp;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
- remap_bus_range(hose->bus);
-}
+EXPORT_SYMBOL_GPL(pcibios_map_io_space);
static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
{
@@ -1203,8 +808,7 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
unsigned long offset;
if (res->flags & IORESOURCE_IO) {
- offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
res->start += offset;
res->end += offset;
} else if (res->flags & IORESOURCE_MEM) {
@@ -1219,9 +823,20 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
/* Update device resources. */
int i;
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags)
- fixup_resource(&dev->resource[i], dev);
+ DBG("%s: Fixup resources:\n", pci_name(dev));
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *res = &dev->resource[i];
+ if (!res->flags)
+ continue;
+
+ DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n",
+ i, res->flags, res->start, res->end);
+
+ fixup_resource(res, dev);
+
+ DBG(" > %08lx:0x%016lx...0x%016lx\n",
+ res->flags, res->start, res->end);
+ }
}
EXPORT_SYMBOL(pcibios_fixup_device_resources);
@@ -1291,119 +906,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL(pcibios_fixup_bus);
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
- struct of_irq oirq;
- unsigned int virq;
-
- DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-#ifdef DEBUG
- memset(&oirq, 0xff, sizeof(oirq));
-#endif
- /* Try to get a mapping from the device-tree */
- if (of_irq_map_pci(pci_dev, &oirq)) {
- u8 line, pin;
-
- /* If that fails, lets fallback to what is in the config
- * space and map that through the default controller. We
- * also set the type to level low since that's what PCI
- * interrupts are. If your platform does differently, then
- * either provide a proper interrupt tree or don't use this
- * function.
- */
- if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
- return -1;
- if (pin == 0)
- return -1;
- if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
- line == 0xff) {
- return -1;
- }
- DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
- virq = irq_create_mapping(NULL, line);
- if (virq != NO_IRQ)
- set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
- } else {
- DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
- oirq.size, oirq.specifier[0], oirq.specifier[1],
- oirq.controller->full_name);
-
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
- }
- if(virq == NO_IRQ) {
- DBG(" -> failed to map !\n");
- return -1;
- }
-
- DBG(" -> mapped to linux irq %d\n", virq);
-
- pci_dev->irq = virq;
-
- return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
- const struct resource *rsrc,
- resource_size_t *start, resource_size_t *end)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- resource_size_t offset = 0;
-
- if (hose == NULL)
- return;
-
- if (rsrc->flags & IORESOURCE_IO)
- offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
- /* We pass a fully fixed up address to userland for MMIO instead of
- * a BAR value because X is lame and expects to be able to use that
- * to pass to /dev/mem !
- *
- * That means that we'll have potentially 64 bits values where some
- * userland apps only expect 32 (like X itself since it thinks only
- * Sparc has 64 bits MMIO) but if we don't do that, we break it on
- * 32 bits CHRPs :-(
- *
- * Hopefully, the sysfs insterface is immune to that gunk. Once X
- * has been fixed (and the fix spread enough), we can re-enable the
- * 2 lines below and pass down a BAR value to userland. In that case
- * we'll also have to re-enable the matching code in
- * __pci_mmap_make_offset().
- *
- * BenH.
- */
-#if 0
- else if (rsrc->flags & IORESOURCE_MEM)
- offset = hose->pci_mem_offset;
-#endif
-
- *start = rsrc->start - offset;
- *end = rsrc->end - offset;
-}
-
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
- if (!have_of)
- return NULL;
- while(node) {
- struct pci_controller *hose, *tmp;
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
- if (hose->arch_data == node)
- return hose;
- node = node->parent;
- }
- return NULL;
-}
-
unsigned long pci_address_to_pio(phys_addr_t address)
{
struct pci_controller *hose, *tmp;
@@ -1412,7 +914,7 @@ unsigned long pci_address_to_pio(phys_addr_t address)
if (address >= hose->io_base_phys &&
address < (hose->io_base_phys + hose->pci_io_size)) {
unsigned long base =
- (unsigned long)hose->io_base_virt - pci_io_base;
+ (unsigned long)hose->io_base_virt - _IO_BASE;
return base + (address - hose->io_base_phys);
}
}
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index c96fa9bd35a4..a20f1951a5ce 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -67,7 +67,6 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
EXPORT_SYMBOL(DMA_MODE_READ);
EXPORT_SYMBOL(DMA_MODE_WRITE);
-EXPORT_SYMBOL(do_signal);
EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
EXPORT_SYMBOL(machine_check_exception);
@@ -106,10 +105,6 @@ EXPORT_SYMBOL(isa_mem_base);
EXPORT_SYMBOL(pci_dram_offset);
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_bus_io_base);
-EXPORT_SYMBOL(pci_bus_io_base_phys);
-EXPORT_SYMBOL(pci_bus_mem_base_phys);
-EXPORT_SYMBOL(pci_bus_to_hose);
#endif /* CONFIG_PCI */
EXPORT_SYMBOL(start_thread);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 6e2f03566b0d..84f000a45e36 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -219,22 +219,26 @@ void discard_lazy_cpu_state(void)
}
#endif /* CONFIG_SMP */
-#ifdef CONFIG_PPC_MERGE /* XXX for now */
int set_dabr(unsigned long dabr)
{
+#ifdef CONFIG_PPC_MERGE /* XXX for now */
if (ppc_md.set_dabr)
return ppc_md.set_dabr(dabr);
+#endif
+ /* XXX should we have a CPU_FTR_HAS_DABR ? */
+#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
mtspr(SPRN_DABR, dabr);
+#endif
return 0;
}
-#endif
#ifdef CONFIG_PPC64
DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
-static DEFINE_PER_CPU(unsigned long, current_dabr);
#endif
+static DEFINE_PER_CPU(unsigned long, current_dabr);
+
struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *new)
{
@@ -299,12 +303,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
#endif /* CONFIG_SMP */
-#ifdef CONFIG_PPC64 /* for now */
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
set_dabr(new->thread.dabr);
__get_cpu_var(current_dabr) = new->thread.dabr;
}
-#endif /* CONFIG_PPC64 */
new_thread = &new->thread;
old_thread = &current->thread;
@@ -473,12 +475,10 @@ void flush_thread(void)
discard_lazy_cpu_state();
-#ifdef CONFIG_PPC64 /* for now */
if (current->thread.dabr) {
current->thread.dabr = 0;
set_dabr(0);
}
-#endif
}
void
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index af42ddab3ab4..37ff99bd98b4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -52,6 +52,7 @@
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
#include <asm/kexec.h>
+#include <asm/system.h>
#ifdef DEBUG
#define DBG(fmt...) printk(KERN_ERR fmt)
@@ -1005,7 +1006,7 @@ static void __init early_reserve_mem(void)
void __init early_init_devtree(void *params)
{
- DBG(" -> early_init_devtree()\n");
+ DBG(" -> early_init_devtree(%p)\n", params);
/* Setup flat device-tree pointer */
initial_boot_params = params;
@@ -1055,8 +1056,6 @@ void __init early_init_devtree(void *params)
DBG(" <- early_init_devtree()\n");
}
-#undef printk
-
int of_n_addr_cells(struct device_node* np)
{
const int *ip;
@@ -1375,8 +1374,17 @@ static void of_node_release(struct kref *kref)
struct device_node *node = kref_to_device_node(kref);
struct property *prop = node->properties;
- if (!OF_IS_DYNAMIC(node))
+ /* We should never be releasing nodes that haven't been detached. */
+ if (!of_node_check_flag(node, OF_DETACHED)) {
+ printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
+ dump_stack();
+ kref_init(&node->kref);
+ return;
+ }
+
+ if (!of_node_check_flag(node, OF_DYNAMIC))
return;
+
while (prop) {
struct property *next = prop->next;
kfree(prop->name);
@@ -1432,6 +1440,8 @@ void of_detach_node(const struct device_node *np)
write_lock(&devtree_lock);
parent = np->parent;
+ if (!parent)
+ goto out_unlock;
if (allnodes == np)
allnodes = np->allnext;
@@ -1455,6 +1465,9 @@ void of_detach_node(const struct device_node *np)
prevsib->sibling = np->sibling;
}
+ of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
write_unlock(&devtree_lock);
}
@@ -1716,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
}
EXPORT_SYMBOL(of_get_cpu_node);
-#ifdef DEBUG
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
static struct debugfs_blob_wrapper flat_dt_blob;
static int __init export_flat_device_tree(void)
{
struct dentry *d;
- d = debugfs_create_dir("powerpc", NULL);
- if (!d)
- return 1;
-
flat_dt_blob.data = initial_boot_params;
flat_dt_blob.size = initial_boot_params->totalsize;
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
- d, &flat_dt_blob);
+ powerpc_debugfs_root, &flat_dt_blob);
if (!d)
return 1;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index d6047c441034..a1d582e38627 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -635,6 +635,7 @@ static void __init early_cmdline_parse(void)
/* ibm,dynamic-reconfiguration-memory property supported */
#define OV5_DRCONF_MEMORY 0x20
#define OV5_LARGE_PAGES 0x10 /* large pages supported */
+#define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */
/* PCIe/MSI support. Without MSI full PCIe is not supported */
#ifdef CONFIG_PCI_MSI
#define OV5_MSI 0x01 /* PCIe/MSI support */
@@ -685,7 +686,8 @@ static unsigned char ibm_architecture_vec[] = {
/* option vector 5: PAPR/OF options */
3 - 2, /* length */
0, /* don't ignore, don't halt */
- OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
+ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
+ OV5_DONATE_DEDICATE_CPU | OV5_MSI,
};
/* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
deleted file mode 100644
index 8797ae737a7b..000000000000
--- a/arch/powerpc/kernel/ptrace-common.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2002 Stephen Rothwell, IBM Coproration
- * Extracted from ptrace.c and ptrace32.c
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file README.legal in the main directory of
- * this archive for more details.
- */
-
-#ifndef _PPC64_PTRACE_COMMON_H
-#define _PPC64_PTRACE_COMMON_H
-
-#include <asm/system.h>
-
-/*
- * Set of msr bits that gdb can change on behalf of a process.
- */
-#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
-
-/*
- * Get contents of register REGNO in task TASK.
- */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
-{
- unsigned long tmp = 0;
-
- /*
- * Put the correct FP bits in, they might be wrong as a result
- * of our lazy FP restore.
- */
- if (regno == PT_MSR) {
- tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
- tmp |= task->thread.fpexc_mode;
- } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
- tmp = ((unsigned long *)task->thread.regs)[regno];
- }
-
- return tmp;
-}
-
-/*
- * Write contents of register REGNO in task TASK.
- */
-static inline int put_reg(struct task_struct *task, int regno,
- unsigned long data)
-{
- if (regno < PT_SOFTE) {
- if (regno == PT_MSR)
- data = (data & MSR_DEBUGCHANGE)
- | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
- ((unsigned long *)task->thread.regs)[regno] = data;
- return 0;
- }
- return -EIO;
-}
-
-static inline void set_single_step(struct task_struct *task)
-{
- struct pt_regs *regs = task->thread.regs;
- if (regs != NULL)
- regs->msr |= MSR_SE;
- set_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-static inline void clear_single_step(struct task_struct *task)
-{
- struct pt_regs *regs = task->thread.regs;
- if (regs != NULL)
- regs->msr &= ~MSR_SE;
- clear_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-#ifdef CONFIG_ALTIVEC
-/*
- * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
- * The transfer totals 34 quadword. Quadwords 0-31 contain the
- * corresponding vector registers. Quadword 32 contains the vscr as the
- * last word (offset 12) within that quadword. Quadword 33 contains the
- * vrsave as the first word (offset 0) within the quadword.
- *
- * This definition of the VMX state is compatible with the current PPC32
- * ptrace interface. This allows signal handling and ptrace to use the
- * same structures. This also simplifies the implementation of a bi-arch
- * (combined (32- and 64-bit) gdb.
- */
-
-/*
- * Get contents of AltiVec register state in task TASK
- */
-static inline int get_vrregs(unsigned long __user *data,
- struct task_struct *task)
-{
- unsigned long regsize;
-
- /* copy AltiVec registers VR[0] .. VR[31] */
- regsize = 32 * sizeof(vector128);
- if (copy_to_user(data, task->thread.vr, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
-
- /* copy VSCR */
- regsize = 1 * sizeof(vector128);
- if (copy_to_user(data, &task->thread.vscr, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
-
- /* copy VRSAVE */
- if (put_user(task->thread.vrsave, (u32 __user *)data))
- return -EFAULT;
-
- return 0;
-}
-
-/*
- * Write contents of AltiVec register state into task TASK.
- */
-static inline int set_vrregs(struct task_struct *task,
- unsigned long __user *data)
-{
- unsigned long regsize;
-
- /* copy AltiVec registers VR[0] .. VR[31] */
- regsize = 32 * sizeof(vector128);
- if (copy_from_user(task->thread.vr, data, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
-
- /* copy VSCR */
- regsize = 1 * sizeof(vector128);
- if (copy_from_user(&task->thread.vscr, data, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
-
- /* copy VRSAVE */
- if (get_user(task->thread.vrsave, (u32 __user *)data))
- return -EFAULT;
-
- return 0;
-}
-#endif
-
-static inline int ptrace_set_debugreg(struct task_struct *task,
- unsigned long addr, unsigned long data)
-{
- /* We only support one DABR and no IABRS at the moment */
- if (addr > 0)
- return -EINVAL;
-
- /* The bottom 3 bits are flags */
- if ((data & ~0x7UL) >= TASK_SIZE)
- return -EIO;
-
- /* Ensure translation is on */
- if (data && !(data & DABR_TRANSLATION))
- return -EIO;
-
- task->thread.dabr = data;
- return 0;
-}
-
-#endif /* _PPC64_PTRACE_COMMON_H */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index bf76562167c3..8a177bd9eab4 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -35,11 +35,11 @@
#include <asm/pgtable.h>
#include <asm/system.h>
-#ifdef CONFIG_PPC64
-#include "ptrace-common.h"
-#endif
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
-#ifdef CONFIG_PPC32
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
@@ -48,65 +48,117 @@
#else
#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
#endif
-#endif /* CONFIG_PPC32 */
/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
+ * Max register writeable via put_reg
*/
-
#ifdef CONFIG_PPC32
+#define PT_MAX_PUT_REG PT_MQ
+#else
+#define PT_MAX_PUT_REG PT_CCR
+#endif
+
/*
* Get contents of register REGNO in task TASK.
*/
-static inline unsigned long get_reg(struct task_struct *task, int regno)
+unsigned long ptrace_get_reg(struct task_struct *task, int regno)
{
- if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
- && task->thread.regs != NULL)
+ unsigned long tmp = 0;
+
+ if (task->thread.regs == NULL)
+ return -EIO;
+
+ if (regno == PT_MSR) {
+ tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
+ return tmp | task->thread.fpexc_mode;
+ }
+
+ if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
return ((unsigned long *)task->thread.regs)[regno];
- return (0);
+
+ return -EIO;
}
/*
* Write contents of register REGNO in task TASK.
*/
-static inline int put_reg(struct task_struct *task, int regno,
- unsigned long data)
+int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
{
- if (regno <= PT_MQ && task->thread.regs != NULL) {
+ if (task->thread.regs == NULL)
+ return -EIO;
+
+ if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+ /* We prevent mucking around with the reserved area of trap
+ * which are used internally by the kernel
+ */
+ if (regno == PT_TRAP)
+ data &= 0xfff0;
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
+
+static int get_fpregs(void __user *data, struct task_struct *task,
+ int has_fpscr)
+{
+ unsigned int count = has_fpscr ? 33 : 32;
+
+ if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_fpregs(void __user *data, struct task_struct *task,
+ int has_fpscr)
+{
+ unsigned int count = has_fpscr ? 33 : 32;
+
+ if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
+ return -EFAULT;
+ return 0;
+}
+
+
#ifdef CONFIG_ALTIVEC
/*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword. Quadwords 0-31 contain the
+ * corresponding vector registers. Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword. Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface. This allows signal handling and ptrace to use the
+ * same structures. This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
+/*
* Get contents of AltiVec register state in task TASK
*/
-static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+static int get_vrregs(unsigned long __user *data, struct task_struct *task)
{
- int i, j;
-
- if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
- return -EFAULT;
+ unsigned long regsize;
/* copy AltiVec registers VR[0] .. VR[31] */
- for (i = 0; i < 32; i++)
- for (j = 0; j < 4; j++, data++)
- if (__put_user(task->thread.vr[i].u[j], data))
- return -EFAULT;
+ regsize = 32 * sizeof(vector128);
+ if (copy_to_user(data, task->thread.vr, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
/* copy VSCR */
- for (i = 0; i < 4; i++, data++)
- if (__put_user(task->thread.vscr.u[i], data))
- return -EFAULT;
+ regsize = 1 * sizeof(vector128);
+ if (copy_to_user(data, &task->thread.vscr, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
- /* copy VRSAVE */
- if (__put_user(task->thread.vrsave, data))
+ /* copy VRSAVE */
+ if (put_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;
return 0;
@@ -115,31 +167,29 @@ static inline int get_vrregs(unsigned long __user *data, struct task_struct *tas
/*
* Write contents of AltiVec register state into task TASK.
*/
-static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+static int set_vrregs(struct task_struct *task, unsigned long __user *data)
{
- int i, j;
-
- if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
- return -EFAULT;
+ unsigned long regsize;
/* copy AltiVec registers VR[0] .. VR[31] */
- for (i = 0; i < 32; i++)
- for (j = 0; j < 4; j++, data++)
- if (__get_user(task->thread.vr[i].u[j], data))
- return -EFAULT;
+ regsize = 32 * sizeof(vector128);
+ if (copy_from_user(task->thread.vr, data, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
/* copy VSCR */
- for (i = 0; i < 4; i++, data++)
- if (__get_user(task->thread.vscr.u[i], data))
- return -EFAULT;
+ regsize = 1 * sizeof(vector128);
+ if (copy_from_user(&task->thread.vscr, data, regsize))
+ return -EFAULT;
+ data += (regsize / sizeof(unsigned long));
/* copy VRSAVE */
- if (__get_user(task->thread.vrsave, data))
+ if (get_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;
return 0;
}
-#endif
+#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SPE
@@ -156,7 +206,7 @@ static inline int set_vrregs(struct task_struct *task, unsigned long __user *dat
/*
* Get contents of SPE register state in task TASK.
*/
-static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+static int get_evrregs(unsigned long *data, struct task_struct *task)
{
int i;
@@ -182,7 +232,7 @@ static inline int get_evrregs(unsigned long *data, struct task_struct *task)
/*
* Write contents of SPE register state into task TASK.
*/
-static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+static int set_evrregs(struct task_struct *task, unsigned long *data)
{
int i;
@@ -205,8 +255,8 @@ static inline int set_evrregs(struct task_struct *task, unsigned long *data)
}
#endif /* CONFIG_SPE */
-static inline void
-set_single_step(struct task_struct *task)
+
+static void set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
@@ -221,8 +271,7 @@ set_single_step(struct task_struct *task)
set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
-static inline void
-clear_single_step(struct task_struct *task)
+static void clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
@@ -236,7 +285,25 @@ clear_single_step(struct task_struct *task)
}
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
-#endif /* CONFIG_PPC32 */
+
+static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+ unsigned long data)
+{
+ /* We only support one DABR and no IABRS at the moment */
+ if (addr > 0)
+ return -EINVAL;
+
+ /* The bottom 3 bits are flags */
+ if ((data & ~0x7UL) >= TASK_SIZE)
+ return -EIO;
+
+ /* Ensure translation is on */
+ if (data && !(data & DABR_TRANSLATION))
+ return -EIO;
+
+ task->thread.dabr = data;
+ return 0;
+}
/*
* Called by kernel/ptrace.c when detaching..
@@ -249,6 +316,62 @@ void ptrace_disable(struct task_struct *child)
clear_single_step(child);
}
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long arch_ptrace_old(struct task_struct *child, long request, long addr,
+ long data)
+{
+ int ret = -EPERM;
+
+ switch(request) {
+ case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+ int i;
+ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+ unsigned long __user *tmp = (unsigned long __user *)addr;
+
+ for (i = 0; i < 32; i++) {
+ ret = put_user(*reg, tmp);
+ if (ret)
+ break;
+ reg++;
+ tmp++;
+ }
+ break;
+ }
+
+ case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+ int i;
+ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+ unsigned long __user *tmp = (unsigned long __user *)addr;
+
+ for (i = 0; i < 32; i++) {
+ ret = get_user(*reg, tmp);
+ if (ret)
+ break;
+ reg++;
+ tmp++;
+ }
+ break;
+ }
+
+ case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+ flush_fp_to_thread(child);
+ ret = get_fpregs((void __user *)addr, child, 0);
+ break;
+ }
+
+ case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+ flush_fp_to_thread(child);
+ ret = set_fpregs((void __user *)addr, child, 0);
+ break;
+ }
+
+ }
+ return ret;
+}
+
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret = -EPERM;
@@ -256,17 +379,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long __user *) data);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -284,11 +399,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
break;
-#ifdef CONFIG_PPC32
CHECK_FULL_REGS(child->thread.regs);
-#endif
if (index < PT_FPR0) {
- tmp = get_reg(child, (int) index);
+ tmp = ptrace_get_reg(child, (int) index);
} else {
flush_fp_to_thread(child);
tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
@@ -300,11 +413,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* If I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1)
- == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
/* write the word at location addr in the USER area */
@@ -323,13 +432,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
break;
-#ifdef CONFIG_PPC32
CHECK_FULL_REGS(child->thread.regs);
-#endif
- if (index == PT_ORIG_R3)
- break;
if (index < PT_FPR0) {
- ret = put_reg(child, index, data);
+ ret = ptrace_put_reg(child, index, data);
} else {
flush_fp_to_thread(child);
((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
@@ -384,7 +489,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
-#ifdef CONFIG_PPC64
case PTRACE_GET_DEBUGREG: {
ret = -EINVAL;
/* We only support one DABR and no IABRS at the moment */
@@ -398,73 +502,61 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_SET_DEBUGREG:
ret = ptrace_set_debugreg(child, addr, data);
break;
-#endif
case PTRACE_DETACH:
ret = ptrace_detach(child, data);
break;
- case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned long __user *tmp = (unsigned long __user *)addr;
-
- for (i = 0; i < 32; i++) {
- ret = put_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
+#ifdef CONFIG_PPC64
+ case PTRACE_GETREGS64:
+#endif
+ case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+ int ui;
+ if (!access_ok(VERIFY_WRITE, (void __user *)data,
+ sizeof(struct pt_regs))) {
+ ret = -EIO;
+ break;
+ }
+ ret = 0;
+ for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+ ret |= __put_user(ptrace_get_reg(child, ui),
+ (unsigned long __user *) data);
+ data += sizeof(long);
}
break;
}
- case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned long __user *tmp = (unsigned long __user *)addr;
-
- for (i = 0; i < 32; i++) {
- ret = get_user(*reg, tmp);
+#ifdef CONFIG_PPC64
+ case PTRACE_SETREGS64:
+#endif
+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+ unsigned long tmp;
+ int ui;
+ if (!access_ok(VERIFY_READ, (void __user *)data,
+ sizeof(struct pt_regs))) {
+ ret = -EIO;
+ break;
+ }
+ ret = 0;
+ for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+ ret = __get_user(tmp, (unsigned long __user *) data);
if (ret)
break;
- reg++;
- tmp++;
+ ptrace_put_reg(child, ui, tmp);
+ data += sizeof(long);
}
break;
}
- case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
- unsigned long __user *tmp = (unsigned long __user *)addr;
-
+ case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
flush_fp_to_thread(child);
-
- for (i = 0; i < 32; i++) {
- ret = put_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
- }
+ ret = get_fpregs((void __user *)data, child, 1);
break;
}
- case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
- unsigned long __user *tmp = (unsigned long __user *)addr;
-
+ case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
flush_fp_to_thread(child);
-
- for (i = 0; i < 32; i++) {
- ret = get_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
- }
+ ret = set_fpregs((void __user *)data, child, 1);
break;
}
@@ -499,11 +591,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
#endif
+ /* Old reverse args ptrace callss */
+ case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+ case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+ case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
+ case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
+ ret = arch_ptrace_old(child, request, addr, data);
+ break;
+
default:
ret = ptrace_request(child, request, addr, data);
break;
}
-
return ret;
}
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 9b9a230349bc..9e6baeac0fb1 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -33,13 +33,55 @@
#include <asm/pgtable.h>
#include <asm/system.h>
-#include "ptrace-common.h"
-
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long compat_ptrace_old(struct task_struct *child, long request,
+ long addr, long data)
+{
+ int ret = -EPERM;
+
+ switch(request) {
+ case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+ int i;
+ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+ unsigned int __user *tmp = (unsigned int __user *)addr;
+
+ for (i = 0; i < 32; i++) {
+ ret = put_user(*reg, tmp);
+ if (ret)
+ break;
+ reg++;
+ tmp++;
+ }
+ break;
+ }
+
+ case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+ int i;
+ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+ unsigned int __user *tmp = (unsigned int __user *)addr;
+
+ for (i = 0; i < 32; i++) {
+ ret = get_user(*reg, tmp);
+ if (ret)
+ break;
+ reg++;
+ tmp++;
+ }
+ break;
+ }
+
+ }
+ return ret;
+}
+
long compat_sys_ptrace(int request, int pid, unsigned long addr,
unsigned long data)
{
@@ -123,7 +165,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
if (index < PT_FPR0) {
- tmp = get_reg(child, index);
+ tmp = ptrace_get_reg(child, index);
} else {
flush_fp_to_thread(child);
/*
@@ -162,7 +204,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
else
part = 0; /* want the 1st half of the register (left-most). */
- /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
+ /* Validate the input - check to see if address is on the wrong boundary
+ * or beyond the end of the user area
+ */
if ((addr & 3) || numReg > PT_FPSCR)
break;
@@ -170,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
flush_fp_to_thread(child);
tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
} else { /* register within PT_REGS struct */
- tmp = get_reg(child, numReg);
+ tmp = ptrace_get_reg(child, numReg);
}
reg32bits = ((u32*)&tmp)[part];
ret = put_user(reg32bits, (u32 __user *)data);
@@ -226,10 +270,8 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
if ((addr & 3) || (index > PT_FPSCR32))
break;
- if (index == PT_ORIG_R3)
- break;
if (index < PT_FPR0) {
- ret = put_reg(child, index, data);
+ ret = ptrace_put_reg(child, index, data);
} else {
flush_fp_to_thread(child);
/*
@@ -258,70 +300,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
/* Determine which register the user wants */
index = (u64)addr >> 2;
numReg = index / 2;
+
/*
* Validate the input - check to see if address is on the
* wrong boundary or beyond the end of the user area
*/
if ((addr & 3) || (numReg > PT_FPSCR))
break;
- /* Insure it is a register we let them change */
- if ((numReg == PT_ORIG_R3)
- || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
- break;
- if (numReg >= PT_FPR0) {
+ if (numReg < PT_FPR0) {
+ unsigned long freg = ptrace_get_reg(child, numReg);
+ if (index % 2)
+ freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
+ else
+ freg = (freg & 0xfffffffful) | (data << 32);
+ ret = ptrace_put_reg(child, numReg, freg);
+ } else {
flush_fp_to_thread(child);
+ ((unsigned int *)child->thread.regs)[index] = data;
+ ret = 0;
}
- if (numReg == PT_MSR)
- data = (data & MSR_DEBUGCHANGE)
- | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
- ((u32*)child->thread.regs)[index] = data;
- ret = 0;
- break;
- }
-
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->exit_code = data;
- /* make sure the single step bit is not set. */
- clear_single_step(child);
- wake_up_process(child);
- ret = 0;
- break;
- }
-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {
- ret = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;
- /* make sure the single step bit is not set. */
- clear_single_step(child);
- wake_up_process(child);
- break;
- }
-
- case PTRACE_SINGLESTEP: { /* set the trap flag. */
- ret = -EIO;
- if (!valid_signal(data))
- break;
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- set_single_step(child);
- child->exit_code = data;
- /* give it a chance to run. */
- wake_up_process(child);
- ret = 0;
break;
}
@@ -334,95 +331,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
}
- case PTRACE_SET_DEBUGREG:
- ret = ptrace_set_debugreg(child, addr, data);
- break;
-
- case PTRACE_DETACH:
- ret = ptrace_detach(child, data);
+ case PTRACE_GETEVENTMSG:
+ ret = put_user(child->ptrace_message, (unsigned int __user *) data);
break;
- case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned int __user *tmp = (unsigned int __user *)addr;
-
- for (i = 0; i < 32; i++) {
- ret = put_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
+ case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+ int ui;
+ if (!access_ok(VERIFY_WRITE, (void __user *)data,
+ PT_REGS_COUNT * sizeof(int))) {
+ ret = -EIO;
+ break;
}
- break;
- }
-
- case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned int __user *tmp = (unsigned int __user *)addr;
-
- for (i = 0; i < 32; i++) {
- ret = get_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
+ ret = 0;
+ for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+ ret |= __put_user(ptrace_get_reg(child, ui),
+ (unsigned int __user *) data);
+ data += sizeof(int);
}
break;
}
- case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
- unsigned int __user *tmp = (unsigned int __user *)addr;
-
- flush_fp_to_thread(child);
-
- for (i = 0; i < 32; i++) {
- ret = put_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+ unsigned long tmp;
+ int ui;
+ if (!access_ok(VERIFY_READ, (void __user *)data,
+ PT_REGS_COUNT * sizeof(int))) {
+ ret = -EIO;
+ break;
}
- break;
- }
-
- case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
- unsigned int __user *tmp = (unsigned int __user *)addr;
-
- flush_fp_to_thread(child);
-
- for (i = 0; i < 32; i++) {
- ret = get_user(*reg, tmp);
+ ret = 0;
+ for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+ ret = __get_user(tmp, (unsigned int __user *) data);
if (ret)
break;
- reg++;
- tmp++;
+ ptrace_put_reg(child, ui, tmp);
+ data += sizeof(int);
}
break;
}
- case PTRACE_GETEVENTMSG:
- ret = put_user(child->ptrace_message, (unsigned int __user *) data);
- break;
-
-#ifdef CONFIG_ALTIVEC
+ case PTRACE_GETFPREGS:
+ case PTRACE_SETFPREGS:
case PTRACE_GETVRREGS:
- /* Get the child altivec register state. */
- flush_altivec_to_thread(child);
- ret = get_vrregs((unsigned long __user *)data, child);
+ case PTRACE_SETVRREGS:
+ case PTRACE_GETREGS64:
+ case PTRACE_SETREGS64:
+ case PPC_PTRACE_GETFPREGS:
+ case PPC_PTRACE_SETFPREGS:
+ case PTRACE_KILL:
+ case PTRACE_SINGLESTEP:
+ case PTRACE_DETACH:
+ case PTRACE_SET_DEBUGREG:
+ case PTRACE_SYSCALL:
+ case PTRACE_CONT:
+ ret = arch_ptrace(child, request, addr, data);
break;
- case PTRACE_SETVRREGS:
- /* Set the child altivec register state. */
- flush_altivec_to_thread(child);
- ret = set_vrregs(child, (unsigned long __user *)data);
+ /* Old reverse args ptrace callss */
+ case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+ case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+ ret = compat_ptrace_old(child, request, addr, data);
break;
-#endif
default:
ret = ptrace_request(child, request, addr, data);
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index f2286822be09..a5de6211b97a 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -278,10 +278,8 @@ void __init find_and_init_phbs(void)
{
struct device_node *node;
struct pci_controller *phb;
- unsigned int index;
struct device_node *root = of_find_node_by_path("/");
- index = 0;
for (node = of_get_next_child(root, NULL);
node != NULL;
node = of_get_next_child(root, node)) {
@@ -295,8 +293,7 @@ void __init find_and_init_phbs(void)
continue;
rtas_setup_phb(phb);
pci_process_bridge_OF_ranges(phb, node, 0);
- pci_setup_phb_io(phb, index == 0);
- index++;
+ isa_bridge_find_early(phb);
}
of_node_put(root);
@@ -335,7 +332,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
return 1;
}
- rc = unmap_bus_range(b);
+ rc = pcibios_unmap_io_space(b);
if (rc) {
printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
__FUNCTION__, b->name);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index ed07a198f8d6..4924c48cb1ff 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -32,6 +32,7 @@
#include <linux/unistd.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
+#include <linux/debugfs.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/processor.h>
@@ -486,6 +487,14 @@ int check_legacy_ioport(unsigned long base_port)
switch(base_port) {
case I8042_DATA_REG:
+ if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303")))
+ np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
+ if (np) {
+ parent = of_get_parent(np);
+ of_node_put(np);
+ np = parent;
+ break;
+ }
np = of_find_node_by_type(NULL, "8042");
break;
case FDC_BASE: /* FDC1 */
@@ -571,3 +580,15 @@ static int __init check_cache_coherency(void)
late_initcall(check_cache_coherency);
#endif /* CONFIG_CHECK_CACHE_COHERENCY */
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *powerpc_debugfs_root;
+
+static int powerpc_debugfs_init(void)
+{
+ powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL);
+
+ return powerpc_debugfs_root == NULL;
+}
+arch_initcall(powerpc_debugfs_init);
+#endif
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 35f8f443c14f..7ec6ba56d83d 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -262,13 +262,11 @@ void __init setup_arch(char **cmdline_p)
* Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value.
*/
- if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
- dcache_bsize = cur_cpu_spec->dcache_bsize;
- icache_bsize = cur_cpu_spec->icache_bsize;
- ucache_bsize = 0;
- } else
- ucache_bsize = dcache_bsize = icache_bsize
- = cur_cpu_spec->dcache_bsize;
+ dcache_bsize = cur_cpu_spec->dcache_bsize;
+ icache_bsize = cur_cpu_spec->icache_bsize;
+ ucache_bsize = 0;
+ if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
+ ucache_bsize = icache_bsize = dcache_bsize;
/* reboot on panic */
panic_timeout = 180;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6018178708a5..bc43bba05cf8 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -350,13 +350,11 @@ void __init setup_system(void)
{
DBG(" -> setup_system()\n");
- /* Apply the CPUs-specific and firmware specific fixups to kernel
- * text (nop out sections not relevant to this CPU or this firmware)
+ /* Apply CPUs-specific fixups to kernel text (nop out sections
+ * not relevant to this CPU)
*/
do_feature_fixups(cur_cpu_spec->cpu_features,
&__start___ftr_fixup, &__stop___ftr_fixup);
- do_feature_fixups(powerpc_firmware_features,
- &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
/*
* Unflatten the device-tree passed by prom_init or kexec
@@ -394,6 +392,12 @@ void __init setup_system(void)
if (ppc_md.init_early)
ppc_md.init_early();
+ /* Apply firmware specific fixups to kernel text (nop out
+ * sections not relevant to this firmware)
+ */
+ do_feature_fixups(powerpc_firmware_features,
+ &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+
/*
* We can discover serial ports now since the above did setup the
* hash table management for us, thus ioremap works. We do that early
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
new file mode 100644
index 000000000000..c434d6c4e4e6
--- /dev/null
+++ b/arch/powerpc/kernel/signal.c
@@ -0,0 +1,180 @@
+/*
+ * Common signal handling code for both 32 and 64 bits
+ *
+ * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ * Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+#include "signal.h"
+
+/*
+ * Allocate space for the signal frame
+ */
+void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long oldsp, newsp;
+
+ /* Default to using normal stack */
+ oldsp = regs->gpr[1];
+
+ /* Check for alt stack */
+ if ((ka->sa.sa_flags & SA_ONSTACK) &&
+ current->sas_ss_size && !on_sig_stack(oldsp))
+ oldsp = (current->sas_ss_sp + current->sas_ss_size);
+
+ /* Get aligned frame */
+ newsp = (oldsp - frame_size) & ~0xFUL;
+
+ /* Check access */
+ if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
+ return NULL;
+
+ return (void __user *)newsp;
+}
+
+
+/*
+ * Restore the user process's signal mask
+ */
+void restore_sigmask(sigset_t *set)
+{
+ sigdelsetmask(set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = *set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+}
+
+static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+ int has_handler)
+{
+ unsigned long ret = regs->gpr[3];
+ int restart = 1;
+
+ /* syscall ? */
+ if (TRAP(regs) != 0x0C00)
+ return;
+
+ /* error signalled ? */
+ if (!(regs->ccr & 0x10000000))
+ return;
+
+ switch (ret) {
+ case ERESTART_RESTARTBLOCK:
+ case ERESTARTNOHAND:
+ /* ERESTARTNOHAND means that the syscall should only be
+ * restarted if there was no handler for the signal, and since
+ * we only get here if there is a handler, we dont restart.
+ */
+ restart = !has_handler;
+ break;
+ case ERESTARTSYS:
+ /* ERESTARTSYS means to restart the syscall if there is no
+ * handler or the handler was registered with SA_RESTART
+ */
+ restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
+ break;
+ case ERESTARTNOINTR:
+ /* ERESTARTNOINTR means that the syscall should be
+ * called again after the signal handler returns.
+ */
+ break;
+ default:
+ return;
+ }
+ if (restart) {
+ if (ret == ERESTART_RESTARTBLOCK)
+ regs->gpr[0] = __NR_restart_syscall;
+ else
+ regs->gpr[3] = regs->orig_gpr3;
+ regs->nip -= 4;
+ regs->result = 0;
+ } else {
+ regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
+ }
+}
+
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+ int ret;
+ int is32 = is_32bit_task();
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else if (!oldset)
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+ /* Is there any syscall restart business here ? */
+ check_syscall_restart(regs, &ka, signr > 0);
+
+ if (signr <= 0) {
+ /* No signal to deliver -- put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+ return 0; /* no signals delivered */
+ }
+
+ /*
+ * Reenable the DABR before delivering the signal to
+ * user space. The DABR will have been cleared if it
+ * triggered inside the kernel.
+ */
+ if (current->thread.dabr)
+ set_dabr(current->thread.dabr);
+
+ if (is32) {
+ if (ka.sa.sa_flags & SA_SIGINFO)
+ ret = handle_rt_signal32(signr, &ka, &info, oldset,
+ regs);
+ else
+ ret = handle_signal32(signr, &ka, &info, oldset,
+ regs);
+ } else {
+ ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+ }
+
+ if (ret) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked,
+ &ka.sa.sa_mask);
+ if (!(ka.sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, signr);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ /*
+ * A signal was successfully delivered; the saved sigmask is in
+ * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return ret;
+}
+
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ unsigned long r5, unsigned long r6, unsigned long r7,
+ unsigned long r8, struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
new file mode 100644
index 000000000000..77efb3d5465a
--- /dev/null
+++ b/arch/powerpc/kernel/signal.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ * Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _POWERPC_ARCH_SIGNAL_H
+#define _POWERPC_ARCH_SIGNAL_H
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size);
+extern void restore_sigmask(sigset_t *set);
+
+extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs *regs);
+
+extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs *regs);
+
+
+#ifdef CONFIG_PPC64
+
+static inline int is_32bit_task(void)
+{
+ return test_thread_flag(TIF_32BIT);
+}
+
+extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *set,
+ struct pt_regs *regs);
+
+#else /* CONFIG_PPC64 */
+
+static inline int is_32bit_task(void)
+{
+ return 1;
+}
+
+static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *set,
+ struct pt_regs *regs)
+{
+ return -EFAULT;
+}
+
+#endif /* !defined(CONFIG_PPC64) */
+
+#endif /* _POWERPC_ARCH_SIGNAL_H */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index dd1dca5bfa81..590057e9e987 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -51,12 +51,11 @@
#include <asm/pgtable.h>
#endif
-#undef DEBUG_SIG
+#include "signal.h"
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#undef DEBUG_SIG
#ifdef CONFIG_PPC64
-#define do_signal do_signal32
#define sys_sigsuspend compat_sys_sigsuspend
#define sys_rt_sigsuspend compat_sys_rt_sigsuspend
#define sys_rt_sigreturn compat_sys_rt_sigreturn
@@ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs,
#endif /* CONFIG_PPC64 */
-int do_signal(sigset_t *oldset, struct pt_regs *regs);
-
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
@@ -251,14 +248,6 @@ long sys_sigsuspend(old_sigset_t mask)
return -ERESTARTNOHAND;
}
-#ifdef CONFIG_PPC32
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
- int r6, int r7, int r8, struct pt_regs *regs)
-{
- return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-#endif
-
long sys_sigaction(int sig, struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
@@ -293,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act,
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
- * a sigregs struct
+ * an ABI gap of 56 words
+ * an mcontext struct
* a sigcontext struct
* a gap of __SIGNAL_FRAMESIZE bytes
*
- * Each of these things must be a multiple of 16 bytes in size.
+ * Each of these things must be a multiple of 16 bytes in size. The following
+ * structure represent all of this except the __SIGNAL_FRAMESIZE gap
*
*/
-struct sigregs {
+struct sigframe {
+ struct sigcontext sctx; /* the sigcontext */
struct mcontext mctx; /* all the register values */
/*
* Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -703,44 +695,22 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
}
#endif /* CONFIG_PPC64 */
-
-/*
- * Restore the user process's signal mask
- */
-#ifdef CONFIG_PPC64
-extern void restore_sigmask(sigset_t *set);
-#else /* CONFIG_PPC64 */
-static void restore_sigmask(sigset_t *set)
-{
- sigdelsetmask(set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = *set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-}
-#endif
-
/*
* Set up a signal frame for a "real-time" signal handler
* (one which gets siginfo).
*/
-static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
- struct pt_regs *regs, unsigned long newsp)
+ struct pt_regs *regs)
{
struct rt_sigframe __user *rt_sf;
struct mcontext __user *frame;
- unsigned long origsp = newsp;
+ unsigned long newsp = 0;
/* Set up Signal Frame */
/* Put a Real Time Context onto stack */
- newsp -= sizeof(*rt_sf);
- rt_sf = (struct rt_sigframe __user *)newsp;
-
- /* create a stack frame for the caller of the handler */
- newsp -= __SIGNAL_FRAMESIZE + 16;
-
- if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+ rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+ if (unlikely(rt_sf == NULL))
goto badframe;
/* Put the siginfo & fill in most of the ucontext */
@@ -770,8 +740,12 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
current->thread.fpscr.val = 0; /* turn off all fp exceptions */
+ /* create a stack frame for the caller of the handler */
+ newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
if (put_user(regs->gpr[1], (u32 __user *)newsp))
goto badframe;
+
+ /* Fill registers for signal handler */
regs->gpr[1] = newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) &rt_sf->info;
@@ -1015,27 +989,18 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
/*
* OK, we're invoking a handler
*/
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
- unsigned long newsp)
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
struct sigcontext __user *sc;
- struct sigregs __user *frame;
- unsigned long origsp = newsp;
+ struct sigframe __user *frame;
+ unsigned long newsp = 0;
/* Set up Signal Frame */
- newsp -= sizeof(struct sigregs);
- frame = (struct sigregs __user *) newsp;
-
- /* Put a sigcontext on the stack */
- newsp -= sizeof(*sc);
- sc = (struct sigcontext __user *) newsp;
-
- /* create a stack frame for the caller of the handler */
- newsp -= __SIGNAL_FRAMESIZE;
-
- if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (unlikely(frame == NULL))
goto badframe;
+ sc = (struct sigcontext __user *) &frame->sctx;
#if _NSIG != 64
#error "Please adjust handle_signal()"
@@ -1047,7 +1012,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
#else
|| __put_user(oldset->sig[1], &sc->_unused[3])
#endif
- || __put_user(to_user_ptr(frame), &sc->regs)
+ || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
|| __put_user(sig, &sc->signal))
goto badframe;
@@ -1063,8 +1028,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
current->thread.fpscr.val = 0; /* turn off all fp exceptions */
+ /* create a stack frame for the caller of the handler */
+ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
if (put_user(regs->gpr[1], (u32 __user *)newsp))
goto badframe;
+
regs->gpr[1] = newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) sc;
@@ -1126,106 +1094,3 @@ badframe:
force_sig(SIGSEGV, current);
return 0;
}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
- siginfo_t info;
- struct k_sigaction ka;
- unsigned int newsp;
- int signr, ret;
-
-#ifdef CONFIG_PPC32
- if (try_to_freeze()) {
- signr = 0;
- if (!signal_pending(current))
- goto no_signal;
- }
-#endif
-
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else if (!oldset)
- oldset = &current->blocked;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-#ifdef CONFIG_PPC32
-no_signal:
-#endif
- if (TRAP(regs) == 0x0C00 /* System Call! */
- && regs->ccr & 0x10000000 /* error signalled */
- && ((ret = regs->gpr[3]) == ERESTARTSYS
- || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
- || ret == ERESTART_RESTARTBLOCK)) {
-
- if (signr > 0
- && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
- || (ret == ERESTARTSYS
- && !(ka.sa.sa_flags & SA_RESTART)))) {
- /* make the system call return an EINTR error */
- regs->result = -EINTR;
- regs->gpr[3] = EINTR;
- /* note that the cr0.SO bit is already set */
- } else {
- regs->nip -= 4; /* Back up & retry system call */
- regs->result = 0;
- regs->trap = 0;
- if (ret == ERESTART_RESTARTBLOCK)
- regs->gpr[0] = __NR_restart_syscall;
- else
- regs->gpr[3] = regs->orig_gpr3;
- }
- }
-
- if (signr == 0) {
- /* No signal to deliver -- put the saved sigmask back */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
- return 0; /* no signals delivered */
- }
-
- if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
- && !on_sig_stack(regs->gpr[1]))
- newsp = current->sas_ss_sp + current->sas_ss_size;
- else
- newsp = regs->gpr[1];
- newsp &= ~0xfUL;
-
-#ifdef CONFIG_PPC64
- /*
- * Reenable the DABR before delivering the signal to
- * user space. The DABR will have been cleared if it
- * triggered inside the kernel.
- */
- if (current->thread.dabr)
- set_dabr(current->thread.dabr);
-#endif
-
- /* Whee! Actually deliver the signal. */
- if (ka.sa.sa_flags & SA_SIGINFO)
- ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
- else
- ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
-
- if (ret) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka.sa.sa_mask);
- if (!(ka.sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- /* A signal was successfully delivered; the saved sigmask is in
- its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- }
-
- return ret;
-}
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index b27e26852fdb..de895e6d8c62 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -34,9 +34,9 @@
#include <asm/syscalls.h>
#include <asm/vdso.h>
-#define DEBUG_SIG 0
+#include "signal.h"
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#define DEBUG_SIG 0
#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
#define FP_REGS_SIZE sizeof(elf_fpregset_t)
@@ -64,14 +64,6 @@ struct rt_sigframe {
char abigap[288];
} __attribute__ ((aligned (16)));
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
- unsigned long r6, unsigned long r7, unsigned long r8,
- struct pt_regs *regs)
-{
- return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-
-
/*
* Set up the sigcontext for the signal frame.
*/
@@ -208,25 +200,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
}
/*
- * Allocate space for the signal frame
- */
-static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
- size_t frame_size)
-{
- unsigned long newsp;
-
- /* Default to using normal stack */
- newsp = regs->gpr[1];
-
- if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
- if (! on_sig_stack(regs->gpr[1]))
- newsp = (current->sas_ss_sp + current->sas_ss_size);
- }
-
- return (void __user *)((newsp - frame_size) & -16ul);
-}
-
-/*
* Setup the trampoline code on the stack
*/
static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
@@ -253,19 +226,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
}
/*
- * Restore the user process's signal mask (also used by signal32.c)
- */
-void restore_sigmask(sigset_t *set)
-{
- sigdelsetmask(set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = *set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-}
-
-
-/*
* Handle {get,set,swap}_context operations
*/
int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -359,7 +319,7 @@ badframe:
return 0;
}
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
/* Handler is *really* a pointer to the function descriptor for
@@ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
long err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (unlikely(frame == NULL))
goto badframe;
err |= __put_user(&frame->info, &frame->pinfo);
@@ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
/* Allocate a dummy caller frame for the signal handler. */
- newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
+ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
/* Set up "regs" so we "return" to the signal handler. */
@@ -442,134 +401,3 @@ badframe:
force_sigsegv(signr, current);
return 0;
}
-
-
-/*
- * OK, we're invoking a handler
- */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
-{
- int ret;
-
- /* Set up Signal Frame */
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
-
- if (ret) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
-
- return ret;
-}
-
-static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
-{
- switch ((int)regs->result) {
- case -ERESTART_RESTARTBLOCK:
- case -ERESTARTNOHAND:
- /* ERESTARTNOHAND means that the syscall should only be
- * restarted if there was no handler for the signal, and since
- * we only get here if there is a handler, we dont restart.
- */
- regs->result = -EINTR;
- regs->gpr[3] = EINTR;
- regs->ccr |= 0x10000000;
- break;
- case -ERESTARTSYS:
- /* ERESTARTSYS means to restart the syscall if there is no
- * handler or the handler was registered with SA_RESTART
- */
- if (!(ka->sa.sa_flags & SA_RESTART)) {
- regs->result = -EINTR;
- regs->gpr[3] = EINTR;
- regs->ccr |= 0x10000000;
- break;
- }
- /* fallthrough */
- case -ERESTARTNOINTR:
- /* ERESTARTNOINTR means that the syscall should be
- * called again after the signal handler returns.
- */
- regs->gpr[3] = regs->orig_gpr3;
- regs->nip -= 4;
- regs->result = 0;
- break;
- }
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
-
- /*
- * If the current thread is 32 bit - invoke the
- * 32 bit signal handling code
- */
- if (test_thread_flag(TIF_32BIT))
- return do_signal32(oldset, regs);
-
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else if (!oldset)
- oldset = &current->blocked;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- int ret;
-
- /* Whee! Actually deliver the signal. */
- if (TRAP(regs) == 0x0C00)
- syscall_restart(regs, &ka);
-
- /*
- * Reenable the DABR before delivering the signal to
- * user space. The DABR will have been cleared if it
- * triggered inside the kernel.
- */
- if (current->thread.dabr)
- set_dabr(current->thread.dabr);
-
- ret = handle_signal(signr, &ka, &info, oldset, regs);
-
- /* If a signal was successfully delivered, the saved sigmask is in
- its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
- if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
- clear_thread_flag(TIF_RESTORE_SIGMASK);
-
- return ret;
- }
-
- if (TRAP(regs) == 0x0C00) { /* System Call! */
- if ((int)regs->result == -ERESTARTNOHAND ||
- (int)regs->result == -ERESTARTSYS ||
- (int)regs->result == -ERESTARTNOINTR) {
- regs->gpr[3] = regs->orig_gpr3;
- regs->nip -= 4; /* Back up & retry system call */
- regs->result = 0;
- } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
- regs->gpr[0] = __NR_restart_syscall;
- regs->nip -= 4;
- regs->result = 0;
- }
- }
- /* No signal to deliver -- put the saved sigmask back */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(do_signal);
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 68991c2d4a1b..55d29ed4b7a0 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid)
return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
kobject_name(&dev->kobj));
}
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
{
struct node *node = &node_devices[nid];
sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
}
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
#else
static void register_nodes(void)
@@ -457,9 +459,6 @@ static void register_nodes(void)
#endif
-EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
-EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
-
/* Only valid if CPU is present. */
static ssize_t show_physical_id(struct sys_device *dev, char *buf)
{
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 2c8564d54e4d..e5df167f7824 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -77,9 +77,8 @@
/* keep track of when we need to update the rtc */
time_t last_rtc_update;
#ifdef CONFIG_PPC_ISERIES
-unsigned long iSeries_recal_titan = 0;
-unsigned long iSeries_recal_tb = 0;
-static unsigned long first_settimeofday = 1;
+static unsigned long __initdata iSeries_recal_titan;
+static signed long __initdata iSeries_recal_tb;
#endif
/* The decrementer counts down by 128 every 128ns on a 601. */
@@ -113,8 +112,9 @@ u64 ticklen_to_xs; /* 0.64 fraction */
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL_GPL(rtc_lock);
-u64 tb_to_ns_scale;
-unsigned tb_to_ns_shift;
+static u64 tb_to_ns_scale __read_mostly;
+static unsigned tb_to_ns_shift __read_mostly;
+static unsigned long boot_tb __read_mostly;
struct gettimeofday_struct do_gtod;
@@ -214,7 +214,6 @@ static void account_process_time(struct pt_regs *regs)
run_posix_cpu_timers(current);
}
-#ifdef CONFIG_PPC_SPLPAR
/*
* Stuff for accounting stolen time.
*/
@@ -222,19 +221,28 @@ struct cpu_purr_data {
int initialized; /* thread is running */
u64 tb; /* last TB value read */
u64 purr; /* last PURR value read */
- spinlock_t lock;
};
+/*
+ * Each entry in the cpu_purr_data array is manipulated only by its
+ * "owner" cpu -- usually in the timer interrupt but also occasionally
+ * in process context for cpu online. As long as cpus do not touch
+ * each others' cpu_purr_data, disabling local interrupts is
+ * sufficient to serialize accesses.
+ */
static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
static void snapshot_tb_and_purr(void *data)
{
+ unsigned long flags;
struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
+ local_irq_save(flags);
p->tb = mftb();
p->purr = mfspr(SPRN_PURR);
wmb();
p->initialized = 1;
+ local_irq_restore(flags);
}
/*
@@ -242,15 +250,14 @@ static void snapshot_tb_and_purr(void *data)
*/
void snapshot_timebases(void)
{
- int cpu;
-
if (!cpu_has_feature(CPU_FTR_PURR))
return;
- for_each_possible_cpu(cpu)
- spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
}
+/*
+ * Must be called with interrupts disabled.
+ */
void calculate_steal_time(void)
{
u64 tb, purr;
@@ -262,7 +269,6 @@ void calculate_steal_time(void)
pme = &per_cpu(cpu_purr_data, smp_processor_id());
if (!pme->initialized)
return; /* this can happen in early boot */
- spin_lock(&pme->lock);
tb = mftb();
purr = mfspr(SPRN_PURR);
stolen = (tb - pme->tb) - (purr - pme->purr);
@@ -270,9 +276,9 @@ void calculate_steal_time(void)
account_steal_time(current, stolen);
pme->tb = tb;
pme->purr = purr;
- spin_unlock(&pme->lock);
}
+#ifdef CONFIG_PPC_SPLPAR
/*
* Must be called before the cpu is added to the online map when
* a cpu is being brought up at runtime.
@@ -284,12 +290,12 @@ static void snapshot_purr(void)
if (!cpu_has_feature(CPU_FTR_PURR))
return;
+ local_irq_save(flags);
pme = &per_cpu(cpu_purr_data, smp_processor_id());
- spin_lock_irqsave(&pme->lock, flags);
pme->tb = mftb();
pme->purr = mfspr(SPRN_PURR);
pme->initialized = 1;
- spin_unlock_irqrestore(&pme->lock, flags);
+ local_irq_restore(flags);
}
#endif /* CONFIG_PPC_SPLPAR */
@@ -550,10 +556,15 @@ EXPORT_SYMBOL(profile_pc);
* returned by the service processor for the timebase frequency.
*/
-static void iSeries_tb_recal(void)
+static int __init iSeries_tb_recal(void)
{
struct div_result divres;
unsigned long titan, tb;
+
+ /* Make sure we only run on iSeries */
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
tb = get_tb();
titan = HvCallXm_loadTod();
if ( iSeries_recal_titan ) {
@@ -594,8 +605,18 @@ static void iSeries_tb_recal(void)
}
iSeries_recal_titan = titan;
iSeries_recal_tb = tb;
+
+ return 0;
}
-#endif
+late_initcall(iSeries_tb_recal);
+
+/* Called from platform early init */
+void __init iSeries_time_init_early(void)
+{
+ iSeries_recal_tb = get_tb();
+ iSeries_recal_titan = HvCallXm_loadTod();
+}
+#endif /* CONFIG_PPC_ISERIES */
/*
* For iSeries shared processors, we have to let the hypervisor
@@ -735,7 +756,7 @@ unsigned long long sched_clock(void)
{
if (__USE_RTC())
return get_rtc();
- return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
+ return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
}
int do_settimeofday(struct timespec *tv)
@@ -759,12 +780,6 @@ int do_settimeofday(struct timespec *tv)
* to the RTC again, or write to the RTC but then they don't call
* settimeofday to perform this operation.
*/
-#ifdef CONFIG_PPC_ISERIES
- if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
- iSeries_tb_recal();
- first_settimeofday = 0;
- }
-#endif
/* Make userspace gettimeofday spin until we're done. */
++vdso_data->tb_update_count;
@@ -960,6 +975,8 @@ void __init time_init(void)
}
tb_to_ns_scale = scale;
tb_to_ns_shift = shift;
+ /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
+ boot_tb = get_tb();
tm = get_boot_time();
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index bf6445ac9f1c..2bb1cb911783 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -149,6 +149,7 @@ int die(const char *str, struct pt_regs *regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
+ add_taint(TAINT_DIE);
spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current) ||
@@ -777,7 +778,7 @@ void __kprobes program_check_exception(struct pt_regs *regs)
return;
if (!(regs->msr & MSR_PR) && /* not user-mode */
- report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
+ report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
regs->nip += 4;
return;
}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 4245579edb4e..cef01e4e8989 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -670,7 +670,7 @@ static int __init vdso_init(void)
/*
* Fill up the "systemcfg" stuff for backward compatiblity
*/
- strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
+ strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
vdso_data->version.major = SYSTEMCFG_MAJOR;
vdso_data->version.minor = SYSTEMCFG_MINOR;
vdso_data->processor = mfspr(SPRN_PVR);
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 21c39ff2dc39..ae4acd84143d 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -7,6 +7,7 @@
#define PROVIDE32(x) PROVIDE(x)
#endif
#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
ENTRY(_stext)
@@ -211,6 +212,11 @@ SECTIONS
*(.data.cacheline_aligned)
}
+ . = ALIGN(L1_CACHE_BYTES);
+ .data.read_mostly : {
+ *(.data.read_mostly)
+ }
+
. = ALIGN(PAGE_SIZE);
__data_nosave : {
__nosave_begin = .;
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index ca4dcb07a939..c3df50476539 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -12,7 +12,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c
index 838e09db71d9..7ff2609b64d1 100644
--- a/arch/powerpc/mm/4xx_mmu.c
+++ b/arch/powerpc/mm/4xx_mmu.c
@@ -9,7 +9,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 4f839c6a9768..7e4d27ad3dee 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -11,8 +11,7 @@ obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o
hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o
obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \
hash_utils_64.o hash_low_64.o tlb_64.o \
- slb_low.o slb.o stab.o mmap.o imalloc.o \
- $(hash-y)
+ slb_low.o slb.o stab.o mmap.o $(hash-y)
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o
obj-$(CONFIG_40x) += 4xx_mmu.o
obj-$(CONFIG_44x) += 44x_mmu.o
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 115b25f50bf8..0ece51310bfe 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -380,7 +380,7 @@ out_of_memory:
}
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
return SIGKILL;
do_sigbus:
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 123da03ab118..afab247d472f 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -14,7 +14,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 4a20d890e2f4..6ba9b47e55af 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local)
spin_unlock(&native_tlbie_lock);
}
-static inline void native_lock_hpte(hpte_t *hptep)
+static inline void native_lock_hpte(struct hash_pte *hptep)
{
unsigned long *word = &hptep->v;
@@ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep)
}
}
-static inline void native_unlock_hpte(hpte_t *hptep)
+static inline void native_unlock_hpte(struct hash_pte *hptep)
{
unsigned long *word = &hptep->v;
@@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long pa, unsigned long rflags,
unsigned long vflags, int psize)
{
- hpte_t *hptep = htab_address + hpte_group;
+ struct hash_pte *hptep = htab_address + hpte_group;
unsigned long hpte_v, hpte_r;
int i;
@@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
hptep->r = hpte_r;
/* Guarantee the second dword is visible before the valid bit */
- __asm__ __volatile__ ("eieio" : : : "memory");
+ eieio();
/*
* Now set the first dword including the valid bit
* NOTE: this also unlocks the hpte
@@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
static long native_hpte_remove(unsigned long hpte_group)
{
- hpte_t *hptep;
+ struct hash_pte *hptep;
int i;
int slot_offset;
unsigned long hpte_v;
@@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group)
static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long va, int psize, int local)
{
- hpte_t *hptep = htab_address + slot;
+ struct hash_pte *hptep = htab_address + slot;
unsigned long hpte_v, want_v;
int ret = 0;
@@ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
/* Even if we miss, we need to invalidate the TLB */
if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
DBG_LOW(" -> miss\n");
- native_unlock_hpte(hptep);
ret = -1;
} else {
DBG_LOW(" -> hit\n");
/* Update the HPTE */
hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
- native_unlock_hpte(hptep);
}
+ native_unlock_hpte(hptep);
/* Ensure it is out of the tlb too. */
tlbie(va, psize, local);
@@ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
static long native_hpte_find(unsigned long va, int psize)
{
- hpte_t *hptep;
+ struct hash_pte *hptep;
unsigned long hash;
unsigned long i, j;
long slot;
@@ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
{
unsigned long vsid, va;
long slot;
- hpte_t *hptep;
+ struct hash_pte *hptep;
vsid = get_kernel_vsid(ea);
va = (vsid << 28) | (ea & 0x0fffffff);
@@ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
static void native_hpte_invalidate(unsigned long slot, unsigned long va,
int psize, int local)
{
- hpte_t *hptep = htab_address + slot;
+ struct hash_pte *hptep = htab_address + slot;
unsigned long hpte_v;
unsigned long want_v;
unsigned long flags;
@@ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
#define LP_BITS 8
#define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT)
-static void hpte_decode(hpte_t *hpte, unsigned long slot,
+static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
int *psize, unsigned long *va)
{
unsigned long hpte_r = hpte->r;
@@ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot,
static void native_hpte_clear(void)
{
unsigned long slot, slots, flags;
- hpte_t *hptep = htab_address;
+ struct hash_pte *hptep = htab_address;
unsigned long hpte_v, va;
unsigned long pteg_count;
int psize;
@@ -462,7 +461,7 @@ static void native_hpte_clear(void)
static void native_flush_hash_range(unsigned long number, int local)
{
unsigned long va, hash, index, hidx, shift, slot;
- hpte_t *hptep;
+ struct hash_pte *hptep;
unsigned long hpte_v;
unsigned long want_v;
unsigned long flags;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 4f2f4534a9d8..2ce9491b48d4 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -87,7 +87,7 @@ extern unsigned long dart_tablebase;
static unsigned long _SDR1;
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
-hpte_t *htab_address;
+struct hash_pte *htab_address;
unsigned long htab_size_bytes;
unsigned long htab_hash_mask;
int mmu_linear_psize = MMU_PAGE_4K;
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
deleted file mode 100644
index c831815c31f0..000000000000
--- a/arch/powerpc/mm/imalloc.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * c 2001 PPC 64 Team, IBM Corp
- *
- * 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/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <linux/mutex.h>
-#include <asm/cacheflush.h>
-
-#include "mmu_decl.h"
-
-static DEFINE_MUTEX(imlist_mutex);
-struct vm_struct * imlist = NULL;
-
-static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
-{
- unsigned long addr;
- struct vm_struct **p, *tmp;
-
- addr = ioremap_bot;
- for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
- if (size + addr < (unsigned long) tmp->addr)
- break;
- if ((unsigned long)tmp->addr >= ioremap_bot)
- addr = tmp->size + (unsigned long) tmp->addr;
- if (addr >= IMALLOC_END-size)
- return 1;
- }
- *im_addr = addr;
-
- return 0;
-}
-
-/* Return whether the region described by v_addr and size is a subset
- * of the region described by parent
- */
-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
- struct vm_struct *parent)
-{
- return (int) (v_addr >= (unsigned long) parent->addr &&
- v_addr < (unsigned long) parent->addr + parent->size &&
- size < parent->size);
-}
-
-/* Return whether the region described by v_addr and size is a superset
- * of the region described by child
- */
-static int im_region_is_superset(unsigned long v_addr, unsigned long size,
- struct vm_struct *child)
-{
- struct vm_struct parent;
-
- parent.addr = (void *) v_addr;
- parent.size = size;
-
- return im_region_is_subset((unsigned long) child->addr, child->size,
- &parent);
-}
-
-/* Return whether the region described by v_addr and size overlaps
- * the region described by vm. Overlapping regions meet the
- * following conditions:
- * 1) The regions share some part of the address space
- * 2) The regions aren't identical
- * 3) Neither region is a subset of the other
- */
-static int im_region_overlaps(unsigned long v_addr, unsigned long size,
- struct vm_struct *vm)
-{
- if (im_region_is_superset(v_addr, size, vm))
- return 0;
-
- return (v_addr + size > (unsigned long) vm->addr + vm->size &&
- v_addr < (unsigned long) vm->addr + vm->size) ||
- (v_addr < (unsigned long) vm->addr &&
- v_addr + size > (unsigned long) vm->addr);
-}
-
-/* Determine imalloc status of region described by v_addr and size.
- * Can return one of the following:
- * IM_REGION_UNUSED - Entire region is unallocated in imalloc space.
- * IM_REGION_SUBSET - Region is a subset of a region that is already
- * allocated in imalloc space.
- * vm will be assigned to a ptr to the parent region.
- * IM_REGION_EXISTS - Exact region already allocated in imalloc space.
- * vm will be assigned to a ptr to the existing imlist
- * member.
- * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space.
- * IM_REGION_SUPERSET - Region is a superset of a region that is already
- * allocated in imalloc space.
- */
-static int im_region_status(unsigned long v_addr, unsigned long size,
- struct vm_struct **vm)
-{
- struct vm_struct *tmp;
-
- for (tmp = imlist; tmp; tmp = tmp->next)
- if (v_addr < (unsigned long) tmp->addr + tmp->size)
- break;
-
- *vm = NULL;
- if (tmp) {
- if (im_region_overlaps(v_addr, size, tmp))
- return IM_REGION_OVERLAP;
-
- *vm = tmp;
- if (im_region_is_subset(v_addr, size, tmp)) {
- /* Return with tmp pointing to superset */
- return IM_REGION_SUBSET;
- }
- if (im_region_is_superset(v_addr, size, tmp)) {
- /* Return with tmp pointing to first subset */
- return IM_REGION_SUPERSET;
- }
- else if (v_addr == (unsigned long) tmp->addr &&
- size == tmp->size) {
- /* Return with tmp pointing to exact region */
- return IM_REGION_EXISTS;
- }
- }
-
- return IM_REGION_UNUSED;
-}
-
-static struct vm_struct * split_im_region(unsigned long v_addr,
- unsigned long size, struct vm_struct *parent)
-{
- struct vm_struct *vm1 = NULL;
- struct vm_struct *vm2 = NULL;
- struct vm_struct *new_vm = NULL;
-
- vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
- if (vm1 == NULL) {
- printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
- return NULL;
- }
-
- if (v_addr == (unsigned long) parent->addr) {
- /* Use existing parent vm_struct to represent child, allocate
- * new one for the remainder of parent range
- */
- vm1->size = parent->size - size;
- vm1->addr = (void *) (v_addr + size);
- vm1->next = parent->next;
-
- parent->size = size;
- parent->next = vm1;
- new_vm = parent;
- } else if (v_addr + size == (unsigned long) parent->addr +
- parent->size) {
- /* Allocate new vm_struct to represent child, use existing
- * parent one for remainder of parent range
- */
- vm1->size = size;
- vm1->addr = (void *) v_addr;
- vm1->next = parent->next;
- new_vm = vm1;
-
- parent->size -= size;
- parent->next = vm1;
- } else {
- /* Allocate two new vm_structs for the new child and
- * uppermost remainder, and use existing parent one for the
- * lower remainder of parent range
- */
- vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
- if (vm2 == NULL) {
- printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
- kfree(vm1);
- return NULL;
- }
-
- vm1->size = size;
- vm1->addr = (void *) v_addr;
- vm1->next = vm2;
- new_vm = vm1;
-
- vm2->size = ((unsigned long) parent->addr + parent->size) -
- (v_addr + size);
- vm2->addr = (void *) v_addr + size;
- vm2->next = parent->next;
-
- parent->size = v_addr - (unsigned long) parent->addr;
- parent->next = vm1;
- }
-
- return new_vm;
-}
-
-static struct vm_struct * __add_new_im_area(unsigned long req_addr,
- unsigned long size)
-{
- struct vm_struct **p, *tmp, *area;
-
- for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
- if (req_addr + size <= (unsigned long)tmp->addr)
- break;
- }
-
- area = kmalloc(sizeof(*area), GFP_KERNEL);
- if (!area)
- return NULL;
- area->flags = 0;
- area->addr = (void *)req_addr;
- area->size = size;
- area->next = *p;
- *p = area;
-
- return area;
-}
-
-static struct vm_struct * __im_get_area(unsigned long req_addr,
- unsigned long size,
- int criteria)
-{
- struct vm_struct *tmp;
- int status;
-
- status = im_region_status(req_addr, size, &tmp);
- if ((criteria & status) == 0) {
- return NULL;
- }
-
- switch (status) {
- case IM_REGION_UNUSED:
- tmp = __add_new_im_area(req_addr, size);
- break;
- case IM_REGION_SUBSET:
- tmp = split_im_region(req_addr, size, tmp);
- break;
- case IM_REGION_EXISTS:
- /* Return requested region */
- break;
- case IM_REGION_SUPERSET:
- /* Return first existing subset of requested region */
- break;
- default:
- printk(KERN_ERR "%s() unexpected imalloc region status\n",
- __FUNCTION__);
- tmp = NULL;
- }
-
- return tmp;
-}
-
-struct vm_struct * im_get_free_area(unsigned long size)
-{
- struct vm_struct *area;
- unsigned long addr;
-
- mutex_lock(&imlist_mutex);
- if (get_free_im_addr(size, &addr)) {
- printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
- __FUNCTION__, size);
- area = NULL;
- goto next_im_done;
- }
-
- area = __im_get_area(addr, size, IM_REGION_UNUSED);
- if (area == NULL) {
- printk(KERN_ERR
- "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
- __FUNCTION__, addr, size);
- }
-next_im_done:
- mutex_unlock(&imlist_mutex);
- return area;
-}
-
-struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
- int criteria)
-{
- struct vm_struct *area;
-
- mutex_lock(&imlist_mutex);
- area = __im_get_area(v_addr, size, criteria);
- mutex_unlock(&imlist_mutex);
- return area;
-}
-
-void im_free(void * addr)
-{
- struct vm_struct **p, *tmp;
-
- if (!addr)
- return;
- if ((unsigned long) addr & ~PAGE_MASK) {
- printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
- return;
- }
- mutex_lock(&imlist_mutex);
- for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
- if (tmp->addr == addr) {
- *p = tmp->next;
- unmap_vm_area(tmp);
- kfree(tmp);
- mutex_unlock(&imlist_mutex);
- return;
- }
- }
- mutex_unlock(&imlist_mutex);
- printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
- addr);
-}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 5fce6ccecb8d..e1f5ded851f6 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -5,7 +5,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
* PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
*
* Derived from "arch/i386/mm/init.c"
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 7312a265545f..1d6edf724c85 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -5,7 +5,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 0266a94d83b6..f0e7eedb1ba3 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -5,7 +5,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
* PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
*
* Derived from "arch/i386/mm/init.c"
@@ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size)
zone = pgdata->node_zones;
return __add_pages(zone, start_pfn, nr_pages);
-
- return 0;
}
/*
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c
index 792086b01000..cc32ba41d900 100644
--- a/arch/powerpc/mm/mmu_context_32.c
+++ b/arch/powerpc/mm/mmu_context_32.c
@@ -11,7 +11,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 2558c34eedaa..c94a64fd3c01 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -8,7 +8,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@@ -40,8 +39,8 @@ extern int __map_without_bats;
extern unsigned long ioremap_base;
extern unsigned int rtas_data, rtas_size;
-struct _PTE;
-extern struct _PTE *Hash, *Hash_end;
+struct hash_pte;
+extern struct hash_pte *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern unsigned int num_tlbcam_entries;
@@ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va,
else
_tlbie(va);
}
-#else /* CONFIG_PPC64 */
-/* imalloc region types */
-#define IM_REGION_UNUSED 0x1
-#define IM_REGION_SUBSET 0x2
-#define IM_REGION_EXISTS 0x4
-#define IM_REGION_OVERLAP 0x8
-#define IM_REGION_SUPERSET 0x10
-
-extern struct vm_struct * im_get_free_area(unsigned long size);
-extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
- int region_type);
-extern void im_free(void *addr);
#endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index f6ae1a57d652..64488723162a 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -8,7 +8,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@@ -37,7 +36,6 @@
unsigned long ioremap_base;
unsigned long ioremap_bot;
EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
-int io_bat_index;
#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
#define HAVE_BATS 1
@@ -300,51 +298,6 @@ void __init mapin_ram(void)
}
}
-/* is x a power of 4? */
-#define is_power_of_4(x) is_power_of_2(x) && (ffs(x) & 1)
-
-/*
- * Set up a mapping for a block of I/O.
- * virt, phys, size must all be page-aligned.
- * This should only be called before ioremap is called.
- */
-void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
- unsigned int size, int flags)
-{
- int i;
-
- if (virt > KERNELBASE && virt < ioremap_bot)
- ioremap_bot = ioremap_base = virt;
-
-#ifdef HAVE_BATS
- /*
- * Use a BAT for this if possible...
- */
- if (io_bat_index < 2 && is_power_of_2(size)
- && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
- setbat(io_bat_index, virt, phys, size, flags);
- ++io_bat_index;
- return;
- }
-#endif /* HAVE_BATS */
-
-#ifdef HAVE_TLBCAM
- /*
- * Use a CAM for this if possible...
- */
- if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
- && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
- settlbcam(tlbcam_index, virt, phys, size, flags, 0);
- ++tlbcam_index;
- return;
- }
-#endif /* HAVE_TLBCAM */
-
- /* No BATs available, put it in the page tables. */
- for (i = 0; i < size; i += PAGE_SIZE)
- map_page(virt + i, phys + i, flags);
-}
-
/* Scan the real Linux page tables and return a PTE pointer for
* a virtual address in a context.
* Returns true (1) if PTE was found, zero otherwise. The pointer to
@@ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
return(retval);
}
-/* Find physical address for this virtual address. Normally used by
- * I/O functions, but anyone can call it.
- */
-unsigned long iopa(unsigned long addr)
-{
- unsigned long pa;
-
- /* I don't know why this won't work on PMacs or CHRP. It
- * appears there is some bug, or there is some implicit
- * mapping done not properly represented by BATs or in page
- * tables.......I am actively working on resolving this, but
- * can't hold up other stuff. -- Dan
- */
- pte_t *pte;
- struct mm_struct *mm;
-
- /* Check the BATs */
- pa = v_mapped_by_bats(addr);
- if (pa)
- return pa;
-
- /* Allow mapping of user addresses (within the thread)
- * for DMA if necessary.
- */
- if (addr < TASK_SIZE)
- mm = current->mm;
- else
- mm = &init_mm;
-
- pa = 0;
- if (get_pteptr(mm, addr, &pte, NULL)) {
- pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
- pte_unmap(pte);
- }
-
- return(pa);
-}
-
-/* This is will find the virtual address for a physical one....
- * Swiped from APUS, could be dangerous :-).
- * This is only a placeholder until I really find a way to make this
- * work. -- Dan
- */
-unsigned long
-mm_ptov (unsigned long paddr)
-{
- unsigned long ret;
-#if 0
- if (paddr < 16*1024*1024)
- ret = ZTWO_VADDR(paddr);
- else {
- int i;
-
- for (i = 0; i < kmap_chunk_count;){
- unsigned long phys = kmap_chunks[i++];
- unsigned long size = kmap_chunks[i++];
- unsigned long virt = kmap_chunks[i++];
- if (paddr >= phys
- && paddr < (phys + size)){
- ret = virt + paddr - phys;
- goto exit;
- }
- }
-
- ret = (unsigned long) __va(paddr);
- }
-exit:
-#ifdef DEBUGPV
- printk ("PTOV(%lx)=%lx\n", paddr, ret);
-#endif
-#else
- ret = (unsigned long)paddr + KERNELBASE;
-#endif
- return ret;
-}
-
#ifdef CONFIG_DEBUG_PAGEALLOC
static int __change_page_attr(struct page *page, pgprot_t prot)
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index ad6e135bf212..3dfd10db931a 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -7,7 +7,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@@ -34,41 +33,27 @@
#include <linux/stddef.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/idr.h>
-#include <linux/nodemask.h>
-#include <linux/module.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
#include <asm/prom.h>
-#include <asm/lmb.h>
-#include <asm/rtas.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/mmu.h>
-#include <asm/uaccess.h>
#include <asm/smp.h>
#include <asm/machdep.h>
#include <asm/tlb.h>
-#include <asm/eeh.h>
#include <asm/processor.h>
-#include <asm/mmzone.h>
#include <asm/cputable.h>
#include <asm/sections.h>
#include <asm/system.h>
-#include <asm/iommu.h>
#include <asm/abs_addr.h>
-#include <asm/vdso.h>
#include <asm/firmware.h>
#include "mmu_decl.h"
-unsigned long ioremap_bot = IMALLOC_BASE;
-static unsigned long phbs_io_bot = PHBS_IO_BASE;
+unsigned long ioremap_bot = IOREMAP_BASE;
/*
* map_io_page currently only called by __ioremap
@@ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
* entry in the hardware page table.
*
*/
- if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
- mmu_io_psize)) {
+ if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
+ pa, flags, mmu_io_psize)) {
printk(KERN_ERR "Failed to do bolted mapping IO "
"memory at %016lx !\n", pa);
return -ENOMEM;
@@ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
}
-static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
- unsigned long ea, unsigned long size,
+/**
+ * __ioremap_at - Low level function to establish the page tables
+ * for an IO mapping
+ */
+void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
unsigned long flags)
{
unsigned long i;
@@ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
if ((flags & _PAGE_PRESENT) == 0)
flags |= pgprot_val(PAGE_KERNEL);
+ WARN_ON(pa & ~PAGE_MASK);
+ WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+ WARN_ON(size & ~PAGE_MASK);
+
for (i = 0; i < size; i += PAGE_SIZE)
- if (map_io_page(ea+i, pa+i, flags))
+ if (map_io_page((unsigned long)ea+i, pa+i, flags))
return NULL;
- return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+ return (void __iomem *)ea;
+}
+
+/**
+ * __iounmap_from - Low level function to tear down the page tables
+ * for an IO mapping. This is used for mappings that
+ * are manipulated manually, like partial unmapping of
+ * PCI IOs or ISA space.
+ */
+void __iounmap_at(void *ea, unsigned long size)
+{
+ WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+ WARN_ON(size & ~PAGE_MASK);
+
+ unmap_kernel_range((unsigned long)ea, size);
}
void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
unsigned long flags)
{
- unsigned long pa, ea;
+ phys_addr_t paligned;
void __iomem *ret;
/*
@@ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
* IMALLOC_END
*
*/
- pa = addr & PAGE_MASK;
- size = PAGE_ALIGN(addr + size) - pa;
+ paligned = addr & PAGE_MASK;
+ size = PAGE_ALIGN(addr + size) - paligned;
- if ((size == 0) || (pa == 0))
+ if ((size == 0) || (paligned == 0))
return NULL;
if (mem_init_done) {
struct vm_struct *area;
- area = im_get_free_area(size);
+
+ area = __get_vm_area(size, VM_IOREMAP,
+ ioremap_bot, IOREMAP_END);
if (area == NULL)
return NULL;
- ea = (unsigned long)(area->addr);
- ret = __ioremap_com(addr, pa, ea, size, flags);
+ ret = __ioremap_at(paligned, area->addr, size, flags);
if (!ret)
- im_free(area->addr);
+ vunmap(area->addr);
} else {
- ea = ioremap_bot;
- ret = __ioremap_com(addr, pa, ea, size, flags);
+ ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
if (ret)
ioremap_bot += size;
}
+
+ if (ret)
+ ret += addr & ~PAGE_MASK;
return ret;
}
@@ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
}
-#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
-
-int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
- unsigned long size, unsigned long flags)
-{
- struct vm_struct *area;
- void __iomem *ret;
-
- /* For now, require page-aligned values for pa, ea, and size */
- if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
- !IS_PAGE_ALIGNED(size)) {
- printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
- return 1;
- }
-
- if (!mem_init_done) {
- /* Two things to consider in this case:
- * 1) No records will be kept (imalloc, etc) that the region
- * has been remapped
- * 2) It won't be easy to iounmap() the region later (because
- * of 1)
- */
- ;
- } else {
- area = im_get_area(ea, size,
- IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
- if (area == NULL) {
- /* Expected when PHB-dlpar is in play */
- return 1;
- }
- if (ea != (unsigned long) area->addr) {
- printk(KERN_ERR "unexpected addr return from "
- "im_get_area\n");
- return 1;
- }
- }
-
- ret = __ioremap_com(pa, pa, ea, size, flags);
- if (ret == NULL) {
- printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
- return 1;
- }
- if (ret != (void *) ea) {
- printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
- return 1;
- }
-
- return 0;
-}
-
/*
* Unmap an IO region and remove it from imalloc'd list.
* Access to IO memory should be serialized by driver.
- * This code is modeled after vmalloc code - unmap_vm_area()
- *
- * XXX what about calls before mem_init_done (ie python_countermeasures())
*/
void __iounmap(volatile void __iomem *token)
{
@@ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token)
if (!mem_init_done)
return;
- addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-
- im_free(addr);
+ addr = (void *) ((unsigned long __force)
+ PCI_FIX_ADDR(token) & PAGE_MASK);
+ if ((unsigned long)addr < ioremap_bot) {
+ printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
+ " at 0x%p\n", addr);
+ return;
+ }
+ vunmap(addr);
}
void iounmap(volatile void __iomem *token)
@@ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token)
__iounmap(token);
}
-static int iounmap_subset_regions(unsigned long addr, unsigned long size)
-{
- struct vm_struct *area;
-
- /* Check whether subsets of this region exist */
- area = im_get_area(addr, size, IM_REGION_SUPERSET);
- if (area == NULL)
- return 1;
-
- while (area) {
- iounmap((void __iomem *) area->addr);
- area = im_get_area(addr, size,
- IM_REGION_SUPERSET);
- }
-
- return 0;
-}
-
-int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
-{
- struct vm_struct *area;
- unsigned long addr;
- int rc;
-
- addr = (unsigned long __force) start & PAGE_MASK;
-
- /* Verify that the region either exists or is a subset of an existing
- * region. In the latter case, split the parent region to create
- * the exact region
- */
- area = im_get_area(addr, size,
- IM_REGION_EXISTS | IM_REGION_SUBSET);
- if (area == NULL) {
- /* Determine whether subset regions exist. If so, unmap */
- rc = iounmap_subset_regions(addr, size);
- if (rc) {
- printk(KERN_ERR
- "%s() cannot unmap nonexistent range 0x%lx\n",
- __FUNCTION__, addr);
- return 1;
- }
- } else {
- iounmap((void __iomem *) area->addr);
- }
- /*
- * FIXME! This can't be right:
- iounmap(area->addr);
- * Maybe it should be "iounmap(area);"
- */
- return 0;
-}
-
EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(ioremap_flags);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__iounmap);
-
-static DEFINE_SPINLOCK(phb_io_lock);
-
-void __iomem * reserve_phb_iospace(unsigned long size)
-{
- void __iomem *virt_addr;
-
- if (phbs_io_bot >= IMALLOC_BASE)
- panic("reserve_phb_iospace(): phb io space overflow\n");
-
- spin_lock(&phb_io_lock);
- virt_addr = (void __iomem *) phbs_io_bot;
- phbs_io_bot += size;
- spin_unlock(&phb_io_lock);
-
- return virt_addr;
-}
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index ec1421a20aaa..5c45d474cfcc 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -11,7 +11,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@@ -35,12 +34,12 @@
#include "mmu_decl.h"
-PTE *Hash, *Hash_end;
+struct hash_pte *Hash, *Hash_end;
unsigned long Hash_size, Hash_mask;
unsigned long _SDR1;
union ubat { /* BAT register values to be loaded */
- BAT bat;
+ struct ppc_bat bat;
u32 word[2];
} BATS[8][2]; /* 8 pairs of IBAT, DBAT */
@@ -245,7 +244,7 @@ void __init MMU_init_hw(void)
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
- Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+ Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
total_memory >> 20, Hash_size >> 10, Hash);
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 132c6bc66ce1..28492bbdee8e 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -55,7 +55,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
for (entry = 0; entry < 8; entry++, ste++) {
if (!(ste->esid_data & STE_ESID_V)) {
ste->vsid_data = vsid_data;
- asm volatile("eieio":::"memory");
+ eieio();
ste->esid_data = esid_data;
return (global_entry | entry);
}
@@ -101,7 +101,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
asm volatile("sync" : : : "memory"); /* Order update */
castout_ste->vsid_data = vsid_data;
- asm volatile("eieio" : : : "memory"); /* Order update */
+ eieio(); /* Order update */
castout_ste->esid_data = esid_data;
asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT));
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c
index 6a69417cbc0e..06c7e77e097a 100644
--- a/arch/powerpc/mm/tlb_32.c
+++ b/arch/powerpc/mm/tlb_32.c
@@ -11,7 +11,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index 2bfc4d7e1aa2..cbd34fc813ee 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -8,7 +8,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
- * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@@ -239,3 +238,59 @@ void pte_free_finish(void)
pte_free_submit(*batchp);
*batchp = NULL;
}
+
+/**
+ * __flush_hash_table_range - Flush all HPTEs for a given address range
+ * from the hash table (and the TLB). But keeps
+ * the linux PTEs intact.
+ *
+ * @mm : mm_struct of the target address space (generally init_mm)
+ * @start : starting address
+ * @end : ending address (not included in the flush)
+ *
+ * This function is mostly to be used by some IO hotplug code in order
+ * to remove all hash entries from a given address range used to map IO
+ * space on a removed PCI-PCI bidge without tearing down the full mapping
+ * since 64K pages may overlap with other bridges when using 64K pages
+ * with 4K HW pages on IO space.
+ *
+ * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
+ * and is implemented for small size rather than speed.
+ */
+#ifdef CONFIG_HOTPLUG
+
+void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ unsigned long flags;
+
+ start = _ALIGN_DOWN(start, PAGE_SIZE);
+ end = _ALIGN_UP(end, PAGE_SIZE);
+
+ BUG_ON(!mm->pgd);
+
+ /* Note: Normally, we should only ever use a batch within a
+ * PTE locked section. This violates the rule, but will work
+ * since we don't actually modify the PTEs, we just flush the
+ * hash while leaving the PTEs intact (including their reference
+ * to being hashed). This is not the most performance oriented
+ * way to do things but is fine for our needs here.
+ */
+ local_irq_save(flags);
+ arch_enter_lazy_mmu_mode();
+ for (; start < end; start += PAGE_SIZE) {
+ pte_t *ptep = find_linux_pte(mm->pgd, start);
+ unsigned long pte;
+
+ if (ptep == NULL)
+ continue;
+ pte = pte_val(*ptep);
+ if (!(pte & _PAGE_HASHPTE))
+ continue;
+ hpte_need_flush(mm, start, ptep, pte, 0);
+ }
+ arch_leave_lazy_mmu_mode();
+ local_irq_restore(flags);
+}
+
+#endif /* CONFIG_HOTPLUG */
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index fe597a154d4f..a7c206b665af 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Added mmcra[slot] support:
+ * Copyright (C) 2006-2007 Will Schmidt <willschm@us.ibm.com>, IBM
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -181,11 +183,17 @@ static void __attribute_used__ kernel_unknown_bucket(void)
* On GQ and newer the MMCRA stores the HV and PR bits at the time
* the SIAR was sampled. We use that to work out if the SIAR was sampled in
* the hypervisor, our exception vectors or RTAS.
+ * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits
+ * to more accurately identify the address of the sampled instruction. The
+ * mmcra[slot] bits represent the slot number of a sampled instruction
+ * within an instruction group. The slot will contain a value between 1
+ * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0.
*/
static unsigned long get_pc(struct pt_regs *regs)
{
unsigned long pc = mfspr(SPRN_SIAR);
unsigned long mmcra;
+ unsigned long slot;
/* Cant do much about it */
if (!cur_cpu_spec->oprofile_mmcra_sihv)
@@ -193,6 +201,12 @@ static unsigned long get_pc(struct pt_regs *regs)
mmcra = mfspr(SPRN_MMCRA);
+ if (mmcra & MMCRA_SAMPLE_ENABLE) {
+ slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT);
+ if (slot > 1)
+ pc += 4 * (slot - 1);
+ }
+
/* Were we in the hypervisor? */
if (firmware_has_feature(FW_FEATURE_LPAR) &&
(mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index f591a9fc19b9..4be6e7a17b66 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -54,7 +54,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
struct pci_controller *hose = bus->sysdata;
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
+ | (hose->global_number << 24);
int ret = -1;
int rval;
@@ -69,7 +69,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
struct pci_controller *hose = bus->sysdata;
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
+ | (hose->global_number << 24);
int rval;
rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -83,7 +83,7 @@ static struct pci_ops rtas_pci_ops = {
};
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
{
const int *bus_range;
int len;
@@ -128,7 +128,7 @@ void __init efika_pcisetup(void)
printk(" controlled by %s\n", pcictrl->full_name);
printk("\n");
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(of_node_get(pcictrl));
if (!hose) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Can't allocate PCI controller structure for %s\n",
@@ -136,7 +136,6 @@ void __init efika_pcisetup(void)
return;
}
- hose->arch_data = of_node_get(pcictrl);
hose->first_busno = bus_range[0];
hose->last_busno = bus_range[1];
hose->ops = &rtas_pci_ops;
@@ -145,7 +144,7 @@ void __init efika_pcisetup(void)
}
#else
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
{}
#endif
@@ -252,6 +251,8 @@ define_machine(efika)
.progress = rtas_progress,
.get_boot_time = rtas_get_boot_time,
.calibrate_decr = generic_calibrate_decr,
+#ifdef CONFIG_PCI
.phys_mem_access_prot = pci_phys_mem_access_prot,
+#endif
};
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 1cfc00dfb99a..5c46e898fd45 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -156,7 +156,7 @@ static void __init lite5200_setup_arch(void)
}
-void lite5200_show_cpuinfo(struct seq_file *m)
+static void lite5200_show_cpuinfo(struct seq_file *m)
{
struct device_node* np = of_find_all_nodes(NULL);
const char *model = NULL;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 34d34a26d305..4c6c82a684b1 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -112,18 +112,18 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
u32 value;
if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
out_be32(hose->cfg_addr,
(1 << 31) |
- ((bus->number - hose->bus_offset) << 16) |
+ (bus->number << 16) |
(devfn << 8) |
(offset & 0xfc));
mb();
#if defined(CONFIG_PPC_MPC5200_BUGFIX)
- if (bus->number != hose->bus_offset) {
+ if (bus->number) {
/* workaround for the bug 435 of the MPC5200 (L25R);
* Don't do 32 bits config access during type-1 cycles */
switch (len) {
@@ -169,18 +169,18 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
u32 value, mask;
if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
out_be32(hose->cfg_addr,
(1 << 31) |
- ((bus->number - hose->bus_offset) << 16) |
+ (bus->number << 16) |
(devfn << 8) |
(offset & 0xfc));
mb();
#if defined(CONFIG_PPC_MPC5200_BUGFIX)
- if (bus->number != hose->bus_offset) {
+ if (bus->number) {
/* workaround for the bug 435 of the MPC5200 (L25R);
* Don't do 32 bits config access during type-1 cycles */
switch (len) {
@@ -385,17 +385,13 @@ mpc52xx_add_bridge(struct device_node *node)
* tree are needed to configure the 52xx PCI controller. Rather
* than parse the tree here, let pci_process_bridge_OF_ranges()
* do it for us and extract the values after the fact */
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(node);
if (!hose)
return -ENOMEM;
- hose->arch_data = node;
- hose->set_cfg_type = 1;
-
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
- hose->bus_offset = 0;
hose->ops = &mpc52xx_pci_ops;
pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index fd40044d16cd..ee2e7639c63e 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -9,8 +9,8 @@
/* these are defined in mpc52xx_sleep.S, and only used here */
-extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
- struct mpc52xx_cdm *, struct mpc52xx_intr *);
+extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs,
+ struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*);
extern void mpc52xx_ds_sram(void);
extern const long mpc52xx_ds_sram_size;
extern void mpc52xx_ds_cached(void);
@@ -21,7 +21,7 @@ static void __iomem *sdram;
static struct mpc52xx_cdm __iomem *cdm;
static struct mpc52xx_intr __iomem *intr;
static struct mpc52xx_gpio_wkup __iomem *gpiow;
-static void *sram;
+static void __iomem *sram;
static int sram_size;
struct mpc52xx_suspend mpc52xx_suspend;
@@ -100,7 +100,7 @@ int mpc52xx_pm_enter(suspend_state_t state)
u32 clk_enables;
u32 msr, hid0;
u32 intr_main_mask;
- void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+ void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500;
unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
char saved_0x500[mpc52xx_ds_cached_size];
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index de7fce9cb6eb..89fde43895c5 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -1,5 +1,5 @@
choice
- prompt "Machine Type"
+ prompt "82xx Board Type"
depends on PPC_82xx
default MPC82xx_ADS
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index 47cb09f08052..da20832b27f1 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -49,7 +49,7 @@
#include <linux/fs_enet_pd.h>
#include <sysdev/fsl_soc.h>
-#include <../sysdev/cpm2_pic.h>
+#include <sysdev/cpm2_pic.h>
#include "pq2ads.h"
@@ -507,7 +507,8 @@ void m82xx_pci_init_irq(void)
return;
}
-static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
+static int m82xx_pci_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn)
{
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -515,7 +516,7 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
return PCIBIOS_SUCCESSFUL;
}
-void __init add_bridge(struct device_node *np)
+static void __init mpc82xx_add_bridge(struct device_node *np)
{
int len;
struct pci_controller *hose;
@@ -542,19 +543,13 @@ void __init add_bridge(struct device_node *np)
pci_assign_all_buses = 1;
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(np);
if (!hose)
return;
- hose->arch_data = np;
- hose->set_cfg_type = 1;
-
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
- hose->bus_offset = 0;
-
- hose->set_cfg_type = 1;
setup_indirect_pci(hose,
r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
@@ -584,7 +579,7 @@ static void __init mpc82xx_ads_setup_arch(void)
#ifdef CONFIG_PCI
ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc82xx_add_bridge(np);
of_node_put(np);
#endif
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 19cafdf6df93..ec305f18abd8 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,5 +1,5 @@
choice
- prompt "Machine Type"
+ prompt "83xx Board Type"
depends on PPC_83xx
default MPC834x_MDS
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 31a91b53f528..5a98f885779f 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for the PowerPC 83xx linux kernel.
#
-obj-y := misc.o
+obj-y := misc.o usb.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 96970ac887ee..3edfe170a03b 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -28,11 +28,6 @@
#define DBG(fmt...)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
/* ************************************************************************
*
* Setup the architecture
@@ -49,10 +44,11 @@ static void __init mpc8313_rdb_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc83xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
+ mpc831x_usb_cfg();
}
void __init mpc8313_rdb_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 94843ed52a93..b39cb52c6fb9 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -49,11 +49,6 @@
#define DBG(fmt...)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
static u8 *bcsr_regs = NULL;
/* ************************************************************************
@@ -80,7 +75,7 @@ static void __init mpc832x_sys_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc83xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 3db68b73fc32..b2b28a44738c 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -32,11 +32,6 @@
#define DBG(fmt...)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
/* ************************************************************************
*
* Setup the architecture
@@ -53,7 +48,7 @@ static void __init mpc832x_rdb_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc83xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 40a01947d684..47ba5446f63c 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -38,11 +38,6 @@
#include "mpc83xx.h"
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
/* ************************************************************************
*
* Setup the architecture
@@ -59,10 +54,12 @@ static void __init mpc834x_itx_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc83xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
+
+ mpc834x_usb_cfg();
}
static void __init mpc834x_itx_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 10394b2d7e7a..4c9ff9cadfe4 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -38,61 +38,17 @@
#include "mpc83xx.h"
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
#define BCSR5_INT_USB 0x02
-/* Note: This is only for PB, not for PB+PIB
- * On PB only port0 is connected using ULPI */
-static int mpc834x_usb_cfg(void)
+static int mpc834xemds_usb_cfg(void)
{
- unsigned long sccr, sicrl;
- void __iomem *immap;
+ struct device_node *np;
void __iomem *bcsr_regs = NULL;
u8 bcsr5;
- struct device_node *np = NULL;
- int port0_is_dr = 0;
-
- if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL)
- port0_is_dr = 1;
- if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){
- if (port0_is_dr) {
- printk(KERN_WARNING
- "There is only one USB port on PB board! \n");
- return -1;
- } else if (!port0_is_dr)
- /* No usb port enabled */
- return -1;
- }
-
- immap = ioremap(get_immrbase(), 0x1000);
- if (!immap)
- return -1;
-
- /* Configure clock */
- sccr = in_be32(immap + MPC83XX_SCCR_OFFS);
- if (port0_is_dr)
- sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */
- else
- sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
- out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
-
- /* Configure Pin */
- sicrl = in_be32(immap + MPC83XX_SICRL_OFFS);
- /* set port0 only */
- if (port0_is_dr)
- sicrl |= MPC83XX_SICRL_USB0;
- else
- sicrl &= ~(MPC83XX_SICRL_USB0);
- out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
-
- iounmap(immap);
+ mpc834x_usb_cfg();
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
- if (np != 0) {
+ if (np) {
struct resource res;
of_address_to_resource(np, 0, &res);
@@ -129,12 +85,12 @@ static void __init mpc834x_mds_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc83xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
- mpc834x_usb_cfg();
+ mpc834xemds_usb_cfg();
}
static void __init mpc834x_mds_init_IRQ(void)
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index bceeff8bbfd2..0e615fd65c1f 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -55,11 +55,6 @@
#define DBG(fmt...)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
static u8 *bcsr_regs = NULL;
/* ************************************************************************
@@ -86,7 +81,7 @@ static void __init mpc836x_mds_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc83xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 9cd03b59c8f4..589ee55730f3 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -3,9 +3,11 @@
#include <linux/init.h>
#include <linux/device.h>
+#include <asm/pci-bridge.h>
/* System Clock Control Register */
#define MPC83XX_SCCR_OFFS 0xA08
+#define MPC83XX_SCCR_USB_MASK 0x00f00000
#define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000
#define MPC83XX_SCCR_USB_MPHCM_01 0x00400000
#define MPC83XX_SCCR_USB_MPHCM_10 0x00800000
@@ -15,21 +17,43 @@
/* system i/o configuration register low */
#define MPC83XX_SICRL_OFFS 0x114
-#define MPC83XX_SICRL_USB0 0x40000000
-#define MPC83XX_SICRL_USB1 0x20000000
+#define MPC834X_SICRL_USB_MASK 0x60000000
+#define MPC834X_SICRL_USB0 0x40000000
+#define MPC834X_SICRL_USB1 0x20000000
+#define MPC831X_SICRL_USB_MASK 0x00000c00
+#define MPC831X_SICRL_USB_ULPI 0x00000800
/* system i/o configuration register high */
#define MPC83XX_SICRH_OFFS 0x118
-#define MPC83XX_SICRH_USB_UTMI 0x00020000
+#define MPC834X_SICRH_USB_UTMI 0x00020000
+#define MPC831X_SICRH_USB_MASK 0x000000e0
+#define MPC831X_SICRH_USB_ULPI 0x000000a0
+
+/* USB Control Register */
+#define FSL_USB2_CONTROL_OFFS 0x500
+#define CONTROL_UTMI_PHY_EN 0x00000200
+#define CONTROL_REFSEL_48MHZ 0x00000080
+#define CONTROL_PHY_CLK_SEL_ULPI 0x00000400
+#define CONTROL_OTG_PORT 0x00000020
+
+/* USB PORTSC Registers */
+#define FSL_USB2_PORTSC1_OFFS 0x184
+#define FSL_USB2_PORTSC2_OFFS 0x188
+#define PORTSCX_PTW_16BIT 0x10000000
+#define PORTSCX_PTS_UTMI 0x00000000
+#define PORTSCX_PTS_ULPI 0x80000000
/*
* Declaration for the various functions exported by the
* mpc83xx_* files. Mostly for use by mpc83xx_setup
*/
-extern int add_bridge(struct device_node *dev);
-extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern int mpc83xx_add_bridge(struct device_node *dev);
+extern int mpc83xx_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn);
extern void mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);
+extern int mpc834x_usb_cfg(void);
+extern int mpc831x_usb_cfg(void);
#endif /* __MPC83XX_H__ */
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 774457d09e94..c0e2b89154e5 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -33,19 +33,14 @@
#define DBG(x...)
#endif
-int mpc83xx_pci2_busno;
-
-int mpc83xx_exclude_device(u_char bus, u_char devfn)
+int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
{
- if (bus == 0 && PCI_SLOT(devfn) == 0)
+ if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (mpc83xx_pci2_busno)
- if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
}
-int __init add_bridge(struct device_node *dev)
+int __init mpc83xx_add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
@@ -66,11 +61,10 @@ int __init add_bridge(struct device_node *dev)
" bus 0\n", dev->full_name);
}
- hose = pcibios_alloc_controller();
+ pci_assign_all_buses = 1;
+ hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
- hose->arch_data = dev;
- hose->set_cfg_type = 1;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -86,8 +80,6 @@ int __init add_bridge(struct device_node *dev)
if ((rsrc.start & 0xfffff) == 0x8600) {
setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
primary = 0;
- hose->bus_offset = hose->first_busno;
- mpc83xx_pci2_busno = hose->first_busno;
}
printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
new file mode 100644
index 000000000000..e7fdf013cd39
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -0,0 +1,181 @@
+/*
+ * Freescale 83xx USB SOC setup code
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ * Author: Li Yang
+ *
+ * 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+
+#ifdef CONFIG_MPC834x
+int mpc834x_usb_cfg(void)
+{
+ unsigned long sccr, sicrl, sicrh;
+ void __iomem *immap;
+ struct device_node *np = NULL;
+ int port0_is_dr = 0, port1_is_dr = 0;
+ const void *prop, *dr_mode;
+
+ immap = ioremap(get_immrbase(), 0x1000);
+ if (!immap)
+ return -ENOMEM;
+
+ /* Read registers */
+ /* Note: DR and MPH must use the same clock setting in SCCR */
+ sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;
+ sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
+ sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
+
+ np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+ if (np) {
+ sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */
+
+ prop = of_get_property(np, "phy_type", NULL);
+ if (prop && (!strcmp(prop, "utmi") ||
+ !strcmp(prop, "utmi_wide"))) {
+ sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+ sicrh |= MPC834X_SICRH_USB_UTMI;
+ port1_is_dr = 1;
+ } else if (prop && !strcmp(prop, "serial")) {
+ dr_mode = of_get_property(np, "dr_mode", NULL);
+ if (dr_mode && !strcmp(dr_mode, "otg")) {
+ sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+ port1_is_dr = 1;
+ } else {
+ sicrl |= MPC834X_SICRL_USB0;
+ }
+ } else if (prop && !strcmp(prop, "ulpi")) {
+ sicrl |= MPC834X_SICRL_USB0;
+ } else {
+ printk(KERN_WARNING "834x USB PHY type not supported\n");
+ }
+ port0_is_dr = 1;
+ of_node_put(np);
+ }
+ np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph");
+ if (np) {
+ sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
+
+ prop = of_get_property(np, "port0", NULL);
+ if (prop) {
+ if (port0_is_dr)
+ printk(KERN_WARNING
+ "834x USB port0 can't be used by both DR and MPH!\n");
+ sicrl |= MPC834X_SICRL_USB0;
+ }
+ prop = of_get_property(np, "port1", NULL);
+ if (prop) {
+ if (port1_is_dr)
+ printk(KERN_WARNING
+ "834x USB port1 can't be used by both DR and MPH!\n");
+ sicrl |= MPC834X_SICRL_USB1;
+ }
+ of_node_put(np);
+ }
+
+ /* Write back */
+ out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
+ out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
+ out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
+
+ iounmap(immap);
+ return 0;
+}
+#endif /* CONFIG_MPC834x */
+
+#ifdef CONFIG_PPC_MPC831x
+int mpc831x_usb_cfg(void)
+{
+ u32 temp;
+ void __iomem *immap, *usb_regs;
+ struct device_node *np = NULL;
+ const void *prop;
+ struct resource res;
+ int ret = 0;
+#ifdef CONFIG_USB_OTG
+ const void *dr_mode;
+#endif
+
+ np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+ if (!np)
+ return -ENODEV;
+ prop = of_get_property(np, "phy_type", NULL);
+
+ /* Map IMMR space for pin and clock settings */
+ immap = ioremap(get_immrbase(), 0x1000);
+ if (!immap) {
+ of_node_put(np);
+ return -ENOMEM;
+ }
+
+ /* Configure clock */
+ temp = in_be32(immap + MPC83XX_SCCR_OFFS);
+ temp &= ~MPC83XX_SCCR_USB_MASK;
+ temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */
+ out_be32(immap + MPC83XX_SCCR_OFFS, temp);
+
+ /* Configure pin mux for ULPI. There is no pin mux for UTMI */
+ if (!strcmp(prop, "ulpi")) {
+ temp = in_be32(immap + MPC83XX_SICRL_OFFS);
+ temp &= ~MPC831X_SICRL_USB_MASK;
+ temp |= MPC831X_SICRL_USB_ULPI;
+ out_be32(immap + MPC83XX_SICRL_OFFS, temp);
+
+ temp = in_be32(immap + MPC83XX_SICRH_OFFS);
+ temp &= ~MPC831X_SICRH_USB_MASK;
+ temp |= MPC831X_SICRH_USB_ULPI;
+ out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+ }
+
+ iounmap(immap);
+
+ /* Map USB SOC space */
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret) {
+ of_node_put(np);
+ return ret;
+ }
+ usb_regs = ioremap(res.start, res.end - res.start + 1);
+
+ /* Using on-chip PHY */
+ if (!strcmp(prop, "utmi_wide") ||
+ !strcmp(prop, "utmi")) {
+ /* Set UTMI_PHY_EN, REFSEL to 48MHZ */
+ out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
+ CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
+ /* Using external UPLI PHY */
+ } else if (!strcmp(prop, "ulpi")) {
+ /* Set PHY_CLK_SEL to ULPI */
+ temp = CONTROL_PHY_CLK_SEL_ULPI;
+#ifdef CONFIG_USB_OTG
+ /* Set OTG_PORT */
+ dr_mode = of_get_property(np, "dr_mode", NULL);
+ if (dr_mode && !strcmp(dr_mode, "otg"))
+ temp |= CONTROL_OTG_PORT;
+#endif /* CONFIG_USB_OTG */
+ out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
+ } else {
+ printk(KERN_WARNING "831x USB PHY type not supported\n");
+ ret = -EINVAL;
+ }
+
+ iounmap(usb_regs);
+ of_node_put(np);
+ return ret;
+}
+#endif /* CONFIG_PPC_MPC831x */
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c
index 3e62fcb04c1c..4fe376e9c3b6 100644
--- a/arch/powerpc/platforms/85xx/misc.c
+++ b/arch/powerpc/platforms/85xx/misc.c
@@ -13,11 +13,43 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+static __be32 __iomem *rstcr;
extern void abort(void);
+static int __init mpc85xx_rstcr(void)
+{
+ struct device_node *np;
+ np = of_find_node_by_name(NULL, "global-utilities");
+ if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
+ const u32 *prop = of_get_property(np, "reg", NULL);
+ if (prop) {
+ /* map reset control register
+ * 0xE00B0 is offset of reset control register
+ */
+ rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
+ if (!rstcr)
+ printk (KERN_EMERG "Error: reset control "
+ "register not mapped!\n");
+ }
+ } else
+ printk (KERN_INFO "rstcr compatible register does not exist!\n");
+ if (np)
+ of_node_put(np);
+ return 0;
+}
+
+arch_initcall(mpc85xx_rstcr);
+
void mpc85xx_restart(char *cmd)
{
local_irq_disable();
+ if (rstcr)
+ /* set reset control register */
+ out_be32(rstcr, 0x2); /* HRESET_REQ */
abort();
}
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c
index bec84ffe708e..6fb90aab879f 100644
--- a/arch/powerpc/platforms/85xx/mpc8544_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c
@@ -61,24 +61,11 @@ void __init mpc8544_ds_pic_init(void)
return;
}
- /* Alloc mpic structure and per isu has 16 INT entries. */
mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 16, 64, " OPENPIC ");
+ 0, 256, " OpenPIC ");
BUG_ON(mpic == NULL);
- /*
- * 48 Internal Interrupts
- */
- mpic_assign_isu(mpic, 0, r.start + 0x10200);
- mpic_assign_isu(mpic, 1, r.start + 0x10400);
- mpic_assign_isu(mpic, 2, r.start + 0x10600);
-
- /*
- * 16 External interrupts
- */
- mpic_assign_isu(mpic, 3, r.start + 0x10000);
-
mpic_init(mpic);
#ifdef CONFIG_PPC_I8259
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index 83415db33378..7286ffac2c1d 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -15,4 +15,4 @@
*/
extern void mpc85xx_restart(char *);
-extern int add_bridge(struct device_node *dev);
+extern int mpc85xx_add_bridge(struct device_node *dev);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 5d27621f0927..7235f702394c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -38,13 +38,9 @@
#include <asm/fs_pd.h>
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
#ifdef CONFIG_PCI
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn)
{
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -91,30 +87,10 @@ static void __init mpc85xx_ads_pic_init(void)
mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 4, 0, " OpenPIC ");
+ 0, 256, " OpenPIC ");
BUG_ON(mpic == NULL);
of_node_put(np);
- mpic_assign_isu(mpic, 0, r.start + 0x10200);
- mpic_assign_isu(mpic, 1, r.start + 0x10280);
- mpic_assign_isu(mpic, 2, r.start + 0x10300);
- mpic_assign_isu(mpic, 3, r.start + 0x10380);
- mpic_assign_isu(mpic, 4, r.start + 0x10400);
- mpic_assign_isu(mpic, 5, r.start + 0x10480);
- mpic_assign_isu(mpic, 6, r.start + 0x10500);
- mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
- /* Unused on this platform (leave room for 8548) */
- mpic_assign_isu(mpic, 8, r.start + 0x10600);
- mpic_assign_isu(mpic, 9, r.start + 0x10680);
- mpic_assign_isu(mpic, 10, r.start + 0x10700);
- mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
- /* External Interrupts */
- mpic_assign_isu(mpic, 12, r.start + 0x10000);
- mpic_assign_isu(mpic, 13, r.start + 0x10080);
- mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
mpic_init(mpic);
#ifdef CONFIG_CPM2
@@ -241,7 +217,7 @@ static void __init mpc85xx_ads_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc85xx_add_bridge(np);
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
}
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 1490eb3ce0d3..50c8d6458362 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -47,11 +47,6 @@
#include <sysdev/fsl_soc.h>
#include "mpc85xx.h"
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
static int cds_pci_slot = 2;
static volatile u8 *cadmus;
@@ -60,15 +55,11 @@ static volatile u8 *cadmus;
#define ARCADIA_HOST_BRIDGE_IDSEL 17
#define ARCADIA_2ND_BRIDGE_IDSEL 3
-extern int mpc85xx_pci2_busno;
-
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn)
{
- if (bus == 0 && PCI_SLOT(devfn) == 0)
+ if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (mpc85xx_pci2_busno)
- if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
/* We explicitly do not go past the Tundra 320 Bridge */
if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -78,52 +69,44 @@ static int mpc85xx_exclude_device(u_char bus, u_char devfn)
return PCIBIOS_SUCCESSFUL;
}
-static void __init mpc85xx_cds_pcibios_fixup(void)
+static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev)
{
- struct pci_dev *dev;
- u_char c;
-
- if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+ u_char c;
+ if (dev->vendor == PCI_VENDOR_ID_VIA) {
+ switch (dev->device) {
+ case PCI_DEVICE_ID_VIA_82C586_1:
+ /*
+ * U-Boot does not set the enable bits
+ * for the IDE device. Force them on here.
+ */
+ pci_read_config_byte(dev, 0x40, &c);
+ c |= 0x03; /* IDE: Chip Enable Bits */
+ pci_write_config_byte(dev, 0x40, c);
+
+ /*
+ * Since only primary interface works, force the
+ * IDE function to standard primary IDE interrupt
+ * w/ 8259 offset
+ */
+ dev->irq = 14;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ break;
/*
- * U-Boot does not set the enable bits
- * for the IDE device. Force them on here.
+ * Force legacy USB interrupt routing
*/
- pci_read_config_byte(dev, 0x40, &c);
- c |= 0x03; /* IDE: Chip Enable Bits */
- pci_write_config_byte(dev, 0x40, c);
-
- /*
- * Since only primary interface works, force the
- * IDE function to standard primary IDE interrupt
- * w/ 8259 offset
+ case PCI_DEVICE_ID_VIA_82C586_2:
+ /* There are two USB controllers.
+ * Identify them by functon number
*/
- dev->irq = 14;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- pci_dev_put(dev);
- }
-
- /*
- * Force legacy USB interrupt routing
- */
- if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
- dev->irq = 10;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
- pci_dev_put(dev);
- }
-
- if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_2, dev))) {
- dev->irq = 11;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
- pci_dev_put(dev);
+ if (PCI_FUNC(dev->devfn))
+ dev->irq = 11;
+ else
+ dev->irq = 10;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ default:
+ break;
+ }
}
-
- /* Now map all the PCI irqs */
- dev = NULL;
- for_each_pci_dev(dev)
- pci_read_irq_line(dev);
}
#ifdef CONFIG_PPC_I8259
@@ -165,33 +148,12 @@ static void __init mpc85xx_cds_pic_init(void)
mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 4, 0, " OpenPIC ");
+ 0, 256, " OpenPIC ");
BUG_ON(mpic == NULL);
/* Return the mpic node */
of_node_put(np);
- mpic_assign_isu(mpic, 0, r.start + 0x10200);
- mpic_assign_isu(mpic, 1, r.start + 0x10280);
- mpic_assign_isu(mpic, 2, r.start + 0x10300);
- mpic_assign_isu(mpic, 3, r.start + 0x10380);
- mpic_assign_isu(mpic, 4, r.start + 0x10400);
- mpic_assign_isu(mpic, 5, r.start + 0x10480);
- mpic_assign_isu(mpic, 6, r.start + 0x10500);
- mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
- /* Used only for 8548 so far, but no harm in
- * allocating them for everyone */
- mpic_assign_isu(mpic, 8, r.start + 0x10600);
- mpic_assign_isu(mpic, 9, r.start + 0x10680);
- mpic_assign_isu(mpic, 10, r.start + 0x10700);
- mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
- /* External Interrupts */
- mpic_assign_isu(mpic, 12, r.start + 0x10000);
- mpic_assign_isu(mpic, 13, r.start + 0x10080);
- mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
mpic_init(mpic);
#ifdef CONFIG_PPC_I8259
@@ -257,9 +219,9 @@ static void __init mpc85xx_cds_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ mpc85xx_add_bridge(np);
- ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+ ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
}
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index e3dddbfe66ff..004b80bd0b84 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -59,11 +59,6 @@
#define DBG(fmt...)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
/* ************************************************************************
*
* Setup the architecture
@@ -100,7 +95,7 @@ static void __init mpc85xx_mds_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) {
- add_bridge(np);
+ mpc85xx_add_bridge(np);
}
of_node_put(np);
#endif
@@ -181,29 +176,10 @@ static void __init mpc85xx_mds_pic_init(void)
mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 4, 0, " OpenPIC ");
+ 0, 256, " OpenPIC ");
BUG_ON(mpic == NULL);
of_node_put(np);
- /* Internal Interrupts */
- mpic_assign_isu(mpic, 0, r.start + 0x10200);
- mpic_assign_isu(mpic, 1, r.start + 0x10280);
- mpic_assign_isu(mpic, 2, r.start + 0x10300);
- mpic_assign_isu(mpic, 3, r.start + 0x10380);
- mpic_assign_isu(mpic, 4, r.start + 0x10400);
- mpic_assign_isu(mpic, 5, r.start + 0x10480);
- mpic_assign_isu(mpic, 6, r.start + 0x10500);
- mpic_assign_isu(mpic, 7, r.start + 0x10580);
- mpic_assign_isu(mpic, 8, r.start + 0x10600);
- mpic_assign_isu(mpic, 9, r.start + 0x10680);
- mpic_assign_isu(mpic, 10, r.start + 0x10700);
- mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
- /* External Interrupts */
- mpic_assign_isu(mpic, 12, r.start + 0x10000);
- mpic_assign_isu(mpic, 13, r.start + 0x10080);
- mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
mpic_init(mpic);
#ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c
index 48f17e23d771..8118417b7364 100644
--- a/arch/powerpc/platforms/85xx/pci.c
+++ b/arch/powerpc/platforms/85xx/pci.c
@@ -33,10 +33,8 @@
#define DBG(x...)
#endif
-int mpc85xx_pci2_busno = 0;
-
#ifdef CONFIG_PCI
-int __init add_bridge(struct device_node *dev)
+int __init mpc85xx_add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
@@ -57,11 +55,10 @@ int __init add_bridge(struct device_node *dev)
" bus 0\n", dev->full_name);
}
- hose = pcibios_alloc_controller();
+ pci_assign_all_buses = 1;
+ hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
- hose->arch_data = dev;
- hose->set_cfg_type = 1;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -74,8 +71,6 @@ int __init add_bridge(struct device_node *dev)
if ((rsrc.start & 0xfffff) == 0x9000) {
setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004);
primary = 0;
- hose->bus_offset = hose->first_busno;
- mpc85xx_pci2_busno = hose->first_busno;
}
printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index d1bcff500464..0faebfdc1596 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,5 +1,5 @@
choice
- prompt "Machine Type"
+ prompt "86xx Board Type"
depends on PPC_86xx
default MPC8641_HPCN
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index 2834462590b8..23f7ed2a7f88 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -15,15 +15,10 @@
* mpc86xx_* files. Mostly for use by mpc86xx_setup().
*/
-extern int add_bridge(struct device_node *dev);
+extern int mpc86xx_add_bridge(struct device_node *dev);
-extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
-
-extern void setup_indirect_pcie(struct pci_controller *hose,
- u32 cfg_addr, u32 cfg_data);
-extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
- void __iomem *cfg_addr,
- void __iomem *cfg_data);
+extern int mpc86xx_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn);
extern void __init mpc86xx_smp_init(void);
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 1051702c8d4f..5b01ec7c13dc 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -44,13 +44,6 @@
#define DBG(fmt...) do { } while(0)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-unsigned long pci_dram_offset = 0;
-#endif
-
-
#ifdef CONFIG_PCI
static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
{
@@ -81,22 +74,9 @@ mpc86xx_hpcn_init_irq(void)
/* Alloc mpic structure and per isu has 16 INT entries. */
mpic1 = mpic_alloc(np, res.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 16, NR_IRQS - 4,
- " MPIC ");
+ 0, 256, " MPIC ");
BUG_ON(mpic1 == NULL);
- mpic_assign_isu(mpic1, 0, res.start + 0x10000);
-
- /* 48 Internal Interrupts */
- mpic_assign_isu(mpic1, 1, res.start + 0x10200);
- mpic_assign_isu(mpic1, 2, res.start + 0x10400);
- mpic_assign_isu(mpic1, 3, res.start + 0x10600);
-
- /* 16 External interrupts
- * Moving them from [0 - 15] to [64 - 79]
- */
- mpic_assign_isu(mpic1, 4, res.start + 0x10000);
-
mpic_init(mpic1);
#ifdef CONFIG_PCI
@@ -319,6 +299,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
{
unsigned short temp;
pci_write_config_word(dev, 0x04, 0x0405);
+ dev->class &= ~0x5;
pci_read_config_word(dev, 0x4a, &temp);
temp |= 0x1000;
pci_write_config_word(dev, 0x4a, temp);
@@ -364,9 +345,7 @@ mpc86xx_hpcn_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
-
- ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+ mpc86xx_add_bridge(np);
#endif
printk("MPC86xx HPCN board from Freescale Semiconductor\n");
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index 8235c562661f..73cd5b05a84e 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -122,7 +122,6 @@ static void __init
mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
{
u16 cmd;
- unsigned int temps;
DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
pcie_offset, pcie_size);
@@ -133,22 +132,49 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
-
- /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
- early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
- temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
- early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
}
-int mpc86xx_exclude_device(u_char bus, u_char devfn)
+static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev)
{
- if (bus == 0 && PCI_SLOT(devfn) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
+ struct resource *res;
+ int i, res_idx = PCI_BRIDGE_RESOURCES;
+ struct pci_controller *hose;
- return PCIBIOS_SUCCESSFUL;
+ /*
+ * Make the bridge be transparent.
+ */
+ dev->transparent = 1;
+
+ hose = pci_bus_to_host(dev->bus);
+ if (!hose) {
+ printk(KERN_ERR "Can't find hose for bus %d\n",
+ dev->bus->number);
+ return;
+ }
+
+ if (hose->io_resource.flags) {
+ res = &dev->resource[res_idx++];
+ res->start = hose->io_resource.start;
+ res->end = hose->io_resource.end;
+ res->flags = hose->io_resource.flags;
+ }
+
+ for (i = 0; i < 3; i++) {
+ res = &dev->resource[res_idx + i];
+ res->start = hose->mem_resources[i].start;
+ res->end = hose->mem_resources[i].end;
+ res->flags = hose->mem_resources[i].flags;
+ }
}
-int __init add_bridge(struct device_node *dev)
+
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent);
+
+#define PCIE_LTSSM 0x404 /* PCIe Link Training and Status */
+#define PCIE_LTSSM_L0 0x16 /* L0 state */
+
+int __init mpc86xx_add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
@@ -156,6 +182,7 @@ int __init add_bridge(struct device_node *dev)
const int *bus_range;
int has_address = 0;
int primary = 0;
+ u16 val;
DBG("Adding PCIE host bridge %s\n", dev->full_name);
@@ -168,17 +195,23 @@ int __init add_bridge(struct device_node *dev)
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
- hose = pcibios_alloc_controller();
+ pci_assign_all_buses = 1;
+ hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
- hose->arch_data = dev;
- hose->set_cfg_type = 1;
- /* last_busno = 0xfe cause by MPC8641 PCIE bug */
+ hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG |
+ PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
+
hose->first_busno = bus_range ? bus_range[0] : 0x0;
- hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4);
- setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+ /* Probe the hose link training status */
+ early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val);
+ if (val < PCIE_LTSSM_L0)
+ return -ENXIO;
/* Setup the PCIE host controller. */
mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 0901dbada350..f1693550c70c 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -32,6 +32,7 @@
#include <linux/root_dev.h>
#include <linux/time.h>
#include <linux/rtc.h>
+#include <linux/fsl_devices.h>
#include <asm/mmu.h>
#include <asm/reg.h>
@@ -49,6 +50,10 @@
#include "sysdev/mpc8xx_pic.h"
+#ifdef CONFIG_PCMCIA_M8XX
+struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
void m8xx_calibrate_decr(void);
extern void m8xx_wdt_handler_install(bd_t *bp);
extern int cpm_pic_init(void);
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index c36e475d93dc..5a808d611ae3 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -22,6 +22,7 @@
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
+#include <linux/fsl_devices.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -39,7 +40,7 @@
#include <asm/prom.h>
extern void cpm_reset(void);
-extern void mpc8xx_show_cpuinfo(struct seq_file*);
+extern void mpc8xx_show_cpuinfo(struct seq_file *);
extern void mpc8xx_restart(char *cmd);
extern void mpc8xx_calibrate_decr(void);
extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
@@ -47,9 +48,73 @@ extern void mpc8xx_get_rtc_time(struct rtc_time *tm);
extern void m8xx_pic_init(void);
extern unsigned int mpc8xx_get_irq(void);
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_scc3_ioports(struct fs_platform_info* ptr);
+static void init_smc1_uart_ioports(struct fs_uart_platform_info *fpi);
+static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi);
+static void init_scc3_ioports(struct fs_platform_info *ptr);
+
+#ifdef CONFIG_PCMCIA_M8XX
+static void pcmcia_hw_setup(int slot, int enable)
+{
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+ if (enable)
+ clrbits32(bcsr_io, BCSR1_PCCEN);
+ else
+ setbits32(bcsr_io, BCSR1_PCCEN);
+
+ iounmap(bcsr_io);
+}
+
+static int pcmcia_set_voltage(int slot, int vcc, int vpp)
+{
+ u32 reg = 0;
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ switch (vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= BCSR1_PCCVCC0;
+ break;
+ case 50:
+ reg |= BCSR1_PCCVCC1;
+ break;
+ default:
+ return 1;
+ }
+
+ switch (vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if (vcc == vpp)
+ reg |= BCSR1_PCCVPP1;
+ else
+ return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= BCSR1_PCCVPP0;
+ else
+ return 1;
+ default:
+ return 1;
+ }
+
+ /* first, turn off all power */
+ clrbits32(bcsr_io, 0x00610000);
+
+ /* enable new powersettings */
+ setbits32(bcsr_io, reg);
+
+ iounmap(bcsr_io);
+ return 0;
+}
+#endif
void __init mpc885ads_board_setup(void)
{
@@ -62,7 +127,7 @@ void __init mpc885ads_board_setup(void)
#endif
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
- cp = (cpm8xx_t *)immr_map(im_cpm);
+ cp = (cpm8xx_t *) immr_map(im_cpm);
if (bcsr_io == NULL) {
printk(KERN_CRIT "Could not remap BCSR\n");
@@ -75,13 +140,13 @@ void __init mpc885ads_board_setup(void)
out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); /* brg1 */
#else
- setbits32(bcsr_io,BCSR1_RS232EN_1);
+ setbits32(bcsr_io, BCSR1_RS232EN_1);
out_be16(&cp->cp_smc[0].smc_smcmr, 0);
out_8(&cp->cp_smc[0].smc_smce, 0);
#endif
#ifdef CONFIG_SERIAL_CPM_SMC2
- clrbits32(bcsr_io,BCSR1_RS232EN_2);
+ clrbits32(bcsr_io, BCSR1_RS232EN_2);
clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */
tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
@@ -90,7 +155,7 @@ void __init mpc885ads_board_setup(void)
init_smc2_uart_ioports(0);
#else
- setbits32(bcsr_io,BCSR1_RS232EN_2);
+ setbits32(bcsr_io, BCSR1_RS232EN_2);
out_be16(&cp->cp_smc[1].smc_smcmr, 0);
out_8(&cp->cp_smc[1].smc_smce, 0);
#endif
@@ -99,29 +164,34 @@ void __init mpc885ads_board_setup(void)
#ifdef CONFIG_FS_ENET
/* use MDC for MII (common) */
- io_port = (iop8xx_t*)immr_map(im_ioport);
+ io_port = (iop8xx_t *) immr_map(im_ioport);
setbits16(&io_port->iop_pdpar, 0x0080);
clrbits16(&io_port->iop_pddir, 0x0080);
bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
- clrbits32(bcsr_io,BCSR5_MII1_EN);
- clrbits32(bcsr_io,BCSR5_MII1_RST);
+ clrbits32(bcsr_io, BCSR5_MII1_EN);
+ clrbits32(bcsr_io, BCSR5_MII1_RST);
#ifndef CONFIG_FC_ENET_HAS_SCC
- clrbits32(bcsr_io,BCSR5_MII2_EN);
- clrbits32(bcsr_io,BCSR5_MII2_RST);
+ clrbits32(bcsr_io, BCSR5_MII2_EN);
+ clrbits32(bcsr_io, BCSR5_MII2_RST);
#endif
iounmap(bcsr_io);
immr_unmap(io_port);
#endif
-}
+#ifdef CONFIG_PCMCIA_M8XX
+ /*Set up board specific hook-ups */
+ m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
+ m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
+#endif
+}
-static void init_fec1_ioports(struct fs_platform_info* ptr)
+static void init_fec1_ioports(struct fs_platform_info *ptr)
{
- cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
- iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+ cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm);
+ iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport);
/* configure FEC1 pins */
setbits16(&io_port->iop_papar, 0xf830);
@@ -143,11 +213,10 @@ static void init_fec1_ioports(struct fs_platform_info* ptr)
immr_unmap(cp);
}
-
-static void init_fec2_ioports(struct fs_platform_info* ptr)
+static void init_fec2_ioports(struct fs_platform_info *ptr)
{
- cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
- iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+ cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm);
+ iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport);
/* configure FEC2 pins */
setbits32(&cp->cp_pepar, 0x0003fffc);
@@ -177,15 +246,15 @@ void init_fec_ioports(struct fs_platform_info *fpi)
}
}
-static void init_scc3_ioports(struct fs_platform_info* fpi)
+static void init_scc3_ioports(struct fs_platform_info *fpi)
{
unsigned *bcsr_io;
iop8xx_t *io_port;
cpm8xx_t *cp;
bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
- io_port = (iop8xx_t *)immr_map(im_ioport);
- cp = (cpm8xx_t *)immr_map(im_cpm);
+ io_port = (iop8xx_t *) immr_map(im_ioport);
+ cp = (cpm8xx_t *) immr_map(im_cpm);
if (bcsr_io == NULL) {
printk(KERN_CRIT "Could not remap BCSR\n");
@@ -194,9 +263,9 @@ static void init_scc3_ioports(struct fs_platform_info* fpi)
/* Enable the PHY.
*/
- clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+ clrbits32(bcsr_io + 4, BCSR4_ETH10_RST);
udelay(1000);
- setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+ setbits32(bcsr_io + 4, BCSR4_ETH10_RST);
/* Configure port A pins for Txd and Rxd.
*/
setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
@@ -212,8 +281,7 @@ static void init_scc3_ioports(struct fs_platform_info* fpi)
*/
setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
clrbits32(&cp->cp_pepar, PE_ENET_TENA);
- clrbits32(&cp->cp_pedir,
- PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+ clrbits32(&cp->cp_pedir, PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
setbits32(&cp->cp_peso, PE_ENET_TENA);
@@ -237,7 +305,7 @@ static void init_scc3_ioports(struct fs_platform_info* fpi)
clrbits32(&cp->cp_pedir, PE_ENET_TENA);
setbits32(&cp->cp_peso, PE_ENET_TENA);
- setbits32(bcsr_io+4, BCSR1_ETHEN);
+ setbits32(bcsr_io + 4, BCSR1_ETHEN);
iounmap(bcsr_io);
immr_unmap(io_port);
immr_unmap(cp);
@@ -257,50 +325,48 @@ void init_scc_ioports(struct fs_platform_info *fpi)
}
}
-
-
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
+static void init_smc1_uart_ioports(struct fs_uart_platform_info *ptr)
{
- unsigned *bcsr_io;
+ unsigned *bcsr_io;
cpm8xx_t *cp;
- cp = (cpm8xx_t *)immr_map(im_cpm);
+ cp = (cpm8xx_t *) immr_map(im_cpm);
setbits32(&cp->cp_pepar, 0x000000c0);
clrbits32(&cp->cp_pedir, 0x000000c0);
clrbits32(&cp->cp_peso, 0x00000040);
setbits32(&cp->cp_peso, 0x00000080);
immr_unmap(cp);
- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
- if (bcsr_io == NULL) {
- printk(KERN_CRIT "Could not remap BCSR1\n");
- return;
- }
- clrbits32(bcsr_io,BCSR1_RS232EN_1);
- iounmap(bcsr_io);
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+ clrbits32(bcsr_io, BCSR1_RS232EN_1);
+ iounmap(bcsr_io);
}
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
+static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi)
{
- unsigned *bcsr_io;
+ unsigned *bcsr_io;
cpm8xx_t *cp;
- cp = (cpm8xx_t *)immr_map(im_cpm);
+ cp = (cpm8xx_t *) immr_map(im_cpm);
setbits32(&cp->cp_pepar, 0x00000c00);
clrbits32(&cp->cp_pedir, 0x00000c00);
clrbits32(&cp->cp_peso, 0x00000400);
setbits32(&cp->cp_peso, 0x00000800);
immr_unmap(cp);
- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
- if (bcsr_io == NULL) {
- printk(KERN_CRIT "Could not remap BCSR1\n");
- return;
- }
- clrbits32(bcsr_io,BCSR1_RS232EN_2);
- iounmap(bcsr_io);
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+ clrbits32(bcsr_io, BCSR1_RS232EN_2);
+ iounmap(bcsr_io);
}
void init_smc_ioports(struct fs_uart_platform_info *data)
@@ -373,15 +439,11 @@ static int __init mpc885ads_probe(void)
return 1;
}
-define_machine(mpc885_ads) {
- .name = "MPC885 ADS",
- .probe = mpc885ads_probe,
- .setup_arch = mpc885ads_setup_arch,
- .init_IRQ = m8xx_pic_init,
- .show_cpuinfo = mpc8xx_show_cpuinfo,
- .get_irq = mpc8xx_get_irq,
- .restart = mpc8xx_restart,
- .calibrate_decr = mpc8xx_calibrate_decr,
- .set_rtc_time = mpc8xx_set_rtc_time,
- .get_rtc_time = mpc8xx_get_rtc_time,
-};
+define_machine(mpc885_ads)
+{
+.name = "MPC885 ADS",.probe = mpc885ads_probe,.setup_arch =
+ mpc885ads_setup_arch,.init_IRQ =
+ m8xx_pic_init,.show_cpuinfo = mpc8xx_show_cpuinfo,.get_irq =
+ mpc8xx_get_irq,.restart = mpc8xx_restart,.calibrate_decr =
+ mpc8xx_calibrate_decr,.set_rtc_time =
+ mpc8xx_set_rtc_time,.get_rtc_time = mpc8xx_get_rtc_time,};
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 361acfa2894c..33545d352e92 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -2,7 +2,7 @@ menu "Platform support"
choice
prompt "Machine type"
- depends on PPC64 || CLASSIC32
+ depends on PPC64 || 6xx
default PPC_MULTIPLATFORM
config PPC_MULTIPLATFORM
@@ -16,15 +16,30 @@ config EMBEDDED6xx
bool "Embedded 6xx/7xx/7xxx-based board"
depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
-config APUS
- bool "Amiga-APUS"
- depends on PPC32 && BROKEN
+config PPC_82xx
+ bool "Freescale 82xx"
+ depends on 6xx
+
+config PPC_83xx
+ bool "Freescale 83xx"
+ depends on 6xx
+ select FSL_SOC
+ select 83xx
+ select WANT_DEVICE_TREE
+
+config PPC_86xx
+ bool "Freescale 86xx"
+ depends on 6xx
+ select FSL_SOC
+ select ALTIVEC
help
- Select APUS if configuring for a PowerUP Amiga.
- More information is available at:
- <http://linux-apus.sourceforge.net/>.
+ The Freescale E600 SoCs have 74xx cores.
endchoice
+config CLASSIC32
+ def_bool y
+ depends on 6xx && PPC_MULTIPLATFORM
+
source "arch/powerpc/platforms/pseries/Kconfig"
source "arch/powerpc/platforms/iseries/Kconfig"
source "arch/powerpc/platforms/chrp/Kconfig"
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
new file mode 100644
index 000000000000..b8b5fde94668
--- /dev/null
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -0,0 +1,221 @@
+config PPC64
+ bool "64-bit kernel"
+ default n
+ help
+ This option selects whether a 32-bit or a 64-bit kernel
+ will be built.
+
+menu "Processor support"
+choice
+ prompt "Processor Type"
+ depends on PPC32
+ default 6xx
+ help
+ There are five families of 32 bit PowerPC chips supported.
+ The most common ones are the desktop and server CPUs (601, 603,
+ 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their
+ embedded 52xx/82xx/83xx/86xx counterparts.
+ The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500
+ (85xx) each form a family of their own that is not compatible
+ with the others.
+
+ If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx.
+
+config 6xx
+ bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx"
+ select PPC_FPU
+
+config PPC_85xx
+ bool "Freescale 85xx"
+ select E500
+ select FSL_SOC
+ select 85xx
+ select WANT_DEVICE_TREE
+
+config PPC_8xx
+ bool "Freescale 8xx"
+ select FSL_SOC
+ select 8xx
+
+config 40x
+ bool "AMCC 40x"
+ select PPC_DCR_NATIVE
+
+config 44x
+ bool "AMCC 44x"
+ select PPC_DCR_NATIVE
+ select WANT_DEVICE_TREE
+
+config E200
+ bool "Freescale e200"
+
+endchoice
+
+config POWER4_ONLY
+ bool "Optimize for POWER4"
+ depends on PPC64
+ default n
+ ---help---
+ Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
+ The resulting binary will not work on POWER3 or RS64 processors
+ when compiled with binutils 2.15 or later.
+
+config POWER3
+ bool
+ depends on PPC64
+ default y if !POWER4_ONLY
+
+config POWER4
+ depends on PPC64
+ def_bool y
+
+config 6xx
+ bool
+
+# this is temp to handle compat with arch=ppc
+config 8xx
+ bool
+
+# this is temp to handle compat with arch=ppc
+config 83xx
+ bool
+
+# this is temp to handle compat with arch=ppc
+config 85xx
+ bool
+
+config E500
+ bool
+
+config PPC_FPU
+ bool
+ default y if PPC64
+
+config 4xx
+ bool
+ depends on 40x || 44x
+ default y
+
+config BOOKE
+ bool
+ depends on E200 || E500 || 44x
+ default y
+
+config FSL_BOOKE
+ bool
+ depends on E200 || E500
+ default y
+
+config PTE_64BIT
+ bool
+ depends on 44x || E500
+ default y if 44x
+ default y if E500 && PHYS_64BIT
+
+config PHYS_64BIT
+ bool 'Large physical address support' if E500
+ depends on 44x || E500
+ select RESOURCES_64BIT
+ default y if 44x
+ ---help---
+ This option enables kernel support for larger than 32-bit physical
+ addresses. This features is not be available on all e500 cores.
+
+ If in doubt, say N here.
+
+config ALTIVEC
+ bool "AltiVec Support"
+ depends on CLASSIC32 || POWER4
+ ---help---
+ This option enables kernel support for the Altivec extensions to the
+ PowerPC processor. The kernel currently supports saving and restoring
+ altivec registers, and turning on the 'altivec enable' bit so user
+ processes can execute altivec instructions.
+
+ This option is only usefully if you have a processor that supports
+ altivec (G4, otherwise known as 74xx series), but does not have
+ any affect on a non-altivec cpu (it does, however add code to the
+ kernel).
+
+ If in doubt, say Y here.
+
+config SPE
+ bool "SPE Support"
+ depends on E200 || E500
+ default y
+ ---help---
+ This option enables kernel support for the Signal Processing
+ Extensions (SPE) to the PowerPC processor. The kernel currently
+ supports saving and restoring SPE registers, and turning on the
+ 'spe enable' bit so user processes can execute SPE instructions.
+
+ This option is only useful if you have a processor that supports
+ SPE (e500, otherwise known as 85xx series), but does not have any
+ effect on a non-spe cpu (it does, however add code to the kernel).
+
+ If in doubt, say Y here.
+
+config PPC_STD_MMU
+ bool
+ depends on 6xx || POWER3 || POWER4 || PPC64
+ default y
+
+config PPC_STD_MMU_32
+ def_bool y
+ depends on PPC_STD_MMU && PPC32
+
+config PPC_MM_SLICES
+ bool
+ default y if HUGETLB_PAGE
+ default n
+
+config VIRT_CPU_ACCOUNTING
+ bool "Deterministic task and CPU time accounting"
+ depends on PPC64
+ default y
+ help
+ Select this option to enable more accurate task and CPU time
+ accounting. This is done by reading a CPU counter on each
+ kernel entry and exit and on transitions within the kernel
+ between system, softirq and hardirq state, so there is a
+ small performance impact. This also enables accounting of
+ stolen time on logically-partitioned systems running on
+ IBM POWER5-based machines.
+
+ If in doubt, say Y here.
+
+config SMP
+ depends on PPC_STD_MMU
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, say N. If you have a system with more
+ than one CPU, say Y. Note that the kernel does not currently
+ support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
+ since they have inadequate hardware support for multiprocessor
+ operation.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on single-processor machines.
+ On a single-processor machine, the kernel will run faster if you say
+ N here.
+
+ If you don't know what to do here, say N.
+
+config NR_CPUS
+ int "Maximum number of CPUs (2-128)"
+ range 2 128
+ depends on SMP
+ default "32" if PPC64
+ default "4"
+
+config NOT_COHERENT_CACHE
+ bool
+ depends on 4xx || 8xx || E200
+ default y
+
+config CONFIG_CHECK_CACHE_COHERENCY
+ bool
+
+endmenu
diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig
deleted file mode 100644
index 6bde3bffed86..000000000000
--- a/arch/powerpc/platforms/apus/Kconfig
+++ /dev/null
@@ -1,130 +0,0 @@
-
-config AMIGA
- bool
- depends on APUS
- default y
- help
- This option enables support for the Amiga series of computers.
-
-config ZORRO
- bool
- depends on APUS
- default y
- help
- This enables support for the Zorro bus in the Amiga. If you have
- expansion cards in your Amiga that conform to the Amiga
- AutoConfig(tm) specification, say Y, otherwise N. Note that even
- expansion cards that do not fit in the Zorro slots but fit in e.g.
- the CPU slot may fall in this category, so you have to say Y to let
- Linux use these.
-
-config ABSTRACT_CONSOLE
- bool
- depends on APUS
- default y
-
-config APUS_FAST_EXCEPT
- bool
- depends on APUS
- default y
-
-config AMIGA_PCMCIA
- bool "Amiga 1200/600 PCMCIA support"
- depends on APUS && EXPERIMENTAL
- help
- Include support in the kernel for pcmcia on Amiga 1200 and Amiga
- 600. If you intend to use pcmcia cards say Y; otherwise say N.
-
-config AMIGA_BUILTIN_SERIAL
- tristate "Amiga builtin serial support"
- depends on APUS
- help
- If you want to use your Amiga's built-in serial port in Linux,
- answer Y.
-
- To compile this driver as a module, choose M here.
-
-config GVPIOEXT
- tristate "GVP IO-Extender support"
- depends on APUS
- help
- If you want to use a GVP IO-Extender serial card in Linux, say Y.
- Otherwise, say N.
-
-config GVPIOEXT_LP
- tristate "GVP IO-Extender parallel printer support"
- depends on GVPIOEXT
- help
- Say Y to enable driving a printer from the parallel port on your
- GVP IO-Extender card, N otherwise.
-
-config GVPIOEXT_PLIP
- tristate "GVP IO-Extender PLIP support"
- depends on GVPIOEXT
- help
- Say Y to enable doing IP over the parallel port on your GVP
- IO-Extender card, N otherwise.
-
-config MULTIFACE_III_TTY
- tristate "Multiface Card III serial support"
- depends on APUS
- help
- If you want to use a Multiface III card's serial port in Linux,
- answer Y.
-
- To compile this driver as a module, choose M here.
-
-config A2232
- tristate "Commodore A2232 serial support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && APUS
- ---help---
- This option supports the 2232 7-port serial card shipped with the
- Amiga 2000 and other Zorro-bus machines, dating from 1989. At
- a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
- each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
- ports were connected with 8 pin DIN connectors on the card bracket,
- for which 8 pin to DB25 adapters were supplied. The card also had
- jumpers internally to toggle various pinning configurations.
-
- This driver can be built as a module; but then "generic_serial"
- will also be built as a module. This has to be loaded before
- "ser_a2232". If you want to do this, answer M here.
-
-config WHIPPET_SERIAL
- tristate "Hisoft Whippet PCMCIA serial support"
- depends on AMIGA_PCMCIA
- help
- HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
- is no listing for the Whippet in their Amiga section.
-
-config APNE
- tristate "PCMCIA NE2000 support"
- depends on AMIGA_PCMCIA
- help
- If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
- say N.
-
- To compile this driver as a module, choose M here: the
- module will be called apne.
-
-config SERIAL_CONSOLE
- bool "Support for serial port console"
- depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
-
-config HEARTBEAT
- bool "Use power LED as a heartbeat"
- depends on APUS
- help
- Use the power-on LED on your machine as a load meter. The exact
- behavior is platform-dependent, but normally the flash frequency is
- a hyperbolic function of the 5-minute load average.
-
-config PROC_HARDWARE
- bool "/proc/hardware support"
- depends on APUS
-
-source "drivers/zorro/Kconfig"
-
-config PCI_PERMEDIA
- bool "PCI for Permedia2"
- depends on !4xx && !8xx && APUS
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 7fb92f23f380..9d7c2ef940a8 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -102,7 +102,7 @@ static void spider_io_flush(const volatile void __iomem *addr)
vaddr = (unsigned long)PCI_FIX_ADDR(addr);
/* Check if it's in allowed range for PIO */
- if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
+ if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
return;
/* Try to find a PTE. If not, clear the paddr, we'll do
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a7f5a7653c62..96a8f609690c 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -31,6 +31,7 @@
#include <linux/mm.h>
#include <linux/io.h>
#include <linux/mutex.h>
+#include <linux/linux_logo.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/xmon.h>
@@ -183,7 +184,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
spu->slb_replace = 0;
spu_restart_dma(spu);
-
+ spu->stats.slb_flt++;
return 0;
}
@@ -332,6 +333,7 @@ spu_irq_class_2(int irq, void *data)
if (stat & 0x10) /* SPU mailbox threshold */
spu->wbox_callback(spu);
+ spu->stats.class2_intr++;
return stat ? IRQ_HANDLED : IRQ_NONE;
}
@@ -462,8 +464,18 @@ void spu_free(struct spu *spu)
}
EXPORT_SYMBOL_GPL(spu_free);
+static int spu_shutdown(struct sys_device *sysdev)
+{
+ struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+ spu_free_irqs(spu);
+ spu_destroy_spu(spu);
+ return 0;
+}
+
struct sysdev_class spu_sysdev_class = {
- set_kset_name("spu")
+ set_kset_name("spu"),
+ .shutdown = spu_shutdown,
};
int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -574,6 +586,9 @@ static int __init create_spu(void *data)
spin_unlock_irqrestore(&spu_list_lock, flags);
mutex_unlock(&spu_mutex);
+ spu->stats.utilization_state = SPU_UTIL_IDLE;
+ spu->stats.tstamp = jiffies;
+
goto out;
out_free_irqs:
@@ -586,6 +601,45 @@ out:
return ret;
}
+static const char *spu_state_names[] = {
+ "user", "system", "iowait", "idle"
+};
+
+static unsigned long long spu_acct_time(struct spu *spu,
+ enum spu_utilization_state state)
+{
+ unsigned long long time = spu->stats.times[state];
+
+ if (spu->stats.utilization_state == state)
+ time += jiffies - spu->stats.tstamp;
+
+ return jiffies_to_msecs(time);
+}
+
+
+static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+{
+ struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+ return sprintf(buf, "%s %llu %llu %llu %llu "
+ "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+ spu_state_names[spu->stats.utilization_state],
+ spu_acct_time(spu, SPU_UTIL_USER),
+ spu_acct_time(spu, SPU_UTIL_SYSTEM),
+ spu_acct_time(spu, SPU_UTIL_IOWAIT),
+ spu_acct_time(spu, SPU_UTIL_IDLE),
+ spu->stats.vol_ctx_switch,
+ spu->stats.invol_ctx_switch,
+ spu->stats.slb_flt,
+ spu->stats.hash_flt,
+ spu->stats.min_flt,
+ spu->stats.maj_flt,
+ spu->stats.class2_intr,
+ spu->stats.libassist);
+}
+
+static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
+
static int __init init_spu_base(void)
{
int i, ret = 0;
@@ -603,14 +657,28 @@ static int __init init_spu_base(void)
ret = spu_enumerate_spus(create_spu);
- if (ret) {
+ if (ret < 0) {
printk(KERN_WARNING "%s: Error initializing spus\n",
__FUNCTION__);
goto out_unregister_sysdev_class;
}
+ if (ret > 0) {
+ /*
+ * We cannot put the forward declaration in
+ * <linux/linux_logo.h> because of conflicting session type
+ * conflicts for const and __initdata with different compiler
+ * versions
+ */
+ extern const struct linux_logo logo_spe_clut224;
+
+ fb_append_extra_logo(&logo_spe_clut224, ret);
+ }
+
xmon_register_spus(&spu_full_list);
+ spu_add_sysdev_attr(&attr_stat);
+
return 0;
out_unregister_sysdev_class:
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 1d4562ae463d..75ed50fcc3db 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -279,6 +279,7 @@ static int __init of_enumerate_spus(int (*fn)(void *data))
{
int ret;
struct device_node *node;
+ unsigned int n = 0;
ret = -ENODEV;
for (node = of_find_node_by_type(NULL, "spe");
@@ -289,8 +290,9 @@ static int __init of_enumerate_spus(int (*fn)(void *data))
__FUNCTION__, node->name);
break;
}
+ n++;
}
- return ret;
+ return ret ? ret : n;
}
static int __init of_create_spu(struct spu *spu, void *data)
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index d32db9ffc6eb..07a0e815abf5 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -320,6 +320,12 @@ static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
/* FIXME: what are the side-effects of this? */
prob->dma_querymask_RW = mask;
prob->dma_querytype_RW = mode;
+ /* In the current implementation, the SPU context is always
+ * acquired in runnable state when new bits are added to the
+ * mask (tagwait), so it's sufficient just to mask
+ * dma_tagstatus_R with the 'mask' parameter here.
+ */
+ ctx->csa.prob.dma_tagstatus_R &= mask;
out:
spin_unlock(&ctx->csa.register_lock);
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 7c51cb54bca1..6d7bd60f5380 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -23,10 +23,14 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <asm/atomic.h>
#include <asm/spu.h>
#include <asm/spu_csa.h>
#include "spufs.h"
+
+atomic_t nr_spu_contexts = ATOMIC_INIT(0);
+
struct spu_context *alloc_spu_context(struct spu_gang *gang)
{
struct spu_context *ctx;
@@ -53,10 +57,12 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
INIT_LIST_HEAD(&ctx->rq);
if (gang)
spu_gang_add_ctx(gang, ctx);
- ctx->rt_priority = current->rt_priority;
- ctx->policy = current->policy;
- ctx->prio = current->prio;
- INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
+ ctx->cpus_allowed = current->cpus_allowed;
+ spu_set_timeslice(ctx);
+ ctx->stats.execution_state = SPUCTX_UTIL_USER;
+ ctx->stats.tstamp = jiffies;
+
+ atomic_inc(&nr_spu_contexts);
goto out;
out_free:
kfree(ctx);
@@ -76,6 +82,7 @@ void destroy_spu_context(struct kref *kref)
if (ctx->gang)
spu_gang_remove_ctx(ctx->gang, ctx);
BUG_ON(!list_empty(&ctx->rq));
+ atomic_dec(&nr_spu_contexts);
kfree(ctx);
}
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 0f75c07e29d8..e064d0c0d80e 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -33,7 +33,8 @@
* function. Currently, there are a few corner cases that we haven't had
* to handle fortunately.
*/
-static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr)
+static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+ unsigned long dsisr, unsigned *flt)
{
struct vm_area_struct *vma;
unsigned long is_write;
@@ -73,7 +74,8 @@ good_area:
goto bad_area;
}
ret = 0;
- switch (handle_mm_fault(mm, vma, ea, is_write)) {
+ *flt = handle_mm_fault(mm, vma, ea, is_write);
+ switch (*flt) {
case VM_FAULT_MINOR:
current->min_flt++;
break;
@@ -153,6 +155,7 @@ int spufs_handle_class1(struct spu_context *ctx)
{
u64 ea, dsisr, access;
unsigned long flags;
+ unsigned flt = 0;
int ret;
/*
@@ -178,9 +181,17 @@ int spufs_handle_class1(struct spu_context *ctx)
if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
return 0;
+ spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT);
+
pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
dsisr, ctx->state);
+ ctx->stats.hash_flt++;
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ ctx->spu->stats.hash_flt++;
+ spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
+ }
+
/* we must not hold the lock when entering spu_handle_mm_fault */
spu_release(ctx);
@@ -192,7 +203,7 @@ int spufs_handle_class1(struct spu_context *ctx)
/* hashing failed, so try the actual fault handler */
if (ret)
- ret = spu_handle_mm_fault(current->mm, ea, dsisr);
+ ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
spu_acquire(ctx);
/*
@@ -201,11 +212,23 @@ int spufs_handle_class1(struct spu_context *ctx)
* In case of unhandled error report the problem to user space.
*/
if (!ret) {
+ if (flt == VM_FAULT_MINOR)
+ ctx->stats.min_flt++;
+ else
+ ctx->stats.maj_flt++;
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ if (flt == VM_FAULT_MINOR)
+ ctx->spu->stats.min_flt++;
+ else
+ ctx->spu->stats.maj_flt++;
+ }
+
if (ctx->spu)
ctx->ops->restart_dma(ctx);
} else
spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
+ spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
return ret;
}
EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index b1e7e2f8a2e9..c2814ea96af2 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -28,6 +28,7 @@
#include <linux/pagemap.h>
#include <linux/poll.h>
#include <linux/ptrace.h>
+#include <linux/seq_file.h>
#include <asm/io.h>
#include <asm/semaphore.h>
@@ -39,6 +40,7 @@
#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
+
static int
spufs_mem_open(struct inode *inode, struct file *file)
{
@@ -216,12 +218,12 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr,
#endif /* CONFIG_SPU_FS_64K_LS */
static const struct file_operations spufs_mem_fops = {
- .open = spufs_mem_open,
- .release = spufs_mem_release,
- .read = spufs_mem_read,
- .write = spufs_mem_write,
- .llseek = generic_file_llseek,
- .mmap = spufs_mem_mmap,
+ .open = spufs_mem_open,
+ .release = spufs_mem_release,
+ .read = spufs_mem_read,
+ .write = spufs_mem_write,
+ .llseek = generic_file_llseek,
+ .mmap = spufs_mem_mmap,
#ifdef CONFIG_SPU_FS_64K_LS
.get_unmapped_area = spufs_get_unmapped_area,
#endif
@@ -1497,14 +1499,15 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
if (status)
ret = status;
}
- spu_release(ctx);
if (ret)
- goto out;
+ goto out_unlock;
ctx->tagwait |= 1 << cmd.tag;
ret = size;
+out_unlock:
+ spu_release(ctx);
out:
return ret;
}
@@ -1515,14 +1518,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
u32 free_elements, tagstatus;
unsigned int mask;
+ poll_wait(file, &ctx->mfc_wq, wait);
+
spu_acquire(ctx);
ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
free_elements = ctx->ops->get_mfc_free_elements(ctx);
tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
spu_release(ctx);
- poll_wait(file, &ctx->mfc_wq, wait);
-
mask = 0;
if (free_elements & 0xffff)
mask |= POLLOUT | POLLWRNORM;
@@ -1797,6 +1800,29 @@ static int spufs_info_open(struct inode *inode, struct file *file)
return 0;
}
+static int spufs_caps_show(struct seq_file *s, void *private)
+{
+ struct spu_context *ctx = s->private;
+
+ if (!(ctx->flags & SPU_CREATE_NOSCHED))
+ seq_puts(s, "sched\n");
+ if (!(ctx->flags & SPU_CREATE_ISOLATE))
+ seq_puts(s, "step\n");
+ return 0;
+}
+
+static int spufs_caps_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_caps_fops = {
+ .open = spufs_caps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
char __user *buf, size_t len, loff_t *pos)
{
@@ -2014,7 +2040,105 @@ static const struct file_operations spufs_proxydma_info_fops = {
.read = spufs_proxydma_info_read,
};
+static int spufs_show_tid(struct seq_file *s, void *private)
+{
+ struct spu_context *ctx = s->private;
+
+ seq_printf(s, "%d\n", ctx->tid);
+ return 0;
+}
+
+static int spufs_tid_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_tid_fops = {
+ .open = spufs_tid_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const char *ctx_state_names[] = {
+ "user", "system", "iowait", "loaded"
+};
+
+static unsigned long long spufs_acct_time(struct spu_context *ctx,
+ enum spuctx_execution_state state)
+{
+ unsigned long time = ctx->stats.times[state];
+
+ if (ctx->stats.execution_state == state)
+ time += jiffies - ctx->stats.tstamp;
+
+ return jiffies_to_msecs(time);
+}
+
+static unsigned long long spufs_slb_flts(struct spu_context *ctx)
+{
+ unsigned long long slb_flts = ctx->stats.slb_flt;
+
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ slb_flts += (ctx->spu->stats.slb_flt -
+ ctx->stats.slb_flt_base);
+ }
+
+ return slb_flts;
+}
+
+static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
+{
+ unsigned long long class2_intrs = ctx->stats.class2_intr;
+
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ class2_intrs += (ctx->spu->stats.class2_intr -
+ ctx->stats.class2_intr_base);
+ }
+
+ return class2_intrs;
+}
+
+
+static int spufs_show_stat(struct seq_file *s, void *private)
+{
+ struct spu_context *ctx = s->private;
+
+ spu_acquire(ctx);
+ seq_printf(s, "%s %llu %llu %llu %llu "
+ "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+ ctx_state_names[ctx->stats.execution_state],
+ spufs_acct_time(ctx, SPUCTX_UTIL_USER),
+ spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM),
+ spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT),
+ spufs_acct_time(ctx, SPUCTX_UTIL_LOADED),
+ ctx->stats.vol_ctx_switch,
+ ctx->stats.invol_ctx_switch,
+ spufs_slb_flts(ctx),
+ ctx->stats.hash_flt,
+ ctx->stats.min_flt,
+ ctx->stats.maj_flt,
+ spufs_class2_intrs(ctx),
+ ctx->stats.libassist);
+ spu_release(ctx);
+ return 0;
+}
+
+static int spufs_stat_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_stat_fops = {
+ .open = spufs_stat_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+
struct tree_descr spufs_dir_contents[] = {
+ { "capabilities", &spufs_caps_fops, 0444, },
{ "mem", &spufs_mem_fops, 0666, },
{ "regs", &spufs_regs_fops, 0666, },
{ "mbox", &spufs_mbox_fops, 0444, },
@@ -2046,10 +2170,13 @@ struct tree_descr spufs_dir_contents[] = {
{ "wbox_info", &spufs_wbox_info_fops, 0444, },
{ "dma_info", &spufs_dma_info_fops, 0444, },
{ "proxydma_info", &spufs_proxydma_info_fops, 0444, },
+ { "tid", &spufs_tid_fops, 0444, },
+ { "stat", &spufs_stat_fops, 0444, },
{},
};
struct tree_descr spufs_dir_nosched_contents[] = {
+ { "capabilities", &spufs_caps_fops, 0444, },
{ "mem", &spufs_mem_fops, 0666, },
{ "mbox", &spufs_mbox_fops, 0444, },
{ "ibox", &spufs_ibox_fops, 0444, },
@@ -2068,6 +2195,8 @@ struct tree_descr spufs_dir_nosched_contents[] = {
{ "psmap", &spufs_psmap_fops, 0666, },
{ "phys-id", &spufs_id_ops, 0666, },
{ "object-id", &spufs_object_id_ops, 0666, },
+ { "tid", &spufs_tid_fops, 0444, },
+ { "stat", &spufs_stat_fops, 0444, },
{},
};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 9807206e0219..f37460e5bfd2 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -232,10 +232,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
return dcache_dir_close(inode, file);
}
-const struct inode_operations spufs_dir_inode_operations = {
- .lookup = simple_lookup,
-};
-
const struct file_operations spufs_context_fops = {
.open = dcache_dir_open,
.release = spufs_dir_close,
@@ -269,7 +265,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
goto out_iput;
ctx->flags = flags;
- inode->i_op = &spufs_dir_inode_operations;
+ inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
if (flags & SPU_CREATE_NOSCHED)
ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
@@ -386,7 +382,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
if (!gang)
goto out_iput;
- inode->i_op = &spufs_dir_inode_operations;
+ inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
d_instantiate(dentry, inode);
@@ -593,7 +589,7 @@ spufs_create_root(struct super_block *sb, void *data)
if (!inode)
goto out;
- inode->i_op = &spufs_dir_inode_operations;
+ inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
SPUFS_I(inode)->i_ctx = NULL;
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 57626600b1a4..58ae13b7de84 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -29,7 +29,8 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
spu = ctx->spu;
pte_fault = spu->dsisr &
(MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
- return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
+ return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ?
+ 1 : 0;
}
static int spu_setup_isolated(struct spu_context *ctx)
@@ -142,8 +143,11 @@ static int spu_run_init(struct spu_context *ctx, u32 * npc)
runcntl = SPU_RUNCNTL_RUNNABLE;
ctx->ops->runcntl_write(ctx, runcntl);
} else {
- spu_start_tick(ctx);
+ unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
ctx->ops->npc_write(ctx, *npc);
+ if (test_thread_flag(TIF_SINGLESTEP))
+ mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+ out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
}
@@ -155,7 +159,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 * npc,
{
int ret = 0;
- spu_stop_tick(ctx);
*status = ctx->ops->status_read(ctx);
*npc = ctx->ops->npc_read(ctx);
spu_release(ctx);
@@ -298,9 +301,22 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
ctx->ops->master_start(ctx);
ctx->event_return = 0;
- ret = spu_acquire_runnable(ctx, 0);
- if (ret)
- return ret;
+ spu_acquire(ctx);
+ if (ctx->state == SPU_STATE_SAVED) {
+ __spu_update_sched_info(ctx);
+
+ ret = spu_activate(ctx, 0);
+ if (ret) {
+ spu_release(ctx);
+ goto out;
+ }
+ } else {
+ /*
+ * We have to update the scheduling priority under active_mutex
+ * to protect against find_victim().
+ */
+ spu_update_sched_info(ctx);
+ }
ret = spu_run_init(ctx, npc);
if (ret) {
@@ -325,16 +341,20 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
ret = spu_reacquire_runnable(ctx, npc, &status);
- if (ret) {
- spu_stop_tick(ctx);
+ if (ret)
goto out2;
- }
continue;
}
ret = spu_process_events(ctx);
} while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
- SPU_STATUS_STOPPED_BY_HALT)));
+ SPU_STATUS_STOPPED_BY_HALT |
+ SPU_STATUS_SINGLE_STEP)));
+
+ if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+ (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) &&
+ (ctx->state == SPU_STATE_RUNNABLE))
+ ctx->stats.libassist++;
ctx->ops->master_stop(ctx);
ret = spu_run_fini(ctx, npc, &status);
@@ -344,10 +364,15 @@ out2:
if ((ret == 0) ||
((ret == -ERESTARTSYS) &&
((status & SPU_STATUS_STOPPED_BY_HALT) ||
+ (status & SPU_STATUS_SINGLE_STEP) ||
((status & SPU_STATUS_STOPPED_BY_STOP) &&
(status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
ret = status;
+ /* Note: we don't need to force_sig SIGTRAP on single-step
+ * since we have TIF_SINGLESTEP set, thus the kernel will do
+ * it upon return from the syscall anyawy
+ */
if ((status & SPU_STATUS_STOPPED_BY_STOP)
&& (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
force_sig(SIGTRAP, current);
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 3b831e07f1ed..e5b4dd1db286 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -35,6 +35,10 @@
#include <linux/numa.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
+#include <linux/kthread.h>
+#include <linux/pid_namespace.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
@@ -43,54 +47,126 @@
#include <asm/spu_priv1.h>
#include "spufs.h"
-#define SPU_TIMESLICE (HZ)
-
struct spu_prio_array {
DECLARE_BITMAP(bitmap, MAX_PRIO);
struct list_head runq[MAX_PRIO];
spinlock_t runq_lock;
struct list_head active_list[MAX_NUMNODES];
struct mutex active_mutex[MAX_NUMNODES];
+ int nr_active[MAX_NUMNODES];
+ int nr_waiting;
};
+static unsigned long spu_avenrun[3];
static struct spu_prio_array *spu_prio;
-static struct workqueue_struct *spu_sched_wq;
+static struct task_struct *spusched_task;
+static struct timer_list spusched_timer;
+
+/*
+ * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
+ */
+#define NORMAL_PRIO 120
+
+/*
+ * Frequency of the spu scheduler tick. By default we do one SPU scheduler
+ * tick for every 10 CPU scheduler ticks.
+ */
+#define SPUSCHED_TICK (10)
-static inline int node_allowed(int node)
+/*
+ * These are the 'tuning knobs' of the scheduler:
+ *
+ * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is
+ * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs.
+ */
+#define MIN_SPU_TIMESLICE max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
+#define DEF_SPU_TIMESLICE (100 * HZ / (1000 * SPUSCHED_TICK))
+
+#define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO)
+#define SCALE_PRIO(x, prio) \
+ max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
+
+/*
+ * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values:
+ * [800ms ... 100ms ... 5ms]
+ *
+ * The higher a thread's priority, the bigger timeslices
+ * it gets during one round of execution. But even the lowest
+ * priority thread gets MIN_TIMESLICE worth of execution time.
+ */
+void spu_set_timeslice(struct spu_context *ctx)
{
- cpumask_t mask;
+ if (ctx->prio < NORMAL_PRIO)
+ ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio);
+ else
+ ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
+}
- if (!nr_cpus_node(node))
- return 0;
- mask = node_to_cpumask(node);
- if (!cpus_intersects(mask, current->cpus_allowed))
- return 0;
- return 1;
+/*
+ * Update scheduling information from the owning thread.
+ */
+void __spu_update_sched_info(struct spu_context *ctx)
+{
+ /*
+ * 32-Bit assignment are atomic on powerpc, and we don't care about
+ * memory ordering here because retriving the controlling thread is
+ * per defintion racy.
+ */
+ ctx->tid = current->pid;
+
+ /*
+ * We do our own priority calculations, so we normally want
+ * ->static_prio to start with. Unfortunately thies field
+ * contains junk for threads with a realtime scheduling
+ * policy so we have to look at ->prio in this case.
+ */
+ if (rt_prio(current->prio))
+ ctx->prio = current->prio;
+ else
+ ctx->prio = current->static_prio;
+ ctx->policy = current->policy;
+
+ /*
+ * A lot of places that don't hold active_mutex poke into
+ * cpus_allowed, including grab_runnable_context which
+ * already holds the runq_lock. So abuse runq_lock
+ * to protect this field aswell.
+ */
+ spin_lock(&spu_prio->runq_lock);
+ ctx->cpus_allowed = current->cpus_allowed;
+ spin_unlock(&spu_prio->runq_lock);
}
-void spu_start_tick(struct spu_context *ctx)
+void spu_update_sched_info(struct spu_context *ctx)
{
- if (ctx->policy == SCHED_RR) {
- /*
- * Make sure the exiting bit is cleared.
- */
- clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
- mb();
- queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
- }
+ int node = ctx->spu->node;
+
+ mutex_lock(&spu_prio->active_mutex[node]);
+ __spu_update_sched_info(ctx);
+ mutex_unlock(&spu_prio->active_mutex[node]);
}
-void spu_stop_tick(struct spu_context *ctx)
+static int __node_allowed(struct spu_context *ctx, int node)
{
- if (ctx->policy == SCHED_RR) {
- /*
- * While the work can be rearming normally setting this flag
- * makes sure it does not rearm itself anymore.
- */
- set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
- mb();
- cancel_delayed_work(&ctx->sched_work);
+ if (nr_cpus_node(node)) {
+ cpumask_t mask = node_to_cpumask(node);
+
+ if (cpus_intersects(mask, ctx->cpus_allowed))
+ return 1;
}
+
+ return 0;
+}
+
+static int node_allowed(struct spu_context *ctx, int node)
+{
+ int rval;
+
+ spin_lock(&spu_prio->runq_lock);
+ rval = __node_allowed(ctx, node);
+ spin_unlock(&spu_prio->runq_lock);
+
+ return rval;
}
/**
@@ -99,9 +175,18 @@ void spu_stop_tick(struct spu_context *ctx)
*/
static void spu_add_to_active_list(struct spu *spu)
{
- mutex_lock(&spu_prio->active_mutex[spu->node]);
- list_add_tail(&spu->list, &spu_prio->active_list[spu->node]);
- mutex_unlock(&spu_prio->active_mutex[spu->node]);
+ int node = spu->node;
+
+ mutex_lock(&spu_prio->active_mutex[node]);
+ spu_prio->nr_active[node]++;
+ list_add_tail(&spu->list, &spu_prio->active_list[node]);
+ mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
+static void __spu_remove_from_active_list(struct spu *spu)
+{
+ list_del_init(&spu->list);
+ spu_prio->nr_active[spu->node]--;
}
/**
@@ -113,7 +198,7 @@ static void spu_remove_from_active_list(struct spu *spu)
int node = spu->node;
mutex_lock(&spu_prio->active_mutex[node]);
- list_del_init(&spu->list);
+ __spu_remove_from_active_list(spu);
mutex_unlock(&spu_prio->active_mutex[node]);
}
@@ -144,6 +229,10 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
{
pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
spu->number, spu->node);
+
+ ctx->stats.slb_flt_base = spu->stats.slb_flt;
+ ctx->stats.class2_intr_base = spu->stats.class2_intr;
+
spu->ctx = ctx;
spu->flags = 0;
ctx->spu = spu;
@@ -161,8 +250,8 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
spu->timestamp = jiffies;
spu_cpu_affinity_set(spu, raw_smp_processor_id());
spu_switch_notify(spu, ctx);
- spu_add_to_active_list(spu);
ctx->state = SPU_STATE_RUNNABLE;
+ spu_switch_state(spu, SPU_UTIL_SYSTEM);
}
/**
@@ -175,7 +264,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
spu->pid, spu->number, spu->node);
- spu_remove_from_active_list(spu);
+ spu_switch_state(spu, SPU_UTIL_IDLE);
+
spu_switch_notify(spu, NULL);
spu_unmap_mappings(ctx);
spu_save(&ctx->csa, spu);
@@ -192,6 +282,11 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
ctx->spu = NULL;
spu->flags = 0;
spu->ctx = NULL;
+
+ ctx->stats.slb_flt +=
+ (spu->stats.slb_flt - ctx->stats.slb_flt_base);
+ ctx->stats.class2_intr +=
+ (spu->stats.class2_intr - ctx->stats.class2_intr_base);
}
/**
@@ -200,20 +295,39 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
*/
static void __spu_add_to_rq(struct spu_context *ctx)
{
- int prio = ctx->prio;
-
- list_add_tail(&ctx->rq, &spu_prio->runq[prio]);
- set_bit(prio, spu_prio->bitmap);
+ /*
+ * Unfortunately this code path can be called from multiple threads
+ * on behalf of a single context due to the way the problem state
+ * mmap support works.
+ *
+ * Fortunately we need to wake up all these threads at the same time
+ * and can simply skip the runqueue addition for every but the first
+ * thread getting into this codepath.
+ *
+ * It's still quite hacky, and long-term we should proxy all other
+ * threads through the owner thread so that spu_run is in control
+ * of all the scheduling activity for a given context.
+ */
+ if (list_empty(&ctx->rq)) {
+ list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
+ set_bit(ctx->prio, spu_prio->bitmap);
+ if (!spu_prio->nr_waiting++)
+ __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+ }
}
static void __spu_del_from_rq(struct spu_context *ctx)
{
int prio = ctx->prio;
- if (!list_empty(&ctx->rq))
+ if (!list_empty(&ctx->rq)) {
+ if (!--spu_prio->nr_waiting)
+ del_timer(&spusched_timer);
list_del_init(&ctx->rq);
- if (list_empty(&spu_prio->runq[prio]))
- clear_bit(prio, spu_prio->bitmap);
+
+ if (list_empty(&spu_prio->runq[prio]))
+ clear_bit(prio, spu_prio->bitmap);
+ }
}
static void spu_prio_wait(struct spu_context *ctx)
@@ -244,7 +358,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
for (n = 0; n < MAX_NUMNODES; n++, node++) {
node = (node < MAX_NUMNODES) ? node : 0;
- if (!node_allowed(node))
+ if (!node_allowed(ctx, node))
continue;
spu = spu_alloc_node(node);
if (spu)
@@ -276,15 +390,15 @@ static struct spu *find_victim(struct spu_context *ctx)
node = cpu_to_node(raw_smp_processor_id());
for (n = 0; n < MAX_NUMNODES; n++, node++) {
node = (node < MAX_NUMNODES) ? node : 0;
- if (!node_allowed(node))
+ if (!node_allowed(ctx, node))
continue;
mutex_lock(&spu_prio->active_mutex[node]);
list_for_each_entry(spu, &spu_prio->active_list[node], list) {
struct spu_context *tmp = spu->ctx;
- if (tmp->rt_priority < ctx->rt_priority &&
- (!victim || tmp->rt_priority < victim->rt_priority))
+ if (tmp->prio > ctx->prio &&
+ (!victim || tmp->prio > victim->prio))
victim = spu->ctx;
}
mutex_unlock(&spu_prio->active_mutex[node]);
@@ -312,7 +426,10 @@ static struct spu *find_victim(struct spu_context *ctx)
victim = NULL;
goto restart;
}
+ spu_remove_from_active_list(spu);
spu_unbind_context(spu, victim);
+ victim->stats.invol_ctx_switch++;
+ spu->stats.invol_ctx_switch++;
mutex_unlock(&victim->state_mutex);
/*
* We need to break out of the wait loop in spu_run
@@ -338,22 +455,30 @@ static struct spu *find_victim(struct spu_context *ctx)
*/
int spu_activate(struct spu_context *ctx, unsigned long flags)
{
-
- if (ctx->spu)
- return 0;
+ spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
do {
struct spu *spu;
+ /*
+ * If there are multiple threads waiting for a single context
+ * only one actually binds the context while the others will
+ * only be able to acquire the state_mutex once the context
+ * already is in runnable state.
+ */
+ if (ctx->spu)
+ return 0;
+
spu = spu_get_idle(ctx);
/*
* If this is a realtime thread we try to get it running by
* preempting a lower priority thread.
*/
- if (!spu && ctx->rt_priority)
+ if (!spu && rt_prio(ctx->prio))
spu = find_victim(ctx);
if (spu) {
spu_bind_context(spu, ctx);
+ spu_add_to_active_list(spu);
return 0;
}
@@ -369,23 +494,28 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
* Remove the highest priority context on the runqueue and return it
* to the caller. Returns %NULL if no runnable context was found.
*/
-static struct spu_context *grab_runnable_context(int prio)
+static struct spu_context *grab_runnable_context(int prio, int node)
{
- struct spu_context *ctx = NULL;
+ struct spu_context *ctx;
int best;
spin_lock(&spu_prio->runq_lock);
best = sched_find_first_bit(spu_prio->bitmap);
- if (best < prio) {
+ while (best < prio) {
struct list_head *rq = &spu_prio->runq[best];
- BUG_ON(list_empty(rq));
-
- ctx = list_entry(rq->next, struct spu_context, rq);
- __spu_del_from_rq(ctx);
+ list_for_each_entry(ctx, rq, rq) {
+ /* XXX(hch): check for affinity here aswell */
+ if (__node_allowed(ctx, node)) {
+ __spu_del_from_rq(ctx);
+ goto found;
+ }
+ }
+ best++;
}
+ ctx = NULL;
+ found:
spin_unlock(&spu_prio->runq_lock);
-
return ctx;
}
@@ -395,9 +525,12 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
struct spu_context *new = NULL;
if (spu) {
- new = grab_runnable_context(max_prio);
+ new = grab_runnable_context(max_prio, spu->node);
if (new || force) {
+ spu_remove_from_active_list(spu);
spu_unbind_context(spu, ctx);
+ ctx->stats.vol_ctx_switch++;
+ spu->stats.vol_ctx_switch++;
spu_free(spu);
if (new)
wake_up(&new->stop_wq);
@@ -417,7 +550,17 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
*/
void spu_deactivate(struct spu_context *ctx)
{
+ /*
+ * We must never reach this for a nosched context,
+ * but handle the case gracefull instead of panicing.
+ */
+ if (ctx->flags & SPU_CREATE_NOSCHED) {
+ WARN_ON(1);
+ return;
+ }
+
__spu_deactivate(ctx, 1, MAX_PRIO);
+ spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
}
/**
@@ -432,56 +575,178 @@ void spu_yield(struct spu_context *ctx)
{
if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
mutex_lock(&ctx->state_mutex);
- __spu_deactivate(ctx, 0, MAX_PRIO);
+ if (__spu_deactivate(ctx, 0, MAX_PRIO))
+ spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
+ else {
+ spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED);
+ spu_switch_state(ctx->spu, SPU_UTIL_USER);
+ }
mutex_unlock(&ctx->state_mutex);
}
}
-void spu_sched_tick(struct work_struct *work)
+static void spusched_tick(struct spu_context *ctx)
{
- struct spu_context *ctx =
- container_of(work, struct spu_context, sched_work.work);
- int preempted;
+ if (ctx->flags & SPU_CREATE_NOSCHED)
+ return;
+ if (ctx->policy == SCHED_FIFO)
+ return;
+
+ if (--ctx->time_slice)
+ return;
/*
- * If this context is being stopped avoid rescheduling from the
- * scheduler tick because we would block on the state_mutex.
- * The caller will yield the spu later on anyway.
+ * Unfortunately active_mutex ranks outside of state_mutex, so
+ * we have to trylock here. If we fail give the context another
+ * tick and try again.
*/
- if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
- return;
+ if (mutex_trylock(&ctx->state_mutex)) {
+ struct spu *spu = ctx->spu;
+ struct spu_context *new;
- mutex_lock(&ctx->state_mutex);
- preempted = __spu_deactivate(ctx, 0, ctx->prio + 1);
- mutex_unlock(&ctx->state_mutex);
+ new = grab_runnable_context(ctx->prio + 1, spu->node);
+ if (new) {
- if (preempted) {
- /*
- * We need to break out of the wait loop in spu_run manually
- * to ensure this context gets put on the runqueue again
- * ASAP.
- */
- wake_up(&ctx->stop_wq);
+ __spu_remove_from_active_list(spu);
+ spu_unbind_context(spu, ctx);
+ ctx->stats.invol_ctx_switch++;
+ spu->stats.invol_ctx_switch++;
+ spu_free(spu);
+ wake_up(&new->stop_wq);
+ /*
+ * We need to break out of the wait loop in
+ * spu_run manually to ensure this context
+ * gets put on the runqueue again ASAP.
+ */
+ wake_up(&ctx->stop_wq);
+ }
+ spu_set_timeslice(ctx);
+ mutex_unlock(&ctx->state_mutex);
} else {
- spu_start_tick(ctx);
+ ctx->time_slice++;
}
}
-int __init spu_sched_init(void)
+/**
+ * count_active_contexts - count nr of active tasks
+ *
+ * Return the number of tasks currently running or waiting to run.
+ *
+ * Note that we don't take runq_lock / active_mutex here. Reading
+ * a single 32bit value is atomic on powerpc, and we don't care
+ * about memory ordering issues here.
+ */
+static unsigned long count_active_contexts(void)
{
- int i;
+ int nr_active = 0, node;
- spu_sched_wq = create_singlethread_workqueue("spusched");
- if (!spu_sched_wq)
- return 1;
+ for (node = 0; node < MAX_NUMNODES; node++)
+ nr_active += spu_prio->nr_active[node];
+ nr_active += spu_prio->nr_waiting;
- spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
- if (!spu_prio) {
- printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
- __FUNCTION__);
- destroy_workqueue(spu_sched_wq);
- return 1;
+ return nr_active;
+}
+
+/**
+ * spu_calc_load - given tick count, update the avenrun load estimates.
+ * @tick: tick count
+ *
+ * No locking against reading these values from userspace, as for
+ * the CPU loadavg code.
+ */
+static void spu_calc_load(unsigned long ticks)
+{
+ unsigned long active_tasks; /* fixed-point */
+ static int count = LOAD_FREQ;
+
+ count -= ticks;
+
+ if (unlikely(count < 0)) {
+ active_tasks = count_active_contexts() * FIXED_1;
+ do {
+ CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
+ CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
+ CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
+ count += LOAD_FREQ;
+ } while (count < 0);
}
+}
+
+static void spusched_wake(unsigned long data)
+{
+ mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+ wake_up_process(spusched_task);
+ spu_calc_load(SPUSCHED_TICK);
+}
+
+static int spusched_thread(void *unused)
+{
+ struct spu *spu, *next;
+ int node;
+
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ for (node = 0; node < MAX_NUMNODES; node++) {
+ mutex_lock(&spu_prio->active_mutex[node]);
+ list_for_each_entry_safe(spu, next,
+ &spu_prio->active_list[node],
+ list)
+ spusched_tick(spu->ctx);
+ mutex_unlock(&spu_prio->active_mutex[node]);
+ }
+ }
+
+ return 0;
+}
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+static int show_spu_loadavg(struct seq_file *s, void *private)
+{
+ int a, b, c;
+
+ a = spu_avenrun[0] + (FIXED_1/200);
+ b = spu_avenrun[1] + (FIXED_1/200);
+ c = spu_avenrun[2] + (FIXED_1/200);
+
+ /*
+ * Note that last_pid doesn't really make much sense for the
+ * SPU loadavg (it even seems very odd on the CPU side..),
+ * but we include it here to have a 100% compatible interface.
+ */
+ seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
+ LOAD_INT(a), LOAD_FRAC(a),
+ LOAD_INT(b), LOAD_FRAC(b),
+ LOAD_INT(c), LOAD_FRAC(c),
+ count_active_contexts(),
+ atomic_read(&nr_spu_contexts),
+ current->nsproxy->pid_ns->last_pid);
+ return 0;
+}
+
+static int spu_loadavg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, show_spu_loadavg, NULL);
+}
+
+static const struct file_operations spu_loadavg_fops = {
+ .open = spu_loadavg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+int __init spu_sched_init(void)
+{
+ struct proc_dir_entry *entry;
+ int err = -ENOMEM, i;
+
+ spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
+ if (!spu_prio)
+ goto out;
+
for (i = 0; i < MAX_PRIO; i++) {
INIT_LIST_HEAD(&spu_prio->runq[i]);
__clear_bit(i, spu_prio->bitmap);
@@ -492,7 +757,30 @@ int __init spu_sched_init(void)
INIT_LIST_HEAD(&spu_prio->active_list[i]);
}
spin_lock_init(&spu_prio->runq_lock);
+
+ setup_timer(&spusched_timer, spusched_wake, 0);
+
+ spusched_task = kthread_run(spusched_thread, NULL, "spusched");
+ if (IS_ERR(spusched_task)) {
+ err = PTR_ERR(spusched_task);
+ goto out_free_spu_prio;
+ }
+
+ entry = create_proc_entry("spu_loadavg", 0, NULL);
+ if (!entry)
+ goto out_stop_kthread;
+ entry->proc_fops = &spu_loadavg_fops;
+
+ pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n",
+ SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE);
return 0;
+
+ out_stop_kthread:
+ kthread_stop(spusched_task);
+ out_free_spu_prio:
+ kfree(spu_prio);
+ out:
+ return err;
}
void __exit spu_sched_exit(void)
@@ -500,6 +788,11 @@ void __exit spu_sched_exit(void)
struct spu *spu, *tmp;
int node;
+ remove_proc_entry("spu_loadavg", NULL);
+
+ del_timer_sync(&spusched_timer);
+ kthread_stop(spusched_task);
+
for (node = 0; node < MAX_NUMNODES; node++) {
mutex_lock(&spu_prio->active_mutex[node]);
list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
@@ -510,5 +803,4 @@ void __exit spu_sched_exit(void)
mutex_unlock(&spu_prio->active_mutex[node]);
}
kfree(spu_prio);
- destroy_workqueue(spu_sched_wq);
}
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c
index 0bf723dcd677..4e19ed7a0756 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_restore.c
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c
@@ -296,7 +296,7 @@ static inline void restore_complete(void)
* This code deviates from the documented sequence in the
* following aspects:
*
- * 1. The EA for LSCSA is passed from PPE in the
+ * 1. The EA for LSCSA is passed from PPE in the
* signal notification channels.
* 2. The register spill area is pulled by SPU
* into LS, rather than pushed by PPE.
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save.c b/arch/powerpc/platforms/cell/spufs/spu_save.c
index 196033b8a579..ae95cc1701e9 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_save.c
+++ b/arch/powerpc/platforms/cell/spufs/spu_save.c
@@ -44,7 +44,7 @@ static inline void save_event_mask(void)
* Read the SPU_RdEventMsk channel and save to the LSCSA.
*/
offset = LSCSA_QW_OFFSET(event_mask);
- regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask);
+ regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);
}
static inline void save_tag_mask(void)
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 47617e8014a5..08b3530288ac 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -26,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/fs.h>
+#include <linux/cpumask.h>
#include <asm/spu.h>
#include <asm/spu_csa.h>
@@ -39,9 +40,17 @@ enum {
struct spu_context_ops;
struct spu_gang;
-/* ctx->sched_flags */
-enum {
- SPU_SCHED_EXITING = 0,
+/*
+ * This is the state for spu utilization reporting to userspace.
+ * Because this state is visible to userspace it must never change and needs
+ * to be kept strictly separate from any internal state kept by the kernel.
+ */
+enum spuctx_execution_state {
+ SPUCTX_UTIL_USER = 0,
+ SPUCTX_UTIL_SYSTEM,
+ SPUCTX_UTIL_IOWAIT,
+ SPUCTX_UTIL_LOADED,
+ SPUCTX_UTIL_MAX
};
struct spu_context {
@@ -81,13 +90,34 @@ struct spu_context {
struct list_head gang_list;
struct spu_gang *gang;
+ /* owner thread */
+ pid_t tid;
+
/* scheduler fields */
- struct list_head rq;
- struct delayed_work sched_work;
+ struct list_head rq;
+ unsigned int time_slice;
unsigned long sched_flags;
- unsigned long rt_priority;
+ cpumask_t cpus_allowed;
int policy;
int prio;
+
+ /* statistics */
+ struct {
+ /* updates protected by ctx->state_mutex */
+ enum spuctx_execution_state execution_state;
+ unsigned long tstamp; /* time of last ctx switch */
+ unsigned long times[SPUCTX_UTIL_MAX];
+ unsigned long long vol_ctx_switch;
+ unsigned long long invol_ctx_switch;
+ unsigned long long min_flt;
+ unsigned long long maj_flt;
+ unsigned long long hash_flt;
+ unsigned long long slb_flt;
+ unsigned long long slb_flt_base; /* # at last ctx switch */
+ unsigned long long class2_intr;
+ unsigned long long class2_intr_base; /* # at last ctx switch */
+ unsigned long long libassist;
+ } stats;
};
struct spu_gang {
@@ -177,6 +207,7 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
int spufs_handle_class1(struct spu_context *ctx);
/* context management */
+extern atomic_t nr_spu_contexts;
static inline void spu_acquire(struct spu_context *ctx)
{
mutex_lock(&ctx->state_mutex);
@@ -200,9 +231,9 @@ void spu_acquire_saved(struct spu_context *ctx);
int spu_activate(struct spu_context *ctx, unsigned long flags);
void spu_deactivate(struct spu_context *ctx);
void spu_yield(struct spu_context *ctx);
-void spu_start_tick(struct spu_context *ctx);
-void spu_stop_tick(struct spu_context *ctx);
-void spu_sched_tick(struct work_struct *work);
+void spu_set_timeslice(struct spu_context *ctx);
+void spu_update_sched_info(struct spu_context *ctx);
+void __spu_update_sched_info(struct spu_context *ctx);
int __init spu_sched_init(void);
void __exit spu_sched_exit(void);
@@ -210,7 +241,7 @@ extern char *isolated_loader;
/*
* spufs_wait
- * Same as wait_event_interruptible(), except that here
+ * Same as wait_event_interruptible(), except that here
* we need to call spu_release(ctx) before sleeping, and
* then spu_acquire(ctx) when awoken.
*/
@@ -256,4 +287,37 @@ struct spufs_coredump_reader {
extern struct spufs_coredump_reader spufs_coredump_read[];
extern int spufs_coredump_num_notes;
+/*
+ * This function is a little bit too large for an inline, but
+ * as fault.c is built into the kernel we can't move it out of
+ * line.
+ */
+static inline void spuctx_switch_state(struct spu_context *ctx,
+ enum spuctx_execution_state new_state)
+{
+ WARN_ON(!mutex_is_locked(&ctx->state_mutex));
+
+ if (ctx->stats.execution_state != new_state) {
+ unsigned long curtime = jiffies;
+
+ ctx->stats.times[ctx->stats.execution_state] +=
+ curtime - ctx->stats.tstamp;
+ ctx->stats.tstamp = curtime;
+ ctx->stats.execution_state = new_state;
+ }
+}
+
+static inline void spu_switch_state(struct spu *spu,
+ enum spuctx_execution_state new_state)
+{
+ if (spu->stats.utilization_state != new_state) {
+ unsigned long curtime = jiffies;
+
+ spu->stats.times[spu->stats.utilization_state] +=
+ curtime - spu->stats.tstamp;
+ spu->stats.tstamp = curtime;
+ spu->stats.utilization_state = new_state;
+ }
+}
+
#endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 71a0b41adb8c..9c506ba08cdc 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -70,7 +70,7 @@
}
#endif /* debug */
-#define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c))
+#define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c))
static inline void acquire_spu_lock(struct spu *spu)
{
@@ -387,6 +387,19 @@ static inline void save_ppu_querytype(struct spu_state *csa, struct spu *spu)
csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW);
}
+static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save the Prxy_TagStatus register in the CSA.
+ *
+ * It is unnecessary to restore dma_tagstatus_R, however,
+ * dma_tagstatus_R in the CSA is accessed via backing_ops, so
+ * we must save it.
+ */
+ csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R);
+}
+
static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu)
{
struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -1812,6 +1825,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
save_mfc_queues(prev, spu); /* Step 19. */
save_ppu_querymask(prev, spu); /* Step 20. */
save_ppu_querytype(prev, spu); /* Step 21. */
+ save_ppu_tagstatus(prev, spu); /* NEW. */
save_mfc_csr_tsq(prev, spu); /* Step 22. */
save_mfc_csr_cmd(prev, spu); /* Step 23. */
save_mfc_csr_ato(prev, spu); /* Step 24. */
@@ -1930,7 +1944,7 @@ static void harvest(struct spu_state *prev, struct spu *spu)
reset_spu_privcntl(prev, spu); /* Step 16. */
reset_spu_lslr(prev, spu); /* Step 17. */
setup_mfc_sr1(prev, spu); /* Step 18. */
- spu_invalidate_slbs(spu); /* Step 19. */
+ spu_invalidate_slbs(spu); /* Step 19. */
reset_ch_part1(prev, spu); /* Step 20. */
reset_ch_part2(prev, spu); /* Step 21. */
enable_interrupts(prev, spu); /* Step 22. */
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index d2c690531963..22b4b4e3b6f0 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -8,4 +8,5 @@ config PPC_CHRP
select PPC_MPC106
select PPC_UDBG_16550
select PPC_NATIVE
+ select PCI
default y
diff --git a/arch/powerpc/platforms/chrp/Makefile b/arch/powerpc/platforms/chrp/Makefile
index 902feb1ac431..4b3bfadc70fa 100644
--- a/arch/powerpc/platforms/chrp/Makefile
+++ b/arch/powerpc/platforms/chrp/Makefile
@@ -1,4 +1,3 @@
-obj-y += setup.o time.o pegasos_eth.o
-obj-$(CONFIG_PCI) += pci.o
+obj-y += setup.o time.o pegasos_eth.o pci.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_NVRAM) += nvram.o
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index d32fedc991d3..3690624e49d4 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -99,7 +99,7 @@ int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
struct pci_controller *hose = bus->sysdata;
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
+ | (hose->global_number << 24);
int ret = -1;
int rval;
@@ -114,7 +114,7 @@ int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
struct pci_controller *hose = bus->sysdata;
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
+ | (hose->global_number << 24);
int rval;
rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -254,13 +254,12 @@ chrp_find_bridges(void)
printk(" at %llx", (unsigned long long)r.start);
printk("\n");
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(dev);
if (!hose) {
printk("Can't allocate PCI controller structure for %s\n",
dev->full_name);
continue;
}
- hose->arch_data = dev;
hose->first_busno = bus_range[0];
hose->last_busno = bus_range[1];
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index f2d26268ca6f..bec772674e40 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -28,6 +28,7 @@ config PPC_HOLLY
bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
select TSI108_BRIDGE
select PPC_UDBG_16550
+ select WANT_DEVICE_TREE
help
Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
Board with TSI108/9 bridge (Hickory/Holly)
@@ -44,6 +45,7 @@ endchoice
config TSI108_BRIDGE
bool
depends on MPC7448HPC2 || PPC_HOLLY
+ select PCI
select MPIC
select MPIC_WEIRD
default y
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index 3a0b4a01401c..6292e36dc577 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -45,7 +45,7 @@
#define HOLLY_PCI_CFG_PHYS 0x7c000000
-int holly_exclude_device(u_char bus, u_char devfn)
+int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
{
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index b412f006a9c5..f4d0a7a603f5 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -54,8 +54,9 @@ static struct mtd_partition linkstation_physmap_partitions[] = {
},
};
-static int __init add_bridge(struct device_node *dev)
+static int __init linkstation_add_bridge(struct device_node *dev)
{
+#ifdef CONFIG_PCI
int len;
struct pci_controller *hose;
const int *bus_range;
@@ -67,18 +68,17 @@ static int __init add_bridge(struct device_node *dev)
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(dev);
if (hose == NULL)
return -ENOMEM;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
- hose->arch_data = dev;
setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges(hose, dev, 1);
-
+#endif
return 0;
}
@@ -92,7 +92,7 @@ static void __init linkstation_setup_arch(void)
/* Lookup PCI host bridges */
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
+ linkstation_add_bridge(np);
printk(KERN_INFO "BUFFALO Network Attached Storage Series\n");
printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n");
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index 4542e0c837c0..1e3cc69487b5 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -54,15 +54,10 @@
#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
-#ifndef CONFIG_PCI
-isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
-isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
-pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
-#endif
-
extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
-int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
+int mpc7448_hpc2_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn)
{
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
index a543a5242e34..f7e0e0c7f8d8 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
@@ -18,9 +18,4 @@
#include <asm/ppcboot.h>
-/* Base Addresses for the PCI bus
- */
-#define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000)
-#define MPC7448_HPC2_ISA_IO_BASE (0x00000000)
-#define MPC7448_HPC2_ISA_MEM_BASE (0x00000000)
#endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h
index a843b0f87b72..8d95fe4b554e 100644
--- a/arch/powerpc/platforms/iseries/call_hpt.h
+++ b/arch/powerpc/platforms/iseries/call_hpt.h
@@ -76,24 +76,25 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
return compressedStatus;
}
-static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
+static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
{
return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
}
-static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
+static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
u8 bitson, u8 bitsoff)
{
return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
bitson, bitsoff);
}
-static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
+static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
{
HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
}
-static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
+ struct hash_pte *hpte)
{
HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
}
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
index ed44dfceaa45..b4e2c7a038e1 100644
--- a/arch/powerpc/platforms/iseries/htab.c
+++ b/arch/powerpc/platforms/iseries/htab.c
@@ -44,7 +44,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long vflags, int psize)
{
long slot;
- hpte_t lhpte;
+ struct hash_pte lhpte;
int secondary = 0;
BUG_ON(psize != MMU_PAGE_4K);
@@ -99,7 +99,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
static unsigned long iSeries_hpte_getword0(unsigned long slot)
{
- hpte_t hpte;
+ struct hash_pte hpte;
HvCallHpt_get(&hpte, slot);
return hpte.v;
@@ -144,7 +144,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group)
static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long va, int psize, int local)
{
- hpte_t hpte;
+ struct hash_pte hpte;
unsigned long want_v;
iSeries_hlock(slot);
@@ -176,7 +176,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
*/
static long iSeries_hpte_find(unsigned long vpn)
{
- hpte_t hpte;
+ struct hash_pte hpte;
long slot;
/*
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 9c974227155e..da87162000f0 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -742,6 +742,11 @@ void __init iSeries_pcibios_init(void)
/* Install IO hooks */
ppc_pci_io = iseries_pci_io;
+ /* iSeries has no IO space in the common sense, it needs to set
+ * the IO base to 0
+ */
+ pci_io_base = 0;
+
if (root == NULL) {
printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
"of device tree\n");
@@ -763,7 +768,7 @@ void __init iSeries_pcibios_init(void)
if (phb == NULL)
continue;
- phb->pci_mem_offset = phb->local_number = bus;
+ phb->pci_mem_offset = bus;
phb->first_busno = bus;
phb->last_busno = bus;
phb->ops = &iSeries_pci_ops;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 7f5dcee814d4..13a8b1908ded 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -79,8 +79,6 @@ extern void iSeries_pci_final_fixup(void);
static void iSeries_pci_final_fixup(void) { }
#endif
-extern unsigned long iSeries_recal_tb;
-extern unsigned long iSeries_recal_titan;
struct MemoryBlock {
unsigned long absStart;
@@ -292,8 +290,8 @@ static void __init iSeries_init_early(void)
{
DBG(" -> iSeries_init_early()\n");
- iSeries_recal_tb = get_tb();
- iSeries_recal_titan = HvCallXm_loadTod();
+ /* Snapshot the timebase, for use in later recalibration */
+ iSeries_time_init_early();
/*
* Initialize the DMA/TCE management
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 7aaa5bbc9363..fceaae40fe70 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -444,7 +444,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
u3_ht = hose;
}
-static int __init add_bridge(struct device_node *dev)
+static int __init maple_add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
@@ -519,23 +519,6 @@ void __devinit maple_pci_irq_fixup(struct pci_dev *dev)
DBG(" <- maple_pci_irq_fixup\n");
}
-static void __init maple_fixup_phb_resources(void)
-{
- struct pci_controller *hose, *tmp;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
- hose->io_resource.start += offset;
- hose->io_resource.end += offset;
-
- printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
- hose->global_number,
- (unsigned long long)hose->io_resource.start,
- (unsigned long long)hose->io_resource.end);
- }
-}
-
void __init maple_pci_init(void)
{
struct device_node *np, *root;
@@ -558,7 +541,7 @@ void __init maple_pci_init(void)
continue;
if ((of_device_is_compatible(np, "u4-pcie") ||
of_device_is_compatible(np, "u3-agp")) &&
- add_bridge(np) == 0)
+ maple_add_bridge(np) == 0)
of_node_get(np);
if (of_device_is_compatible(np, "u3-ht")) {
@@ -570,27 +553,9 @@ void __init maple_pci_init(void)
/* Now setup the HyperTransport host if we found any
*/
- if (ht && add_bridge(ht) != 0)
+ if (ht && maple_add_bridge(ht) != 0)
of_node_put(ht);
- /*
- * We need to call pci_setup_phb_io for the HT bridge first
- * so it gets the I/O port numbers starting at 0, and we
- * need to call it for the AGP bridge after that so it gets
- * small positive I/O port numbers.
- */
- if (u3_ht)
- pci_setup_phb_io(u3_ht, 1);
- if (u3_agp)
- pci_setup_phb_io(u3_agp, 0);
- if (u4_pcie)
- pci_setup_phb_io(u4_pcie, 0);
-
- /* Fixup the IO resources on our host bridges as the common code
- * does it only for childs of the host bridges
- */
- maple_fixup_phb_resources();
-
/* Setup the linkage between OF nodes and PHBs */
pci_devs_phb_init();
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 7c5076e38ea1..95cd90fd81c7 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -25,4 +25,13 @@ config PPC_PASEMI_MDIO
help
Driver for MDIO via GPIO on PWRficient platforms
+config ELECTRA_IDE
+ tristate "Electra IDE driver"
+ default y
+ depends on PPC_PASEMI && ATA
+ select PATA_PLATFORM
+ help
+ This includes driver support for the Electra on-board IDE
+ interface.
+
endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index 2cd2a4f26a48..f47fcac7e581 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,3 +1,4 @@
obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o
obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
+obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
new file mode 100644
index 000000000000..12fb0c949263
--- /dev/null
+++ b/arch/powerpc/platforms/pasemi/electra_ide.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/platform_device.h>
+
+#include <asm/prom.h>
+#include <asm/system.h>
+
+/* The electra IDE interface is incredibly simple: Just a device on the localbus
+ * with interrupts hooked up to one of the GPIOs. The device tree contains the
+ * address window and interrupt mappings already, and the pata_platform driver handles
+ * the rest. We just need to hook the two up.
+ */
+
+#define MAX_IFS 4 /* really, we have only one */
+
+static struct platform_device *pdevs[MAX_IFS];
+
+static int __devinit electra_ide_init(void)
+{
+ struct device_node *np;
+ struct resource r[3];
+ int ret = 0;
+ int i;
+
+ np = of_find_compatible_node(NULL, "ide", "electra-ide");
+ i = 0;
+
+ while (np && i < MAX_IFS) {
+ memset(r, 0, sizeof(r));
+
+ /* pata_platform wants two address ranges: one for the base registers,
+ * another for the control (altstatus). It's located at offset 0x3f6 in
+ * the window, but the device tree only has one large register window
+ * that covers both ranges. So we need to split it up by hand here:
+ */
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ goto out;
+ ret = of_address_to_resource(np, 0, &r[1]);
+ if (ret)
+ goto out;
+
+ r[1].start += 0x3f6;
+ r[0].end = r[1].start-1;
+
+ r[2].start = irq_of_parse_and_map(np, 0);
+ r[2].end = irq_of_parse_and_map(np, 0);
+ r[2].flags = IORESOURCE_IRQ;
+
+ pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
+ r[0].start, r[1].start, r[2].start);
+ pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
+ if (IS_ERR(pdevs[i])) {
+ ret = PTR_ERR(pdevs[i]);
+ pdevs[i] = NULL;
+ goto out;
+ }
+ np = of_find_compatible_node(np, "ide", "electra-ide");
+ }
+out:
+ return ret;
+}
+module_init(electra_ide_init);
+
+static void __devexit electra_ide_exit(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_IFS; i++)
+ if (pdevs[i])
+ platform_device_unregister(pdevs[i]);
+}
+module_exit(electra_ide_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra IDE driver");
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index bbc6dfcfaa91..ab1f5f62bcd8 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -132,7 +132,7 @@ static void __init setup_pa_pxp(struct pci_controller *hose)
hose->cfg_data = ioremap(0xe0000000, 0x10000000);
}
-static int __init add_bridge(struct device_node *dev)
+static int __init pas_add_bridge(struct device_node *dev)
{
struct pci_controller *hose;
@@ -150,29 +150,11 @@ static int __init add_bridge(struct device_node *dev)
printk(KERN_INFO "Found PA-PXP PCI host bridge.\n");
/* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges(hose, dev, 1);
- pci_setup_phb_io(hose, 1);
return 0;
}
-
-static void __init pas_fixup_phb_resources(void)
-{
- struct pci_controller *hose, *tmp;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
- hose->io_resource.start += offset;
- hose->io_resource.end += offset;
- printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
- hose->global_number,
- hose->io_resource.start, hose->io_resource.end);
- }
-}
-
-
void __init pas_pci_init(void)
{
struct device_node *np, *root;
@@ -185,13 +167,11 @@ void __init pas_pci_init(void)
}
for (np = NULL; (np = of_get_next_child(root, np)) != NULL;)
- if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np))
+ if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np))
of_node_get(np);
of_node_put(root);
- pas_fixup_phb_resources();
-
/* Setup the linkage between OF nodes and PHBs */
pci_devs_phb_init();
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index c5a3f61f8d85..ffe6528048b5 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -239,7 +239,7 @@ static int __init pas_probe(void)
return 1;
}
-define_machine(pas) {
+define_machine(pasemi) {
.name = "PA Semi PA6T-1682M",
.probe = pas_probe,
.setup_arch = pas_setup_arch,
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 5b7afe50039a..055990ca8ce6 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -2,6 +2,7 @@ config PPC_PMAC
bool "Apple PowerMac based machines"
depends on PPC_MULTIPLATFORM
select MPIC
+ select PCI
select PPC_INDIRECT_PCI if PPC32
select PPC_MPC106 if PPC32
select PPC_NATIVE
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 3f507ab9c5e5..efdf5eb81ecc 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -42,6 +42,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/timer.h>
+#include <linux/mutex.h>
#include <asm/keylargo.h>
#include <asm/uninorth.h>
#include <asm/io.h>
@@ -84,7 +85,7 @@ struct pmac_i2c_bus
void *hostdata;
int channel; /* some hosts have multiple */
int mode; /* current mode */
- struct semaphore sem;
+ struct mutex mutex;
int opened;
int polled; /* open mode */
struct platform_device *platform_dev;
@@ -104,7 +105,7 @@ static LIST_HEAD(pmac_i2c_busses);
struct pmac_i2c_host_kw
{
- struct semaphore mutex; /* Access mutex for use by
+ struct mutex mutex; /* Access mutex for use by
* i2c-keywest */
void __iomem *base; /* register base address */
int bsteps; /* register stepping */
@@ -375,14 +376,14 @@ static void kw_i2c_timeout(unsigned long data)
static int kw_i2c_open(struct pmac_i2c_bus *bus)
{
struct pmac_i2c_host_kw *host = bus->hostdata;
- down(&host->mutex);
+ mutex_lock(&host->mutex);
return 0;
}
static void kw_i2c_close(struct pmac_i2c_bus *bus)
{
struct pmac_i2c_host_kw *host = bus->hostdata;
- up(&host->mutex);
+ mutex_unlock(&host->mutex);
}
static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
@@ -498,7 +499,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
kfree(host);
return NULL;
}
- init_MUTEX(&host->mutex);
+ mutex_init(&host->mutex);
init_completion(&host->complete);
spin_lock_init(&host->lock);
init_timer(&host->timeout_timer);
@@ -571,7 +572,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host,
bus->open = kw_i2c_open;
bus->close = kw_i2c_close;
bus->xfer = kw_i2c_xfer;
- init_MUTEX(&bus->sem);
+ mutex_init(&bus->mutex);
if (controller == busnode)
bus->flags = pmac_i2c_multibus;
list_add(&bus->link, &pmac_i2c_busses);
@@ -798,7 +799,7 @@ static void __init pmu_i2c_probe(void)
bus->mode = pmac_i2c_mode_std;
bus->hostdata = bus + 1;
bus->xfer = pmu_i2c_xfer;
- init_MUTEX(&bus->sem);
+ mutex_init(&bus->mutex);
bus->flags = pmac_i2c_multibus;
list_add(&bus->link, &pmac_i2c_busses);
@@ -921,7 +922,7 @@ static void __init smu_i2c_probe(void)
bus->mode = pmac_i2c_mode_std;
bus->hostdata = bus + 1;
bus->xfer = smu_i2c_xfer;
- init_MUTEX(&bus->sem);
+ mutex_init(&bus->mutex);
bus->flags = 0;
list_add(&bus->link, &pmac_i2c_busses);
@@ -1093,13 +1094,13 @@ int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled)
{
int rc;
- down(&bus->sem);
+ mutex_lock(&bus->mutex);
bus->polled = polled || pmac_i2c_force_poll;
bus->opened = 1;
bus->mode = pmac_i2c_mode_std;
if (bus->open && (rc = bus->open(bus)) != 0) {
bus->opened = 0;
- up(&bus->sem);
+ mutex_unlock(&bus->mutex);
return rc;
}
return 0;
@@ -1112,7 +1113,7 @@ void pmac_i2c_close(struct pmac_i2c_bus *bus)
if (bus->close)
bus->close(bus);
bus->opened = 0;
- up(&bus->sem);
+ mutex_unlock(&bus->mutex);
}
EXPORT_SYMBOL_GPL(pmac_i2c_close);
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index c4af9e21ac93..92586db19754 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -35,8 +35,6 @@
#define DBG(x...)
#endif
-static int add_bridge(struct device_node *dev);
-
/* XXX Could be per-controller, but I don't think we risk anything by
* assuming we won't have both UniNorth and Bandit */
static int has_uninorth;
@@ -897,7 +895,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
* "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
* if we have one or more bandit or chaos bridges, we don't have a MPC106.
*/
-static int __init add_bridge(struct device_node *dev)
+static int __init pmac_add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
@@ -918,15 +916,9 @@ static int __init add_bridge(struct device_node *dev)
" bus 0\n", dev->full_name);
}
- /* XXX Different prototypes, to be merged */
-#ifdef CONFIG_PPC64
hose = pcibios_alloc_controller(dev);
-#else
- hose = pcibios_alloc_controller();
-#endif
if (!hose)
return -ENOMEM;
- hose->arch_data = dev;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -1006,19 +998,6 @@ void __devinit pmac_pci_irq_fixup(struct pci_dev *dev)
#endif /* CONFIG_PPC32 */
}
-#ifdef CONFIG_PPC64
-static void __init pmac_fixup_phb_resources(void)
-{
- struct pci_controller *hose, *tmp;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
- hose->global_number,
- hose->io_resource.start, hose->io_resource.end);
- }
-}
-#endif
-
void __init pmac_pci_init(void)
{
struct device_node *np, *root;
@@ -1036,7 +1015,7 @@ void __init pmac_pci_init(void)
if (strcmp(np->name, "bandit") == 0
|| strcmp(np->name, "chaos") == 0
|| strcmp(np->name, "pci") == 0) {
- if (add_bridge(np) == 0)
+ if (pmac_add_bridge(np) == 0)
of_node_get(np);
}
if (strcmp(np->name, "ht") == 0) {
@@ -1050,28 +1029,9 @@ void __init pmac_pci_init(void)
/* Probe HT last as it relies on the agp resources to be already
* setup
*/
- if (ht && add_bridge(ht) != 0)
+ if (ht && pmac_add_bridge(ht) != 0)
of_node_put(ht);
- /*
- * We need to call pci_setup_phb_io for the HT bridge first
- * so it gets the I/O port numbers starting at 0, and we
- * need to call it for the AGP bridge after that so it gets
- * small positive I/O port numbers.
- */
- if (u3_ht)
- pci_setup_phb_io(u3_ht, 1);
- if (u3_agp)
- pci_setup_phb_io(u3_agp, 0);
- if (u4_pcie)
- pci_setup_phb_io(u4_pcie, 0);
-
- /*
- * On ppc64, fixup the IO resources on our host bridges as
- * the common code does it only for children of the host bridges
- */
- pmac_fixup_phb_resources();
-
/* Setup the linkage between OF nodes and PHBs */
pci_devs_phb_init();
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 40f0008af4d1..a05079b07696 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -7,6 +7,7 @@ config PPC_PS3
select USB_OHCI_BIG_ENDIAN_MMIO
select USB_ARCH_HAS_EHCI
select USB_EHCI_BIG_ENDIAN_MMIO
+ select MEMORY_HOTPLUG
help
This option enables support for the Sony PS3 game console
and other platforms using the PS3 hypervisor.
@@ -73,18 +74,12 @@ config PS3_USE_LPAR_ADDR
config PS3_VUART
depends on PPC_PS3
- bool "PS3 Virtual UART support" if PS3_ADVANCED
- default y
- help
- Include support for the PS3 Virtual UART.
-
- This support is required for several system services
- including the System Manager and AV Settings. In
- general, all users will say Y.
+ tristate
config PS3_PS3AV
+ depends on PPC_PS3
tristate "PS3 AV settings driver" if PS3_ADVANCED
- depends on PS3_VUART
+ select PS3_VUART
default y
help
Include support for the PS3 AV Settings driver.
@@ -93,13 +88,18 @@ config PS3_PS3AV
general, all users will say Y or M.
config PS3_SYS_MANAGER
- bool "PS3 System Manager driver" if PS3_ADVANCED
- depends on PS3_VUART
- default y
+ depends on PPC_PS3
+ tristate "PS3 System Manager driver" if PS3_ADVANCED
+ select PS3_VUART
+ default m
help
Include support for the PS3 System Manager.
This support is required for system control. In
- general, all users will say Y.
+ general, all users will say Y or M.
+
+config PS3_STORAGE
+ depends on PPC_PS3
+ tristate
endmenu
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile
index a0048fcf0866..ac1bdf844eca 100644
--- a/arch/powerpc/platforms/ps3/Makefile
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -4,3 +4,4 @@ obj-y += system-bus.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SPU_BASE) += spu.o
+obj-y += device-init.o
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
new file mode 100644
index 000000000000..825ebb2cbc2a
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -0,0 +1,785 @@
+/*
+ * PS3 device registration routines.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+
+#include <asm/firmware.h>
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+#include "platform.h"
+
+/**
+ * ps3_setup_gelic_device - Setup and register a gelic device instance.
+ *
+ * Allocates memory for a struct ps3_system_bus_device instance, initialises the
+ * structure members, and registers the device instance with the system bus.
+ */
+
+static int __init ps3_setup_gelic_device(
+ const struct ps3_repository_device *repo)
+{
+ int result;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ struct ps3_dma_region d_region;
+ } *p;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+ BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
+
+ p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+ if (!p) {
+ result = -ENOMEM;
+ goto fail_malloc;
+ }
+
+ p->dev.match_id = PS3_MATCH_ID_GELIC;
+ p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+ p->dev.bus_id = repo->bus_id;
+ p->dev.dev_id = repo->dev_id;
+ p->dev.d_region = &p->d_region;
+
+ result = ps3_repository_find_interrupt(repo,
+ PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
+
+ if (result) {
+ pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+ __func__, __LINE__);
+ goto fail_find_interrupt;
+ }
+
+ BUG_ON(p->dev.interrupt_id != 0);
+
+ result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+ PS3_DMA_OTHER, NULL, 0);
+
+ if (result) {
+ pr_debug("%s:%d ps3_dma_region_init failed\n",
+ __func__, __LINE__);
+ goto fail_dma_init;
+ }
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result) {
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+ goto fail_device_register;
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+
+fail_device_register:
+fail_dma_init:
+fail_find_interrupt:
+ kfree(p);
+fail_malloc:
+ pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+ return result;
+}
+
+static int __init_refok ps3_setup_uhc_device(
+ const struct ps3_repository_device *repo, enum ps3_match_id match_id,
+ enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
+{
+ int result;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ struct ps3_dma_region d_region;
+ struct ps3_mmio_region m_region;
+ } *p;
+ u64 bus_addr;
+ u64 len;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+ BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
+
+ p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+ if (!p) {
+ result = -ENOMEM;
+ goto fail_malloc;
+ }
+
+ p->dev.match_id = match_id;
+ p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+ p->dev.bus_id = repo->bus_id;
+ p->dev.dev_id = repo->dev_id;
+ p->dev.d_region = &p->d_region;
+ p->dev.m_region = &p->m_region;
+
+ result = ps3_repository_find_interrupt(repo,
+ interrupt_type, &p->dev.interrupt_id);
+
+ if (result) {
+ pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+ __func__, __LINE__);
+ goto fail_find_interrupt;
+ }
+
+ result = ps3_repository_find_reg(repo, reg_type,
+ &bus_addr, &len);
+
+ if (result) {
+ pr_debug("%s:%d ps3_repository_find_reg failed\n",
+ __func__, __LINE__);
+ goto fail_find_reg;
+ }
+
+ result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+ PS3_DMA_INTERNAL, NULL, 0);
+
+ if (result) {
+ pr_debug("%s:%d ps3_dma_region_init failed\n",
+ __func__, __LINE__);
+ goto fail_dma_init;
+ }
+
+ result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
+ PS3_MMIO_4K);
+
+ if (result) {
+ pr_debug("%s:%d ps3_mmio_region_init failed\n",
+ __func__, __LINE__);
+ goto fail_mmio_init;
+ }
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result) {
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+ goto fail_device_register;
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+
+fail_device_register:
+fail_mmio_init:
+fail_dma_init:
+fail_find_reg:
+fail_find_interrupt:
+ kfree(p);
+fail_malloc:
+ pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+ return result;
+}
+
+static int __init ps3_setup_ehci_device(
+ const struct ps3_repository_device *repo)
+{
+ return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
+ PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
+}
+
+static int __init ps3_setup_ohci_device(
+ const struct ps3_repository_device *repo)
+{
+ return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
+ PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
+}
+
+static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
+ unsigned int port_number)
+{
+ int result;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ } *p;
+
+ pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
+ match_id, port_number);
+
+ p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+ if (!p)
+ return -ENOMEM;
+
+ p->dev.match_id = match_id;
+ p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
+ p->dev.port_number = port_number;
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result)
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
+ unsigned int timeout)
+{
+ int result = -1;
+ unsigned int retries = 0;
+ u64 status;
+
+ for (retries = 0; retries < timeout; retries++) {
+ result = lv1_storage_check_async_status(dev_id, tag, &status);
+ if (!result)
+ break;
+
+ msleep(1);
+ }
+
+ if (result)
+ pr_debug("%s:%u: check_async_status: %s, status %lx\n",
+ __func__, __LINE__, ps3_result(result), status);
+
+ return result;
+}
+
+/**
+ * ps3_storage_wait_for_device - Wait for a storage device to become ready.
+ * @repo: The repository device to wait for.
+ *
+ * Uses the hypervisor's storage device notification mechanism to wait until
+ * a storage device is ready. The device notification mechanism uses a
+ * psuedo device (id = -1) to asynchronously notify the guest when storage
+ * devices become ready. The notification device has a block size of 512
+ * bytes.
+ */
+
+static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
+{
+ int result;
+ const u64 notification_dev_id = (u64)-1LL;
+ const unsigned int timeout = HZ;
+ u64 lpar;
+ u64 tag;
+ struct {
+ u64 operation_code; /* must be zero */
+ u64 event_mask; /* 1 = device ready */
+ } *notify_cmd;
+ struct {
+ u64 event_type; /* notify_device_ready */
+ u64 bus_id;
+ u64 dev_id;
+ u64 dev_type;
+ u64 dev_port;
+ } *notify_event;
+ enum {
+ notify_device_ready = 1
+ };
+
+ pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__,
+ __LINE__, repo->bus_id, repo->dev_id, repo->dev_type);
+
+ notify_cmd = kzalloc(512, GFP_KERNEL);
+ notify_event = (void *)notify_cmd;
+ if (!notify_cmd)
+ return -ENOMEM;
+
+ lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd));
+
+ result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
+ if (result) {
+ printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
+ __LINE__, ps3_result(result));
+ result = -ENODEV;
+ goto fail_free;
+ }
+
+ /* Setup and write the request for device notification. */
+
+ notify_cmd->operation_code = 0; /* must be zero */
+ notify_cmd->event_mask = 0x01; /* device ready */
+
+ result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
+ &tag);
+ if (result) {
+ printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
+ ps3_result(result));
+ result = -ENODEV;
+ goto fail_close;
+ }
+
+ /* Wait for the write completion */
+
+ result = ps3stor_wait_for_completion(notification_dev_id, tag,
+ timeout);
+ if (result) {
+ printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
+ __LINE__, ps3_result(result));
+ result = -ENODEV;
+ goto fail_close;
+ }
+
+ /* Loop here processing the requested notification events. */
+
+ result = -ENODEV;
+ while (1) {
+ memset(notify_event, 0, sizeof(*notify_event));
+
+ result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,
+ lpar, &tag);
+ if (result) {
+ printk(KERN_ERR "%s:%u: write failed %s\n", __func__,
+ __LINE__, ps3_result(result));
+ break;
+ }
+
+ result = ps3stor_wait_for_completion(notification_dev_id, tag,
+ timeout);
+ if (result) {
+ printk(KERN_ERR "%s:%u: read not completed %s\n",
+ __func__, __LINE__, ps3_result(result));
+ break;
+ }
+
+ if (notify_event->event_type != notify_device_ready ||
+ notify_event->bus_id != repo->bus_id) {
+ pr_debug("%s:%u: bad notify_event: event %lu, "
+ "dev_id %lu, dev_type %lu\n",
+ __func__, __LINE__, notify_event->event_type,
+ notify_event->dev_id, notify_event->dev_type);
+ break;
+ }
+
+ if (notify_event->dev_id == repo->dev_id &&
+ notify_event->dev_type == repo->dev_type) {
+ pr_debug("%s:%u: device ready: dev_id %u\n", __func__,
+ __LINE__, repo->dev_id);
+ result = 0;
+ break;
+ }
+
+ if (notify_event->dev_id == repo->dev_id &&
+ notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
+ pr_debug("%s:%u: no access: dev_id %u\n", __func__,
+ __LINE__, repo->dev_id);
+ break;
+ }
+ }
+
+fail_close:
+ lv1_close_device(repo->bus_id, notification_dev_id);
+fail_free:
+ kfree(notify_cmd);
+ pr_debug(" <- %s:%u\n", __func__, __LINE__);
+ return result;
+}
+
+static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
+ enum ps3_match_id match_id)
+{
+ int result;
+ struct ps3_storage_device *p;
+ u64 port, blk_size, num_blocks;
+ unsigned int num_regions, i;
+
+ pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id);
+
+ result = ps3_repository_read_stor_dev_info(repo->bus_index,
+ repo->dev_index, &port,
+ &blk_size, &num_blocks,
+ &num_regions);
+ if (result) {
+ printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n",
+ __func__, __LINE__, result);
+ return -ENODEV;
+ }
+
+ pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu "
+ "num_regions %u\n", __func__, __LINE__, repo->bus_index,
+ repo->dev_index, port, blk_size, num_blocks, num_regions);
+
+ p = kzalloc(sizeof(struct ps3_storage_device) +
+ num_regions * sizeof(struct ps3_storage_region),
+ GFP_KERNEL);
+ if (!p) {
+ result = -ENOMEM;
+ goto fail_malloc;
+ }
+
+ p->sbd.match_id = match_id;
+ p->sbd.dev_type = PS3_DEVICE_TYPE_SB;
+ p->sbd.bus_id = repo->bus_id;
+ p->sbd.dev_id = repo->dev_id;
+ p->sbd.d_region = &p->dma_region;
+ p->blk_size = blk_size;
+ p->num_regions = num_regions;
+
+ result = ps3_repository_find_interrupt(repo,
+ PS3_INTERRUPT_TYPE_EVENT_PORT,
+ &p->sbd.interrupt_id);
+ if (result) {
+ printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__,
+ __LINE__, result);
+ result = -ENODEV;
+ goto fail_find_interrupt;
+ }
+
+ /* FIXME: Arrange to only do this on a 'cold' boot */
+
+ result = ps3_storage_wait_for_device(repo);
+ if (result) {
+ printk(KERN_ERR "%s:%u: storage_notification failed %d\n",
+ __func__, __LINE__, result);
+ result = -ENODEV;
+ goto fail_probe_notification;
+ }
+
+ for (i = 0; i < num_regions; i++) {
+ unsigned int id;
+ u64 start, size;
+
+ result = ps3_repository_read_stor_dev_region(repo->bus_index,
+ repo->dev_index,
+ i, &id, &start,
+ &size);
+ if (result) {
+ printk(KERN_ERR
+ "%s:%u: read_stor_dev_region failed %d\n",
+ __func__, __LINE__, result);
+ result = -ENODEV;
+ goto fail_read_region;
+ }
+ pr_debug("%s:%u: region %u: id %u start %lu size %lu\n",
+ __func__, __LINE__, i, id, start, size);
+
+ p->regions[i].id = id;
+ p->regions[i].start = start;
+ p->regions[i].size = size;
+ }
+
+ result = ps3_system_bus_device_register(&p->sbd);
+ if (result) {
+ pr_debug("%s:%u ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+ goto fail_device_register;
+ }
+
+ pr_debug(" <- %s:%u\n", __func__, __LINE__);
+ return 0;
+
+fail_device_register:
+fail_read_region:
+fail_probe_notification:
+fail_find_interrupt:
+ kfree(p);
+fail_malloc:
+ pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__);
+ return result;
+}
+
+static int __init ps3_register_vuart_devices(void)
+{
+ int result;
+ unsigned int port_number;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ result = ps3_repository_read_vuart_av_port(&port_number);
+ if (result)
+ port_number = 0; /* av default */
+
+ result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
+ WARN_ON(result);
+
+ result = ps3_repository_read_vuart_sysmgr_port(&port_number);
+ if (result)
+ port_number = 2; /* sysmgr default */
+
+ result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
+ port_number);
+ WARN_ON(result);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+static int __init ps3_register_sound_devices(void)
+{
+ int result;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ struct ps3_dma_region d_region;
+ struct ps3_mmio_region m_region;
+ } *p;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->dev.match_id = PS3_MATCH_ID_SOUND;
+ p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+ p->dev.d_region = &p->d_region;
+ p->dev.m_region = &p->m_region;
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result)
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+static int __init ps3_register_graphics_devices(void)
+{
+ int result;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ } *p;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+ if (!p)
+ return -ENOMEM;
+
+ p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+ p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result)
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+/**
+ * ps3_register_repository_device - Register a device from the repositiory info.
+ *
+ */
+
+static int ps3_register_repository_device(
+ const struct ps3_repository_device *repo)
+{
+ int result;
+
+ switch (repo->dev_type) {
+ case PS3_DEV_TYPE_SB_GELIC:
+ result = ps3_setup_gelic_device(repo);
+ if (result) {
+ pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+ __func__, __LINE__);
+ }
+ break;
+ case PS3_DEV_TYPE_SB_USB:
+
+ /* Each USB device has both an EHCI and an OHCI HC */
+
+ result = ps3_setup_ehci_device(repo);
+
+ if (result) {
+ pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+ __func__, __LINE__);
+ }
+
+ result = ps3_setup_ohci_device(repo);
+
+ if (result) {
+ pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+ __func__, __LINE__);
+ }
+ break;
+ case PS3_DEV_TYPE_STOR_DISK:
+ result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
+
+ /* Some devices are not accessable from the Other OS lpar. */
+ if (result == -ENODEV) {
+ result = 0;
+ pr_debug("%s:%u: not accessable\n", __func__,
+ __LINE__);
+ }
+
+ if (result)
+ pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+ __func__, __LINE__);
+ break;
+
+ case PS3_DEV_TYPE_STOR_ROM:
+ result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM);
+ if (result)
+ pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+ __func__, __LINE__);
+ break;
+
+ case PS3_DEV_TYPE_STOR_FLASH:
+ result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH);
+ if (result)
+ pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+ __func__, __LINE__);
+ break;
+
+ default:
+ result = 0;
+ pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
+ repo->dev_type);
+ }
+
+ return result;
+}
+
+/**
+ * ps3_probe_thread - Background repository probing at system startup.
+ *
+ * This implementation only supports background probing on a single bus.
+ */
+
+static int ps3_probe_thread(void *data)
+{
+ struct ps3_repository_device *repo = data;
+ int result;
+ unsigned int ms = 250;
+
+ pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
+
+ do {
+ try_to_freeze();
+
+ pr_debug("%s:%u: probing...\n", __func__, __LINE__);
+
+ do {
+ result = ps3_repository_find_device(repo);
+
+ if (result == -ENODEV)
+ pr_debug("%s:%u: nothing new\n", __func__,
+ __LINE__);
+ else if (result)
+ pr_debug("%s:%u: find device error.\n",
+ __func__, __LINE__);
+ else {
+ pr_debug("%s:%u: found device\n", __func__,
+ __LINE__);
+ ps3_register_repository_device(repo);
+ ps3_repository_bump_device(repo);
+ ms = 250;
+ }
+ } while (!result);
+
+ pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
+
+ if ( ms > 60000)
+ break;
+
+ msleep_interruptible(ms);
+
+ /* An exponential backoff. */
+ ms <<= 1;
+
+ } while (!kthread_should_stop());
+
+ pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
+
+ return 0;
+}
+
+/**
+ * ps3_start_probe_thread - Starts the background probe thread.
+ *
+ */
+
+static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
+{
+ int result;
+ struct task_struct *task;
+ static struct ps3_repository_device repo; /* must be static */
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ memset(&repo, 0, sizeof(repo));
+
+ repo.bus_type = bus_type;
+
+ result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
+
+ if (result) {
+ printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
+ return -ENODEV;
+ }
+
+ result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
+
+ if (result) {
+ printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
+ result);
+ return -ENODEV;
+ }
+
+ task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
+
+ if (IS_ERR(task)) {
+ result = PTR_ERR(task);
+ printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
+ result);
+ return result;
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return 0;
+}
+
+/**
+ * ps3_register_devices - Probe the system and register devices found.
+ *
+ * A device_initcall() routine.
+ */
+
+static int __init ps3_register_devices(void)
+{
+ int result;
+
+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return -ENODEV;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ /* ps3_repository_dump_bus_info(); */
+
+ result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
+
+ ps3_register_vuart_devices();
+
+ ps3_register_graphics_devices();
+
+ ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+ ps3_register_repository_device);
+
+ ps3_register_sound_devices();
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return 0;
+}
+
+device_initcall(ps3_register_devices);
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index a1409e450c70..5d2e176a1b18 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -29,12 +29,12 @@
#include "platform.h"
#if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
#else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
#endif
-static hpte_t *htab;
+static struct hash_pte *htab;
static unsigned long htab_addr;
static unsigned char *bolttab;
static unsigned char *inusetab;
@@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(ps3_bolttab_lock);
#define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
_debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
static void _debug_dump_hpte(unsigned long pa, unsigned long va,
- unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
- unsigned long slot, const char* func, int line)
+ unsigned long group, unsigned long bitmap, struct hash_pte lhpte,
+ int psize, unsigned long slot, const char* func, int line)
{
DBG("%s:%d: pa = %lxh\n", func, line, pa);
DBG("%s:%d: lpar = %lxh\n", func, line,
@@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
{
unsigned long slot;
- hpte_t lhpte;
+ struct hash_pte lhpte;
int secondary = 0;
unsigned long result;
unsigned long bitmap;
@@ -234,10 +234,17 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
static void ps3_hpte_clear(void)
{
- /* Make sure to clean up the frame buffer device first */
- ps3fb_cleanup();
+ int result;
- lv1_unmap_htab(htab_addr);
+ DBG(" -> %s:%d\n", __func__, __LINE__);
+
+ result = lv1_unmap_htab(htab_addr);
+ BUG_ON(result);
+
+ ps3_mm_shutdown();
+ ps3_mm_vas_destroy();
+
+ DBG(" <- %s:%d\n", __func__, __LINE__);
}
void __init ps3_hpte_init(unsigned long htab_size)
@@ -255,7 +262,7 @@ void __init ps3_hpte_init(unsigned long htab_size)
ppc64_pft_size = __ilog2(htab_size);
- bitmap_size = htab_size / sizeof(hpte_t) / 8;
+ bitmap_size = htab_size / sizeof(struct hash_pte) / 8;
bolttab = __va(lmb_alloc(bitmap_size, 1));
inusetab = __va(lmb_alloc(bitmap_size, 1));
@@ -273,8 +280,8 @@ void __init ps3_map_htab(void)
result = lv1_map_htab(0, &htab_addr);
- htab = (hpte_t *)__ioremap(htab_addr, htab_size,
- pgprot_val(PAGE_READONLY_X));
+ htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size,
+ pgprot_val(PAGE_READONLY_X));
DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
htab_addr, (unsigned long)htab);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index ec9030dbb5f1..67e32ec9b37e 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -30,9 +30,9 @@
#include "platform.h"
#if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
#else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
#endif
/**
@@ -78,19 +78,85 @@ struct ps3_bmp {
/**
* struct ps3_private - a per cpu data structure
* @bmp: ps3_bmp structure
- * @node: HV logical_ppe_id
- * @cpu: HV thread_id
+ * @ppe_id: HV logical_ppe_id
+ * @thread_id: HV thread_id
*/
struct ps3_private {
struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
- u64 node;
- unsigned int cpu;
+ u64 ppe_id;
+ u64 thread_id;
};
static DEFINE_PER_CPU(struct ps3_private, ps3_private);
/**
+ * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_mask(unsigned int virq)
+{
+ struct ps3_private *pd = get_irq_chip_data(virq);
+ unsigned long flags;
+
+ pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+ pd->thread_id, virq);
+
+ local_irq_save(flags);
+ clear_bit(63 - virq, &pd->bmp.mask);
+ lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+ local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_unmask(unsigned int virq)
+{
+ struct ps3_private *pd = get_irq_chip_data(virq);
+ unsigned long flags;
+
+ pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+ pd->thread_id, virq);
+
+ local_irq_save(flags);
+ set_bit(63 - virq, &pd->bmp.mask);
+ lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+ local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_eoi - HV end-of-interrupt.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls lv1_end_of_interrupt_ext().
+ */
+
+static void ps3_chip_eoi(unsigned int virq)
+{
+ const struct ps3_private *pd = get_irq_chip_data(virq);
+ lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
+}
+
+/**
+ * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
+ */
+
+static struct irq_chip ps3_irq_chip = {
+ .typename = "ps3",
+ .mask = ps3_chip_mask,
+ .unmask = ps3_chip_unmask,
+ .eoi = ps3_chip_eoi,
+};
+
+/**
* ps3_virq_setup - virq related setup.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
@@ -134,6 +200,8 @@ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
goto fail_set;
}
+ ps3_chip_mask(*virq);
+
return result;
fail_set:
@@ -153,8 +221,8 @@ int ps3_virq_destroy(unsigned int virq)
{
const struct ps3_private *pd = get_irq_chip_data(virq);
- pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
- pd->node, pd->cpu, virq);
+ pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+ __LINE__, pd->ppe_id, pd->thread_id, virq);
set_irq_chip_data(virq, NULL);
irq_dispose_mapping(virq);
@@ -190,7 +258,8 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
/* Binds outlet to cpu + virq. */
- result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
+ result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
+ outlet, 0);
if (result) {
pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
@@ -222,10 +291,12 @@ int ps3_irq_plug_destroy(unsigned int virq)
int result;
const struct ps3_private *pd = get_irq_chip_data(virq);
- pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
- pd->node, pd->cpu, virq);
+ pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+ __LINE__, pd->ppe_id, pd->thread_id, virq);
+
+ ps3_chip_mask(virq);
- result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
+ result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
if (result)
pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
@@ -282,7 +353,9 @@ int ps3_event_receive_port_destroy(unsigned int virq)
{
int result;
- pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
+ pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
+
+ ps3_chip_mask(virq);
result = lv1_destruct_event_receive_port(virq_to_hw(virq));
@@ -290,17 +363,14 @@ int ps3_event_receive_port_destroy(unsigned int virq)
pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
__func__, __LINE__, ps3_result(result));
- /* lv1_destruct_event_receive_port() destroys the IRQ plug,
- * so don't call ps3_irq_plug_destroy() here.
+ /*
+ * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
+ * calls from interrupt context (smp_call_function) when kexecing.
*/
- result = ps3_virq_destroy(virq);
- BUG_ON(result);
-
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result;
}
-EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
int ps3_send_event_locally(unsigned int virq)
{
@@ -311,17 +381,15 @@ int ps3_send_event_locally(unsigned int virq)
* ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
- * @did: The HV device identifier read from the system repository.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @dev: The system bus device instance.
* @virq: The assigned Linux virq.
*
* An event irq represents a virtual device interrupt. The interrupt_id
* coresponds to the software interrupt number.
*/
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
- const struct ps3_device_id *did, unsigned int interrupt_id,
- unsigned int *virq)
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+ enum ps3_cpu_binding cpu, unsigned int *virq)
{
/* this should go in system-bus.c */
@@ -332,8 +400,8 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
if (result)
return result;
- result = lv1_connect_interrupt_event_receive_port(did->bus_id,
- did->dev_id, virq_to_hw(*virq), interrupt_id);
+ result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
+ dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
if (result) {
pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
@@ -345,24 +413,24 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
}
pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
- interrupt_id, *virq);
+ dev->interrupt_id, *virq);
return 0;
}
EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
- unsigned int interrupt_id, unsigned int virq)
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+ unsigned int virq)
{
/* this should go in system-bus.c */
int result;
pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
- interrupt_id, virq);
+ dev->interrupt_id, virq);
- result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
- did->dev_id, virq_to_hw(virq), interrupt_id);
+ result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
+ dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
if (result)
pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
@@ -372,6 +440,14 @@ int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
result = ps3_event_receive_port_destroy(virq);
BUG_ON(result);
+ /*
+ * ps3_event_receive_port_destroy() destroys the IRQ plug,
+ * so don't call ps3_irq_plug_destroy() here.
+ */
+
+ result = ps3_virq_destroy(virq);
+ BUG_ON(result);
+
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result;
}
@@ -412,16 +488,24 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
int ps3_io_irq_destroy(unsigned int virq)
{
int result;
+ unsigned long outlet = virq_to_hw(virq);
- result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+ ps3_chip_mask(virq);
- if (result)
- pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
- __func__, __LINE__, ps3_result(result));
+ /*
+ * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
+ * so call ps3_irq_plug_destroy() first.
+ */
result = ps3_irq_plug_destroy(virq);
BUG_ON(result);
+ result = lv1_destruct_io_irq_outlet(outlet);
+
+ if (result)
+ pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
return result;
}
EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
@@ -461,11 +545,13 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
return result;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
int ps3_vuart_irq_destroy(unsigned int virq)
{
int result;
+ ps3_chip_mask(virq);
result = lv1_deconfigure_virtual_uart_irq();
if (result) {
@@ -479,6 +565,7 @@ int ps3_vuart_irq_destroy(unsigned int virq)
return result;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
/**
* ps3_spe_irq_setup - Setup an spe virq.
@@ -514,9 +601,14 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
int ps3_spe_irq_destroy(unsigned int virq)
{
- int result = ps3_irq_plug_destroy(virq);
+ int result;
+
+ ps3_chip_mask(virq);
+
+ result = ps3_irq_plug_destroy(virq);
BUG_ON(result);
- return 0;
+
+ return result;
}
@@ -533,7 +625,7 @@ static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu,
*p & 0xffff);
}
-static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
+static void __maybe_unused _dump_256_bmp(const char *header,
const u64 *p, unsigned cpu, const char* func, int line)
{
pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
@@ -546,86 +638,25 @@ static void _dump_bmp(struct ps3_private* pd, const char* func, int line)
unsigned long flags;
spin_lock_irqsave(&pd->bmp.lock, flags);
- _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line);
- _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+ _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
+ _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
spin_unlock_irqrestore(&pd->bmp.lock, flags);
}
#define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd,
+static void __maybe_unused _dump_mask(struct ps3_private *pd,
const char* func, int line)
{
unsigned long flags;
spin_lock_irqsave(&pd->bmp.lock, flags);
- _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+ _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
spin_unlock_irqrestore(&pd->bmp.lock, flags);
}
#else
static void dump_bmp(struct ps3_private* pd) {};
#endif /* defined(DEBUG) */
-static void ps3_chip_mask(unsigned int virq)
-{
- struct ps3_private *pd = get_irq_chip_data(virq);
- u64 bit = 0x8000000000000000UL >> virq;
- u64 *p = &pd->bmp.mask;
- u64 old;
- unsigned long flags;
-
- pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
- local_irq_save(flags);
- asm volatile(
- "1: ldarx %0,0,%3\n"
- "andc %0,%0,%2\n"
- "stdcx. %0,0,%3\n"
- "bne- 1b"
- : "=&r" (old), "+m" (*p)
- : "r" (bit), "r" (p)
- : "cc" );
-
- lv1_did_update_interrupt_mask(pd->node, pd->cpu);
- local_irq_restore(flags);
-}
-
-static void ps3_chip_unmask(unsigned int virq)
-{
- struct ps3_private *pd = get_irq_chip_data(virq);
- u64 bit = 0x8000000000000000UL >> virq;
- u64 *p = &pd->bmp.mask;
- u64 old;
- unsigned long flags;
-
- pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
- local_irq_save(flags);
- asm volatile(
- "1: ldarx %0,0,%3\n"
- "or %0,%0,%2\n"
- "stdcx. %0,0,%3\n"
- "bne- 1b"
- : "=&r" (old), "+m" (*p)
- : "r" (bit), "r" (p)
- : "cc" );
-
- lv1_did_update_interrupt_mask(pd->node, pd->cpu);
- local_irq_restore(flags);
-}
-
-static void ps3_chip_eoi(unsigned int virq)
-{
- const struct ps3_private *pd = get_irq_chip_data(virq);
- lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
-}
-
-static struct irq_chip irq_chip = {
- .typename = "ps3",
- .mask = ps3_chip_mask,
- .unmask = ps3_chip_unmask,
- .eoi = ps3_chip_eoi,
-};
-
static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
{
set_irq_chip_data(virq, NULL);
@@ -637,7 +668,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
virq);
- set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
+ set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
return 0;
}
@@ -657,7 +688,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
cpu, virq, pd->bmp.ipi_debug_brk_mask);
}
-unsigned int ps3_get_irq(void)
+static unsigned int ps3_get_irq(void)
{
struct ps3_private *pd = &__get_cpu_var(ps3_private);
u64 x = (pd->bmp.status & pd->bmp.mask);
@@ -672,8 +703,8 @@ unsigned int ps3_get_irq(void)
plug &= 0x3f;
if (unlikely(plug) == NO_IRQ) {
- pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__,
- pd->cpu);
+ pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+ __LINE__, pd->thread_id);
dump_bmp(&per_cpu(ps3_private, 0));
dump_bmp(&per_cpu(ps3_private, 1));
return NO_IRQ;
@@ -703,16 +734,16 @@ void __init ps3_init_IRQ(void)
for_each_possible_cpu(cpu) {
struct ps3_private *pd = &per_cpu(ps3_private, cpu);
- lv1_get_logical_ppe_id(&pd->node);
- pd->cpu = get_hard_smp_processor_id(cpu);
+ lv1_get_logical_ppe_id(&pd->ppe_id);
+ pd->thread_id = get_hard_smp_processor_id(cpu);
spin_lock_init(&pd->bmp.lock);
- pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
- __LINE__, pd->node, pd->cpu,
+ pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n",
+ __func__, __LINE__, pd->ppe_id, pd->thread_id,
ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
- result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
- ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
+ result = lv1_configure_irq_state_bitmap(pd->ppe_id,
+ pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
if (result)
pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
@@ -722,3 +753,16 @@ void __init ps3_init_IRQ(void)
ppc_md.get_irq = ps3_get_irq;
}
+
+void ps3_shutdown_IRQ(int cpu)
+{
+ int result;
+ u64 ppe_id;
+ u64 thread_id = get_hard_smp_processor_id(cpu);
+
+ lv1_get_logical_ppe_id(&ppe_id);
+ result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
+
+ DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
+ __LINE__, ppe_id, thread_id, cpu, ps3_result(result));
+}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index f8a3e206c584..7bb3e1620974 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -30,9 +30,9 @@
#include "platform.h"
#if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
#else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
#endif
enum {
@@ -115,7 +115,8 @@ struct map {
};
#define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
-static void _debug_dump_map(const struct map* m, const char* func, int line)
+static void __maybe_unused _debug_dump_map(const struct map *m,
+ const char *func, int line)
{
DBG("%s:%d: map.total = %lxh\n", func, line, m->total);
DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size);
@@ -212,9 +213,15 @@ fail:
void ps3_mm_vas_destroy(void)
{
+ int result;
+
+ DBG("%s:%d: map.vas_id = %lu\n", __func__, __LINE__, map.vas_id);
+
if (map.vas_id) {
- lv1_select_virtual_address_space(0);
- lv1_destruct_virtual_address_space(map.vas_id);
+ result = lv1_select_virtual_address_space(0);
+ BUG_ON(result);
+ result = lv1_destruct_virtual_address_space(map.vas_id);
+ BUG_ON(result);
map.vas_id = 0;
}
}
@@ -232,7 +239,7 @@ void ps3_mm_vas_destroy(void)
* @size is rounded down to a multiple of the vas large page size.
*/
-int ps3_mm_region_create(struct mem_region *r, unsigned long size)
+static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
{
int result;
unsigned long muid;
@@ -273,10 +280,14 @@ zero_region:
* @r: pointer to struct mem_region
*/
-void ps3_mm_region_destroy(struct mem_region *r)
+static void ps3_mm_region_destroy(struct mem_region *r)
{
+ int result;
+
+ DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base);
if (r->base) {
- lv1_release_memory(r->base);
+ result = lv1_release_memory(r->base);
+ BUG_ON(result);
r->size = r->base = r->offset = 0;
map.total = map.rm.size;
}
@@ -329,31 +340,34 @@ core_initcall(ps3_mm_add_memory);
/*============================================================================*/
/**
- * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
+ * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
* @r: pointer to dma region structure
* @lpar_addr: HV lpar address
*/
-static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r,
+static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
unsigned long lpar_addr)
{
- BUG_ON(lpar_addr >= map.r1.base + map.r1.size);
- return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr
- : lpar_addr - map.r1.offset);
+ if (lpar_addr >= map.rm.size)
+ lpar_addr -= map.r1.offset;
+ BUG_ON(lpar_addr < r->offset);
+ BUG_ON(lpar_addr >= r->offset + r->len);
+ return r->bus_addr + lpar_addr - r->offset;
}
#define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__)
-static void _dma_dump_region(const struct ps3_dma_region *r, const char* func,
- int line)
+static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
+ const char *func, int line)
{
- DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id,
- r->did.dev_id);
+ DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id,
+ r->dev->dev_id);
DBG("%s:%d: page_size %u\n", func, line, r->page_size);
DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
DBG("%s:%d: len %lxh\n", func, line, r->len);
+ DBG("%s:%d: offset %lxh\n", func, line, r->offset);
}
-/**
+ /**
* dma_chunk - A chunk of dma pages mapped by the io controller.
* @region - The dma region that owns this chunk.
* @lpar_addr: Starting lpar address of the area to map.
@@ -381,10 +395,11 @@ static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
int line)
{
DBG("%s:%d: r.dev %u:%u\n", func, line,
- c->region->did.bus_id, c->region->did.dev_id);
+ c->region->dev->bus_id, c->region->dev->dev_id);
DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr);
DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size);
DBG("%s:%d: r.len %lxh\n", func, line, c->region->len);
+ DBG("%s:%d: r.offset %lxh\n", func, line, c->region->offset);
DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr);
DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr);
DBG("%s:%d: c.len %lxh\n", func, line, c->len);
@@ -395,39 +410,68 @@ static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r,
{
struct dma_chunk *c;
unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size);
- unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+ unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus,
+ 1 << r->page_size);
list_for_each_entry(c, &r->chunk_list.head, link) {
/* intersection */
- if (aligned_bus >= c->bus_addr
- && aligned_bus < c->bus_addr + c->len
- && aligned_bus + aligned_len <= c->bus_addr + c->len) {
+ if (aligned_bus >= c->bus_addr &&
+ aligned_bus + aligned_len <= c->bus_addr + c->len)
return c;
- }
+
/* below */
- if (aligned_bus + aligned_len <= c->bus_addr) {
+ if (aligned_bus + aligned_len <= c->bus_addr)
continue;
- }
+
/* above */
- if (aligned_bus >= c->bus_addr + c->len) {
+ if (aligned_bus >= c->bus_addr + c->len)
continue;
- }
/* we don't handle the multi-chunk case for now */
-
dma_dump_chunk(c);
BUG();
}
return NULL;
}
-static int dma_free_chunk(struct dma_chunk *c)
+static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r,
+ unsigned long lpar_addr, unsigned long len)
+{
+ struct dma_chunk *c;
+ unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size);
+ unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar,
+ 1 << r->page_size);
+
+ list_for_each_entry(c, &r->chunk_list.head, link) {
+ /* intersection */
+ if (c->lpar_addr <= aligned_lpar &&
+ aligned_lpar < c->lpar_addr + c->len) {
+ if (aligned_lpar + aligned_len <= c->lpar_addr + c->len)
+ return c;
+ else {
+ dma_dump_chunk(c);
+ BUG();
+ }
+ }
+ /* below */
+ if (aligned_lpar + aligned_len <= c->lpar_addr) {
+ continue;
+ }
+ /* above */
+ if (c->lpar_addr + c->len <= aligned_lpar) {
+ continue;
+ }
+ }
+ return NULL;
+}
+
+static int dma_sb_free_chunk(struct dma_chunk *c)
{
int result = 0;
if (c->bus_addr) {
- result = lv1_unmap_device_dma_region(c->region->did.bus_id,
- c->region->did.dev_id, c->bus_addr, c->len);
+ result = lv1_unmap_device_dma_region(c->region->dev->bus_id,
+ c->region->dev->dev_id, c->bus_addr, c->len);
BUG_ON(result);
}
@@ -435,8 +479,39 @@ static int dma_free_chunk(struct dma_chunk *c)
return result;
}
+static int dma_ioc0_free_chunk(struct dma_chunk *c)
+{
+ int result = 0;
+ int iopage;
+ unsigned long offset;
+ struct ps3_dma_region *r = c->region;
+
+ DBG("%s:start\n", __func__);
+ for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) {
+ offset = (1 << r->page_size) * iopage;
+ /* put INVALID entry */
+ result = lv1_put_iopte(0,
+ c->bus_addr + offset,
+ c->lpar_addr + offset,
+ r->ioid,
+ 0);
+ DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__,
+ c->bus_addr + offset,
+ c->lpar_addr + offset,
+ r->ioid);
+
+ if (result) {
+ DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__,
+ __LINE__, ps3_result(result));
+ }
+ }
+ kfree(c);
+ DBG("%s:end\n", __func__);
+ return result;
+}
+
/**
- * dma_map_pages - Maps dma pages into the io controller bus address space.
+ * dma_sb_map_pages - Maps dma pages into the io controller bus address space.
* @r: Pointer to a struct ps3_dma_region.
* @phys_addr: Starting physical address of the area to map.
* @len: Length in bytes of the area to map.
@@ -446,8 +521,8 @@ static int dma_free_chunk(struct dma_chunk *c)
* make the HV call to add the pages into the io controller address space.
*/
-static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
- unsigned long len, struct dma_chunk **c_out)
+static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+ unsigned long len, struct dma_chunk **c_out, u64 iopte_flag)
{
int result;
struct dma_chunk *c;
@@ -461,13 +536,13 @@ static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
c->region = r;
c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
- c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr);
+ c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr);
c->len = len;
- result = lv1_map_device_dma_region(c->region->did.bus_id,
- c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len,
- 0xf800000000000000UL);
-
+ BUG_ON(iopte_flag != 0xf800000000000000UL);
+ result = lv1_map_device_dma_region(c->region->dev->bus_id,
+ c->region->dev->dev_id, c->lpar_addr,
+ c->bus_addr, c->len, iopte_flag);
if (result) {
DBG("%s:%d: lv1_map_device_dma_region failed: %s\n",
__func__, __LINE__, ps3_result(result));
@@ -487,26 +562,120 @@ fail_alloc:
return result;
}
+static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+ unsigned long len, struct dma_chunk **c_out,
+ u64 iopte_flag)
+{
+ int result;
+ struct dma_chunk *c, *last;
+ int iopage, pages;
+ unsigned long offset;
+
+ DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__,
+ phys_addr, ps3_mm_phys_to_lpar(phys_addr), len);
+ c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
+
+ if (!c) {
+ result = -ENOMEM;
+ goto fail_alloc;
+ }
+
+ c->region = r;
+ c->len = len;
+ c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
+ /* allocate IO address */
+ if (list_empty(&r->chunk_list.head)) {
+ /* first one */
+ c->bus_addr = r->bus_addr;
+ } else {
+ /* derive from last bus addr*/
+ last = list_entry(r->chunk_list.head.next,
+ struct dma_chunk, link);
+ c->bus_addr = last->bus_addr + last->len;
+ DBG("%s: last bus=%#lx, len=%#lx\n", __func__,
+ last->bus_addr, last->len);
+ }
+
+ /* FIXME: check whether length exceeds region size */
+
+ /* build ioptes for the area */
+ pages = len >> r->page_size;
+ DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__,
+ r->page_size, r->len, pages, iopte_flag);
+ for (iopage = 0; iopage < pages; iopage++) {
+ offset = (1 << r->page_size) * iopage;
+ result = lv1_put_iopte(0,
+ c->bus_addr + offset,
+ c->lpar_addr + offset,
+ r->ioid,
+ iopte_flag);
+ if (result) {
+ printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region "
+ "failed: %s\n", __func__, __LINE__,
+ ps3_result(result));
+ goto fail_map;
+ }
+ DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__,
+ iopage, c->bus_addr + offset, c->lpar_addr + offset,
+ r->ioid);
+ }
+
+ /* be sure that last allocated one is inserted at head */
+ list_add(&c->link, &r->chunk_list.head);
+
+ *c_out = c;
+ DBG("%s: end\n", __func__);
+ return 0;
+
+fail_map:
+ for (iopage--; 0 <= iopage; iopage--) {
+ lv1_put_iopte(0,
+ c->bus_addr + offset,
+ c->lpar_addr + offset,
+ r->ioid,
+ 0);
+ }
+ kfree(c);
+fail_alloc:
+ *c_out = NULL;
+ return result;
+}
+
/**
- * dma_region_create - Create a device dma region.
+ * dma_sb_region_create - Create a device dma region.
* @r: Pointer to a struct ps3_dma_region.
*
* This is the lowest level dma region create routine, and is the one that
* will make the HV call to create the region.
*/
-static int dma_region_create(struct ps3_dma_region* r)
+static int dma_sb_region_create(struct ps3_dma_region *r)
{
int result;
- r->len = _ALIGN_UP(map.total, 1 << r->page_size);
+ pr_info(" -> %s:%d:\n", __func__, __LINE__);
+
+ BUG_ON(!r);
+
+ if (!r->dev->bus_id) {
+ pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+ r->dev->bus_id, r->dev->dev_id);
+ return 0;
+ }
+
+ DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__,
+ __LINE__, r->len, r->page_size, r->offset);
+
+ BUG_ON(!r->len);
+ BUG_ON(!r->page_size);
+ BUG_ON(!r->region_ops);
+
INIT_LIST_HEAD(&r->chunk_list.head);
spin_lock_init(&r->chunk_list.lock);
- result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id,
- r->len, r->page_size, r->region_type, &r->bus_addr);
-
- dma_dump_region(r);
+ result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id,
+ roundup_pow_of_two(r->len), r->page_size, r->region_type,
+ &r->bus_addr);
if (result) {
DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
@@ -517,6 +686,27 @@ static int dma_region_create(struct ps3_dma_region* r)
return result;
}
+static int dma_ioc0_region_create(struct ps3_dma_region *r)
+{
+ int result;
+
+ INIT_LIST_HEAD(&r->chunk_list.head);
+ spin_lock_init(&r->chunk_list.lock);
+
+ result = lv1_allocate_io_segment(0,
+ r->len,
+ r->page_size,
+ &r->bus_addr);
+ if (result) {
+ DBG("%s:%d: lv1_allocate_io_segment failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ r->len = r->bus_addr = 0;
+ }
+ DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__,
+ r->len, r->page_size, r->bus_addr);
+ return result;
+}
+
/**
* dma_region_free - Free a device dma region.
* @r: Pointer to a struct ps3_dma_region.
@@ -525,31 +715,62 @@ static int dma_region_create(struct ps3_dma_region* r)
* will make the HV call to free the region.
*/
-static int dma_region_free(struct ps3_dma_region* r)
+static int dma_sb_region_free(struct ps3_dma_region *r)
{
int result;
struct dma_chunk *c;
struct dma_chunk *tmp;
+ BUG_ON(!r);
+
+ if (!r->dev->bus_id) {
+ pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+ r->dev->bus_id, r->dev->dev_id);
+ return 0;
+ }
+
list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
list_del(&c->link);
- dma_free_chunk(c);
+ dma_sb_free_chunk(c);
}
- result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id,
+ result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id,
r->bus_addr);
if (result)
DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
__func__, __LINE__, ps3_result(result));
- r->len = r->bus_addr = 0;
+ r->bus_addr = 0;
+
+ return result;
+}
+
+static int dma_ioc0_region_free(struct ps3_dma_region *r)
+{
+ int result;
+ struct dma_chunk *c, *n;
+
+ DBG("%s: start\n", __func__);
+ list_for_each_entry_safe(c, n, &r->chunk_list.head, link) {
+ list_del(&c->link);
+ dma_ioc0_free_chunk(c);
+ }
+
+ result = lv1_release_io_segment(0, r->bus_addr);
+
+ if (result)
+ DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
+ r->bus_addr = 0;
+ DBG("%s: end\n", __func__);
return result;
}
/**
- * dma_map_area - Map an area of memory into a device dma region.
+ * dma_sb_map_area - Map an area of memory into a device dma region.
* @r: Pointer to a struct ps3_dma_region.
* @virt_addr: Starting virtual address of the area to map.
* @len: Length in bytes of the area to map.
@@ -559,16 +780,19 @@ static int dma_region_free(struct ps3_dma_region* r)
* This is the common dma mapping routine.
*/
-static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+ unsigned long len, unsigned long *bus_addr,
+ u64 iopte_flag)
{
int result;
unsigned long flags;
struct dma_chunk *c;
unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
: virt_addr;
-
- *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+ unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+ unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+ 1 << r->page_size);
+ *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
if (!USE_DYNAMIC_DMA) {
unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
@@ -588,17 +812,18 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
c = dma_find_chunk(r, *bus_addr, len);
if (c) {
+ DBG("%s:%d: reusing mapped chunk", __func__, __LINE__);
+ dma_dump_chunk(c);
c->usage_count++;
spin_unlock_irqrestore(&r->chunk_list.lock, flags);
return 0;
}
- result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size),
- _ALIGN_UP(len, 1 << r->page_size), &c);
+ result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag);
if (result) {
*bus_addr = 0;
- DBG("%s:%d: dma_map_pages failed (%d)\n",
+ DBG("%s:%d: dma_sb_map_pages failed (%d)\n",
__func__, __LINE__, result);
spin_unlock_irqrestore(&r->chunk_list.lock, flags);
return result;
@@ -610,8 +835,57 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
return result;
}
+static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+ unsigned long len, unsigned long *bus_addr,
+ u64 iopte_flag)
+{
+ int result;
+ unsigned long flags;
+ struct dma_chunk *c;
+ unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
+ : virt_addr;
+ unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+ unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+ 1 << r->page_size);
+
+ DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__,
+ virt_addr, len);
+ DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__,
+ phys_addr, aligned_phys, aligned_len);
+
+ spin_lock_irqsave(&r->chunk_list.lock, flags);
+ c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len);
+
+ if (c) {
+ /* FIXME */
+ BUG();
+ *bus_addr = c->bus_addr + phys_addr - aligned_phys;
+ c->usage_count++;
+ spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+ return 0;
+ }
+
+ result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c,
+ iopte_flag);
+
+ if (result) {
+ *bus_addr = 0;
+ DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n",
+ __func__, __LINE__, result);
+ spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+ return result;
+ }
+ *bus_addr = c->bus_addr + phys_addr - aligned_phys;
+ DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__,
+ virt_addr, phys_addr, aligned_phys, *bus_addr);
+ c->usage_count = 1;
+
+ spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+ return result;
+}
+
/**
- * dma_unmap_area - Unmap an area of memory from a device dma region.
+ * dma_sb_unmap_area - Unmap an area of memory from a device dma region.
* @r: Pointer to a struct ps3_dma_region.
* @bus_addr: The starting ioc bus address of the area to unmap.
* @len: Length in bytes of the area to unmap.
@@ -619,7 +893,7 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
* This is the common dma unmap routine.
*/
-int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
+static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
unsigned long len)
{
unsigned long flags;
@@ -631,7 +905,8 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
if (!c) {
unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
1 << r->page_size);
- unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+ unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+ - aligned_bus, 1 << r->page_size);
DBG("%s:%d: not found: bus_addr %lxh\n",
__func__, __LINE__, bus_addr);
DBG("%s:%d: not found: len %lxh\n",
@@ -647,94 +922,166 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
if (!c->usage_count) {
list_del(&c->link);
- dma_free_chunk(c);
+ dma_sb_free_chunk(c);
}
spin_unlock_irqrestore(&r->chunk_list.lock, flags);
return 0;
}
+static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
+ unsigned long bus_addr, unsigned long len)
+{
+ unsigned long flags;
+ struct dma_chunk *c;
+
+ DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len);
+ spin_lock_irqsave(&r->chunk_list.lock, flags);
+ c = dma_find_chunk(r, bus_addr, len);
+
+ if (!c) {
+ unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
+ 1 << r->page_size);
+ unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+ - aligned_bus,
+ 1 << r->page_size);
+ DBG("%s:%d: not found: bus_addr %lxh\n",
+ __func__, __LINE__, bus_addr);
+ DBG("%s:%d: not found: len %lxh\n",
+ __func__, __LINE__, len);
+ DBG("%s:%d: not found: aligned_bus %lxh\n",
+ __func__, __LINE__, aligned_bus);
+ DBG("%s:%d: not found: aligned_len %lxh\n",
+ __func__, __LINE__, aligned_len);
+ BUG();
+ }
+
+ c->usage_count--;
+
+ if (!c->usage_count) {
+ list_del(&c->link);
+ dma_ioc0_free_chunk(c);
+ }
+
+ spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+ DBG("%s: end\n", __func__);
+ return 0;
+}
+
/**
- * dma_region_create_linear - Setup a linear dma maping for a device.
+ * dma_sb_region_create_linear - Setup a linear dma mapping for a device.
* @r: Pointer to a struct ps3_dma_region.
*
* This routine creates an HV dma region for the device and maps all available
* ram into the io controller bus address space.
*/
-static int dma_region_create_linear(struct ps3_dma_region *r)
+static int dma_sb_region_create_linear(struct ps3_dma_region *r)
{
int result;
- unsigned long tmp;
-
- /* force 16M dma pages for linear mapping */
-
- if (r->page_size != PS3_DMA_16M) {
- pr_info("%s:%d: forcing 16M pages for linear map\n",
- __func__, __LINE__);
- r->page_size = PS3_DMA_16M;
+ unsigned long virt_addr, len, tmp;
+
+ if (r->len > 16*1024*1024) { /* FIXME: need proper fix */
+ /* force 16M dma pages for linear mapping */
+ if (r->page_size != PS3_DMA_16M) {
+ pr_info("%s:%d: forcing 16M pages for linear map\n",
+ __func__, __LINE__);
+ r->page_size = PS3_DMA_16M;
+ r->len = _ALIGN_UP(r->len, 1 << r->page_size);
+ }
}
- result = dma_region_create(r);
+ result = dma_sb_region_create(r);
BUG_ON(result);
- result = dma_map_area(r, map.rm.base, map.rm.size, &tmp);
- BUG_ON(result);
-
- if (USE_LPAR_ADDR)
- result = dma_map_area(r, map.r1.base, map.r1.size,
- &tmp);
- else
- result = dma_map_area(r, map.rm.size, map.r1.size,
- &tmp);
+ if (r->offset < map.rm.size) {
+ /* Map (part of) 1st RAM chunk */
+ virt_addr = map.rm.base + r->offset;
+ len = map.rm.size - r->offset;
+ if (len > r->len)
+ len = r->len;
+ result = dma_sb_map_area(r, virt_addr, len, &tmp,
+ IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+ BUG_ON(result);
+ }
- BUG_ON(result);
+ if (r->offset + r->len > map.rm.size) {
+ /* Map (part of) 2nd RAM chunk */
+ virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
+ len = r->len;
+ if (r->offset >= map.rm.size)
+ virt_addr += r->offset - map.rm.size;
+ else
+ len -= map.rm.size - r->offset;
+ result = dma_sb_map_area(r, virt_addr, len, &tmp,
+ IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+ BUG_ON(result);
+ }
return result;
}
/**
- * dma_region_free_linear - Free a linear dma mapping for a device.
+ * dma_sb_region_free_linear - Free a linear dma mapping for a device.
* @r: Pointer to a struct ps3_dma_region.
*
* This routine will unmap all mapped areas and free the HV dma region.
*/
-static int dma_region_free_linear(struct ps3_dma_region *r)
+static int dma_sb_region_free_linear(struct ps3_dma_region *r)
{
int result;
+ unsigned long bus_addr, len, lpar_addr;
+
+ if (r->offset < map.rm.size) {
+ /* Unmap (part of) 1st RAM chunk */
+ lpar_addr = map.rm.base + r->offset;
+ len = map.rm.size - r->offset;
+ if (len > r->len)
+ len = r->len;
+ bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+ result = dma_sb_unmap_area(r, bus_addr, len);
+ BUG_ON(result);
+ }
- result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size);
- BUG_ON(result);
-
- result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base),
- map.r1.size);
- BUG_ON(result);
+ if (r->offset + r->len > map.rm.size) {
+ /* Unmap (part of) 2nd RAM chunk */
+ lpar_addr = map.r1.base;
+ len = r->len;
+ if (r->offset >= map.rm.size)
+ lpar_addr += r->offset - map.rm.size;
+ else
+ len -= map.rm.size - r->offset;
+ bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+ result = dma_sb_unmap_area(r, bus_addr, len);
+ BUG_ON(result);
+ }
- result = dma_region_free(r);
+ result = dma_sb_region_free(r);
BUG_ON(result);
return result;
}
/**
- * dma_map_area_linear - Map an area of memory into a device dma region.
+ * dma_sb_map_area_linear - Map an area of memory into a device dma region.
* @r: Pointer to a struct ps3_dma_region.
* @virt_addr: Starting virtual address of the area to map.
* @len: Length in bytes of the area to map.
* @bus_addr: A pointer to return the starting ioc bus address of the area to
* map.
*
- * This routine just returns the coresponding bus address. Actual mapping
+ * This routine just returns the corresponding bus address. Actual mapping
* occurs in dma_region_create_linear().
*/
-static int dma_map_area_linear(struct ps3_dma_region *r,
- unsigned long virt_addr, unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area_linear(struct ps3_dma_region *r,
+ unsigned long virt_addr, unsigned long len, unsigned long *bus_addr,
+ u64 iopte_flag)
{
unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
: virt_addr;
- *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+ *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
return 0;
}
@@ -744,42 +1091,98 @@ static int dma_map_area_linear(struct ps3_dma_region *r,
* @bus_addr: The starting ioc bus address of the area to unmap.
* @len: Length in bytes of the area to unmap.
*
- * This routine does nothing. Unmapping occurs in dma_region_free_linear().
+ * This routine does nothing. Unmapping occurs in dma_sb_region_free_linear().
*/
-static int dma_unmap_area_linear(struct ps3_dma_region *r,
+static int dma_sb_unmap_area_linear(struct ps3_dma_region *r,
unsigned long bus_addr, unsigned long len)
{
return 0;
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_ops = {
+ .create = dma_sb_region_create,
+ .free = dma_sb_region_free,
+ .map = dma_sb_map_area,
+ .unmap = dma_sb_unmap_area
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = {
+ .create = dma_sb_region_create_linear,
+ .free = dma_sb_region_free_linear,
+ .map = dma_sb_map_area_linear,
+ .unmap = dma_sb_unmap_area_linear
+};
+
+static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = {
+ .create = dma_ioc0_region_create,
+ .free = dma_ioc0_region_free,
+ .map = dma_ioc0_map_area,
+ .unmap = dma_ioc0_unmap_area
+};
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+ struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+ enum ps3_dma_region_type region_type, void *addr, unsigned long len)
+{
+ unsigned long lpar_addr;
+
+ lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
+
+ r->dev = dev;
+ r->page_size = page_size;
+ r->region_type = region_type;
+ r->offset = lpar_addr;
+ if (r->offset >= map.rm.size)
+ r->offset -= map.r1.offset;
+ r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size);
+
+ switch (dev->dev_type) {
+ case PS3_DEVICE_TYPE_SB:
+ r->region_ops = (USE_DYNAMIC_DMA)
+ ? &ps3_dma_sb_region_ops
+ : &ps3_dma_sb_region_linear_ops;
+ break;
+ case PS3_DEVICE_TYPE_IOC0:
+ r->region_ops = &ps3_dma_ioc0_region_ops;
+ break;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+ return 0;
}
+EXPORT_SYMBOL(ps3_dma_region_init);
int ps3_dma_region_create(struct ps3_dma_region *r)
{
- return (USE_DYNAMIC_DMA)
- ? dma_region_create(r)
- : dma_region_create_linear(r);
+ BUG_ON(!r);
+ BUG_ON(!r->region_ops);
+ BUG_ON(!r->region_ops->create);
+ return r->region_ops->create(r);
}
+EXPORT_SYMBOL(ps3_dma_region_create);
int ps3_dma_region_free(struct ps3_dma_region *r)
{
- return (USE_DYNAMIC_DMA)
- ? dma_region_free(r)
- : dma_region_free_linear(r);
+ BUG_ON(!r);
+ BUG_ON(!r->region_ops);
+ BUG_ON(!r->region_ops->free);
+ return r->region_ops->free(r);
}
+EXPORT_SYMBOL(ps3_dma_region_free);
int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr)
+ unsigned long len, unsigned long *bus_addr,
+ u64 iopte_flag)
{
- return (USE_DYNAMIC_DMA)
- ? dma_map_area(r, virt_addr, len, bus_addr)
- : dma_map_area_linear(r, virt_addr, len, bus_addr);
+ return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag);
}
int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
unsigned long len)
{
- return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len)
- : dma_unmap_area_linear(r, bus_addr, len);
+ return r->region_ops->unmap(r, bus_addr, len);
}
/*============================================================================*/
@@ -810,12 +1213,13 @@ void __init ps3_mm_init(void)
BUG_ON(map.rm.base);
BUG_ON(!map.rm.size);
- lmb_add(map.rm.base, map.rm.size);
- lmb_analyze();
/* arrange to do this in ps3_mm_add_memory */
ps3_mm_region_create(&map.r1, map.total - map.rm.size);
+ /* correct map.total for the real total amount of memory we use */
+ map.total = map.rm.size + map.r1.size;
+
DBG(" <- %s:%d\n", __func__, __LINE__);
}
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 5c3da08bc0c4..b70e474014f0 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -133,7 +133,7 @@ struct saved_params {
} static saved_params;
#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
-static void _dump_header(const struct os_area_header __iomem *h, const char* func,
+static void _dump_header(const struct os_area_header *h, const char *func,
int line)
{
pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
@@ -151,7 +151,7 @@ static void _dump_header(const struct os_area_header __iomem *h, const char* fun
}
#define dump_params(_a) _dump_params(_a, __func__, __LINE__)
-static void _dump_params(const struct os_area_params __iomem *p, const char* func,
+static void _dump_params(const struct os_area_params *p, const char *func,
int line)
{
pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag);
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index ca04f03305c7..87d52060fec0 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -41,6 +41,7 @@ void ps3_mm_shutdown(void);
/* irq */
void ps3_init_IRQ(void);
+void ps3_shutdown_IRQ(int cpu);
void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
/* smp */
@@ -82,6 +83,7 @@ enum ps3_dev_type {
PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */
PS3_DEV_TYPE_SB_GPIO = 6,
PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */
+ PS3_DEV_TYPE_NOACCESS = 255,
};
int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -129,24 +131,28 @@ int ps3_repository_read_dev_reg(unsigned int bus_index,
/* repository bus enumerators */
struct ps3_repository_device {
+ enum ps3_bus_type bus_type;
unsigned int bus_index;
+ unsigned int bus_id;
+ enum ps3_dev_type dev_type;
unsigned int dev_index;
- struct ps3_device_id did;
+ unsigned int dev_id;
};
-int ps3_repository_find_device(enum ps3_bus_type bus_type,
- enum ps3_dev_type dev_type,
- const struct ps3_repository_device *start_dev,
- struct ps3_repository_device *dev);
-static inline int ps3_repository_find_first_device(
- enum ps3_bus_type bus_type, enum ps3_dev_type dev_type,
- struct ps3_repository_device *dev)
+static inline struct ps3_repository_device *ps3_repository_bump_device(
+ struct ps3_repository_device *repo)
{
- return ps3_repository_find_device(bus_type, dev_type, NULL, dev);
+ repo->dev_index++;
+ return repo;
}
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_device(struct ps3_repository_device *repo);
+int ps3_repository_find_devices(enum ps3_bus_type bus_type,
+ int (*callback)(const struct ps3_repository_device *repo));
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+ unsigned int *bus_index);
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
enum ps3_interrupt_type intr_type, unsigned int *interrupt_id);
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len);
/* repository block device info */
@@ -216,4 +222,19 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id);
int ps3_repository_read_spu_resource_id(unsigned int res_index,
enum ps3_spu_resource_type* resource_type, unsigned int *resource_id);
+/* repository vuart info */
+
+int ps3_repository_read_vuart_av_port(unsigned int *port);
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port);
+
+/* Page table entries */
+#define IOPTE_PP_W 0x8000000000000000ul /* protection: write */
+#define IOPTE_PP_R 0x4000000000000000ul /* protection: read */
+#define IOPTE_M 0x2000000000000000ul /* coherency required */
+#define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */
+#define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */
+#define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */
+#define IOPTE_H 0x0000000000000800ul /* cache hint */
+#define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */
+
#endif
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index ae586a0e5d3f..8cc37cfea0f2 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -138,7 +138,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
__func__, __LINE__, ps3_result(result));
dump_node_name(lpar_id, n1, n2, n3, n4);
- return result;
+ return -ENOENT;
}
dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
@@ -155,7 +155,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
__func__, __LINE__, v2);
- return result;
+ return 0;
}
int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -314,324 +314,140 @@ int ps3_repository_read_dev_reg(unsigned int bus_index,
reg_index, bus_addr, len);
}
-#if defined(DEBUG)
-int ps3_repository_dump_resource_info(unsigned int bus_index,
- unsigned int dev_index)
-{
- int result = 0;
- unsigned int res_index;
- pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
- bus_index, dev_index);
- for (res_index = 0; res_index < 10; res_index++) {
- enum ps3_interrupt_type intr_type;
- unsigned int interrupt_id;
+int ps3_repository_find_device(struct ps3_repository_device *repo)
+{
+ int result;
+ struct ps3_repository_device tmp = *repo;
+ unsigned int num_dev;
- result = ps3_repository_read_dev_intr(bus_index, dev_index,
- res_index, &intr_type, &interrupt_id);
+ BUG_ON(repo->bus_index > 10);
+ BUG_ON(repo->dev_index > 10);
- if (result) {
- if (result != LV1_NO_ENTRY)
- pr_debug("%s:%d ps3_repository_read_dev_intr"
- " (%u:%u) failed\n", __func__, __LINE__,
- bus_index, dev_index);
- break;
- }
+ result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
- pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
- __func__, __LINE__, bus_index, dev_index, intr_type,
- interrupt_id);
+ if (result) {
+ pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
+ return result;
}
- for (res_index = 0; res_index < 10; res_index++) {
- enum ps3_reg_type reg_type;
- u64 bus_addr;
- u64 len;
-
- result = ps3_repository_read_dev_reg(bus_index, dev_index,
- res_index, &reg_type, &bus_addr, &len);
+ pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",
+ __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
+ num_dev);
- if (result) {
- if (result != LV1_NO_ENTRY)
- pr_debug("%s:%d ps3_repository_read_dev_reg"
- " (%u:%u) failed\n", __func__, __LINE__,
- bus_index, dev_index);
- break;
- }
-
- pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
- __func__, __LINE__, bus_index, dev_index, reg_type,
- bus_addr, len);
+ if (tmp.dev_index >= num_dev) {
+ pr_debug("%s:%d: no device found\n", __func__, __LINE__);
+ return -ENODEV;
}
- pr_debug(" <- %s:%d\n", __func__, __LINE__);
- return result;
-}
-
-static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
-{
- int result = 0;
- unsigned int num_regions, region_index;
- u64 port, blk_size, num_blocks;
-
- pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
- bus_index, dev_index);
+ result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
+ &tmp.dev_type);
- result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
- &blk_size, &num_blocks, &num_regions);
if (result) {
- pr_debug("%s:%d ps3_repository_read_stor_dev_info"
- " (%u:%u) failed\n", __func__, __LINE__,
- bus_index, dev_index);
- goto out;
+ pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);
+ return result;
}
- pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks "
- "%lu, num_regions %u\n",
- __func__, __LINE__, bus_index, dev_index, port,
- blk_size, num_blocks, num_regions);
-
- for (region_index = 0; region_index < num_regions; region_index++) {
- unsigned int region_id;
- u64 region_start, region_size;
-
- result = ps3_repository_read_stor_dev_region(bus_index,
- dev_index, region_index, &region_id, &region_start,
- &region_size);
- if (result) {
- pr_debug("%s:%d ps3_repository_read_stor_dev_region"
- " (%u:%u) failed\n", __func__, __LINE__,
- bus_index, dev_index);
- break;
- }
+ result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
+ &tmp.dev_id);
- pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
- __func__, __LINE__, bus_index, dev_index, region_id,
- region_start, region_size);
+ if (result) {
+ pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
+ __LINE__);
+ return result;
}
-out:
- pr_debug(" <- %s:%d\n", __func__, __LINE__);
- return result;
-}
-
-static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
- unsigned int num_dev)
-{
- int result = 0;
- unsigned int dev_index;
-
- pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
-
- for (dev_index = 0; dev_index < num_dev; dev_index++) {
- enum ps3_dev_type dev_type;
- unsigned int dev_id;
-
- result = ps3_repository_read_dev_type(bus_index, dev_index,
- &dev_type);
-
- if (result) {
- pr_debug("%s:%d ps3_repository_read_dev_type"
- " (%u:%u) failed\n", __func__, __LINE__,
- bus_index, dev_index);
- break;
- }
-
- result = ps3_repository_read_dev_id(bus_index, dev_index,
- &dev_id);
-
- if (result) {
- pr_debug("%s:%d ps3_repository_read_dev_id"
- " (%u:%u) failed\n", __func__, __LINE__,
- bus_index, dev_index);
- continue;
- }
+ pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",
+ __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
- pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__,
- __LINE__, bus_index, dev_index, dev_type, dev_id);
-
- ps3_repository_dump_resource_info(bus_index, dev_index);
-
- if (bus_type == PS3_BUS_TYPE_STORAGE)
- dump_stor_dev_info(bus_index, dev_index);
- }
-
- pr_debug(" <- %s:%d\n", __func__, __LINE__);
- return result;
+ *repo = tmp;
+ return 0;
}
-int ps3_repository_dump_bus_info(void)
+int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
+ int (*callback)(const struct ps3_repository_device *repo))
{
int result = 0;
- unsigned int bus_index;
+ struct ps3_repository_device repo;
- pr_debug(" -> %s:%d\n", __func__, __LINE__);
+ pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
- for (bus_index = 0; bus_index < 10; bus_index++) {
- enum ps3_bus_type bus_type;
- unsigned int bus_id;
- unsigned int num_dev;
+ for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
- result = ps3_repository_read_bus_type(bus_index, &bus_type);
+ result = ps3_repository_read_bus_type(repo.bus_index,
+ &repo.bus_type);
if (result) {
pr_debug("%s:%d read_bus_type(%u) failed\n",
- __func__, __LINE__, bus_index);
+ __func__, __LINE__, repo.bus_index);
break;
}
- result = ps3_repository_read_bus_id(bus_index, &bus_id);
-
- if (result) {
- pr_debug("%s:%d read_bus_id(%u) failed\n",
- __func__, __LINE__, bus_index);
+ if (repo.bus_type != bus_type) {
+ pr_debug("%s:%d: skip, bus_type %u\n", __func__,
+ __LINE__, repo.bus_type);
continue;
}
- if (bus_index != bus_id)
- pr_debug("%s:%d bus_index != bus_id\n",
- __func__, __LINE__);
-
- result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
+ result = ps3_repository_read_bus_id(repo.bus_index,
+ &repo.bus_id);
if (result) {
- pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
- __func__, __LINE__, bus_index);
+ pr_debug("%s:%d read_bus_id(%u) failed\n",
+ __func__, __LINE__, repo.bus_index);
continue;
}
- pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
- __func__, __LINE__, bus_index, bus_type, bus_id,
- num_dev);
+ for (repo.dev_index = 0; ; repo.dev_index++) {
+ result = ps3_repository_find_device(&repo);
- dump_device_info(bus_index, bus_type, num_dev);
- }
+ if (result == -ENODEV) {
+ result = 0;
+ break;
+ } else if (result)
+ break;
- pr_debug(" <- %s:%d\n", __func__, __LINE__);
- return result;
-}
-#endif /* defined(DEBUG) */
-
-static int find_device(unsigned int bus_index, unsigned int num_dev,
- unsigned int start_dev_index, enum ps3_dev_type dev_type,
- struct ps3_repository_device *dev)
-{
- int result = 0;
- unsigned int dev_index;
+ result = callback(&repo);
- pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
-
- dev->dev_index = UINT_MAX;
-
- for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
- enum ps3_dev_type x;
-
- result = ps3_repository_read_dev_type(bus_index, dev_index,
- &x);
-
- if (result) {
- pr_debug("%s:%d read_dev_type failed\n",
- __func__, __LINE__);
- return result;
+ if (result) {
+ pr_debug("%s:%d: abort at callback\n", __func__,
+ __LINE__);
+ break;
+ }
}
-
- if (x == dev_type)
- break;
- }
-
- if (dev_index == num_dev)
- return -1;
-
- pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
- __func__, __LINE__, dev_type, dev_index);
-
- result = ps3_repository_read_dev_id(bus_index, dev_index,
- &dev->did.dev_id);
-
- if (result) {
- pr_debug("%s:%d read_dev_id failed\n",
- __func__, __LINE__);
- return result;
+ break;
}
- dev->dev_index = dev_index;
-
- pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
- dev->did.dev_id);
-
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result;
}
-int ps3_repository_find_device (enum ps3_bus_type bus_type,
- enum ps3_dev_type dev_type,
- const struct ps3_repository_device *start_dev,
- struct ps3_repository_device *dev)
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+ unsigned int *bus_index)
{
- int result = 0;
- unsigned int bus_index;
- unsigned int num_dev;
-
- pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
- bus_type, dev_type);
-
- BUG_ON(start_dev && start_dev->bus_index > 10);
-
- for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
- bus_index++) {
- enum ps3_bus_type x;
-
- result = ps3_repository_read_bus_type(bus_index, &x);
+ unsigned int i;
+ enum ps3_bus_type type;
+ int error;
- if (result) {
+ for (i = from; i < 10; i++) {
+ error = ps3_repository_read_bus_type(i, &type);
+ if (error) {
pr_debug("%s:%d read_bus_type failed\n",
__func__, __LINE__);
- dev->bus_index = UINT_MAX;
- return result;
+ *bus_index = UINT_MAX;
+ return error;
+ }
+ if (type == bus_type) {
+ *bus_index = i;
+ return 0;
}
- if (x == bus_type)
- break;
- }
-
- if (bus_index >= 10)
- return -ENODEV;
-
- pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
- __func__, __LINE__, bus_type, bus_index);
-
- result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
-
- if (result) {
- pr_debug("%s:%d read_bus_num_dev failed\n",
- __func__, __LINE__);
- return result;
- }
-
- result = find_device(bus_index, num_dev, start_dev
- ? start_dev->dev_index + 1 : 0, dev_type, dev);
-
- if (result) {
- pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
- return result;
- }
-
- result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
-
- if (result) {
- pr_debug("%s:%d read_bus_id failed\n",
- __func__, __LINE__);
- return result;
}
-
- dev->bus_index = bus_index;
-
- pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
- __func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
-
- return result;
+ *bus_index = UINT_MAX;
+ return -ENODEV;
}
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
{
int result = 0;
@@ -645,8 +461,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
enum ps3_interrupt_type t;
unsigned int id;
- result = ps3_repository_read_dev_intr(dev->bus_index,
- dev->dev_index, res_index, &t, &id);
+ result = ps3_repository_read_dev_intr(repo->bus_index,
+ repo->dev_index, res_index, &t, &id);
if (result) {
pr_debug("%s:%d read_dev_intr failed\n",
@@ -669,7 +485,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
return result;
}
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
{
int result = 0;
@@ -684,8 +500,8 @@ int ps3_repository_find_reg(const struct ps3_repository_device *dev,
u64 a;
u64 l;
- result = ps3_repository_read_dev_reg(dev->bus_index,
- dev->dev_index, res_index, &t, &a, &l);
+ result = ps3_repository_read_dev_reg(repo->bus_index,
+ repo->dev_index, res_index, &t, &a, &l);
if (result) {
pr_debug("%s:%d read_dev_reg failed\n",
@@ -965,6 +781,36 @@ int ps3_repository_read_boot_dat_size(unsigned int *size)
return result;
}
+int ps3_repository_read_vuart_av_port(unsigned int *port)
+{
+ int result;
+ u64 v1;
+
+ result = read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("bi", 0),
+ make_field("vir_uart", 0),
+ make_field("port", 0),
+ make_field("avset", 0),
+ &v1, 0);
+ *port = v1;
+ return result;
+}
+
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
+{
+ int result;
+ u64 v1;
+
+ result = read_node(PS3_LPAR_ID_CURRENT,
+ make_first_field("bi", 0),
+ make_field("vir_uart", 0),
+ make_field("port", 0),
+ make_field("sysmgr", 0),
+ &v1, 0);
+ *port = v1;
+ return result;
+}
+
/**
* ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
* address: lpar address of cell_ext_os_area
@@ -1026,3 +872,205 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
return result ? result
: ps3_repository_read_tb_freq(node_id, tb_freq);
}
+
+#if defined(DEBUG)
+
+int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
+{
+ int result = 0;
+ unsigned int res_index;
+
+ pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+
+ for (res_index = 0; res_index < 10; res_index++) {
+ enum ps3_interrupt_type intr_type;
+ unsigned int interrupt_id;
+
+ result = ps3_repository_read_dev_intr(repo->bus_index,
+ repo->dev_index, res_index, &intr_type, &interrupt_id);
+
+ if (result) {
+ if (result != LV1_NO_ENTRY)
+ pr_debug("%s:%d ps3_repository_read_dev_intr"
+ " (%u:%u) failed\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+ break;
+ }
+
+ pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
+ __func__, __LINE__, repo->bus_index, repo->dev_index,
+ intr_type, interrupt_id);
+ }
+
+ for (res_index = 0; res_index < 10; res_index++) {
+ enum ps3_reg_type reg_type;
+ u64 bus_addr;
+ u64 len;
+
+ result = ps3_repository_read_dev_reg(repo->bus_index,
+ repo->dev_index, res_index, &reg_type, &bus_addr, &len);
+
+ if (result) {
+ if (result != LV1_NO_ENTRY)
+ pr_debug("%s:%d ps3_repository_read_dev_reg"
+ " (%u:%u) failed\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+ break;
+ }
+
+ pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
+ __func__, __LINE__, repo->bus_index, repo->dev_index,
+ reg_type, bus_addr, len);
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+static int dump_stor_dev_info(struct ps3_repository_device *repo)
+{
+ int result = 0;
+ unsigned int num_regions, region_index;
+ u64 port, blk_size, num_blocks;
+
+ pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+
+ result = ps3_repository_read_stor_dev_info(repo->bus_index,
+ repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
+ if (result) {
+ pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+ " (%u:%u) failed\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+ goto out;
+ }
+
+ pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks "
+ "%lu, num_regions %u\n",
+ __func__, __LINE__, repo->bus_index, repo->dev_index, port,
+ blk_size, num_blocks, num_regions);
+
+ for (region_index = 0; region_index < num_regions; region_index++) {
+ unsigned int region_id;
+ u64 region_start, region_size;
+
+ result = ps3_repository_read_stor_dev_region(repo->bus_index,
+ repo->dev_index, region_index, &region_id,
+ &region_start, &region_size);
+ if (result) {
+ pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+ " (%u:%u) failed\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+ break;
+ }
+
+ pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+ __func__, __LINE__, repo->bus_index, repo->dev_index,
+ region_id, region_start, region_size);
+ }
+
+out:
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+static int dump_device_info(struct ps3_repository_device *repo,
+ unsigned int num_dev)
+{
+ int result = 0;
+
+ pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
+
+ for (repo->dev_index = 0; repo->dev_index < num_dev;
+ repo->dev_index++) {
+
+ result = ps3_repository_read_dev_type(repo->bus_index,
+ repo->dev_index, &repo->dev_type);
+
+ if (result) {
+ pr_debug("%s:%d ps3_repository_read_dev_type"
+ " (%u:%u) failed\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+ break;
+ }
+
+ result = ps3_repository_read_dev_id(repo->bus_index,
+ repo->dev_index, &repo->dev_id);
+
+ if (result) {
+ pr_debug("%s:%d ps3_repository_read_dev_id"
+ " (%u:%u) failed\n", __func__, __LINE__,
+ repo->bus_index, repo->dev_index);
+ continue;
+ }
+
+ pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__,
+ __LINE__, repo->bus_index, repo->dev_index,
+ repo->dev_type, repo->dev_id);
+
+ ps3_repository_dump_resource_info(repo);
+
+ if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
+ dump_stor_dev_info(repo);
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+int ps3_repository_dump_bus_info(void)
+{
+ int result = 0;
+ struct ps3_repository_device repo;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ memset(&repo, 0, sizeof(repo));
+
+ for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
+ unsigned int num_dev;
+
+ result = ps3_repository_read_bus_type(repo.bus_index,
+ &repo.bus_type);
+
+ if (result) {
+ pr_debug("%s:%d read_bus_type(%u) failed\n",
+ __func__, __LINE__, repo.bus_index);
+ break;
+ }
+
+ result = ps3_repository_read_bus_id(repo.bus_index,
+ &repo.bus_id);
+
+ if (result) {
+ pr_debug("%s:%d read_bus_id(%u) failed\n",
+ __func__, __LINE__, repo.bus_index);
+ continue;
+ }
+
+ if (repo.bus_index != repo.bus_id)
+ pr_debug("%s:%d bus_index != bus_id\n",
+ __func__, __LINE__);
+
+ result = ps3_repository_read_bus_num_dev(repo.bus_index,
+ &num_dev);
+
+ if (result) {
+ pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
+ __func__, __LINE__, repo.bus_index);
+ continue;
+ }
+
+ pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
+ __func__, __LINE__, repo.bus_index, repo.bus_type,
+ repo.bus_id, num_dev);
+
+ dump_device_info(&repo, num_dev);
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return result;
+}
+
+#endif /* defined(DEBUG) */
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 935396766621..aa05288de64e 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -37,27 +37,35 @@
#include "platform.h"
#if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
#else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
#endif
#if !defined(CONFIG_SMP)
static void smp_send_stop(void) {}
#endif
-int ps3_get_firmware_version(union ps3_firmware_version *v)
+static union ps3_firmware_version ps3_firmware_version;
+
+void ps3_get_firmware_version(union ps3_firmware_version *v)
{
- int result = lv1_get_version_info(&v->raw);
+ *v = ps3_firmware_version;
+}
+EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
- if (result) {
- v->raw = 0;
- return -1;
- }
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev)
+{
+ union ps3_firmware_version x;
+
+ x.pad = 0;
+ x.major = major;
+ x.minor = minor;
+ x.rev = rev;
- return result;
+ return (ps3_firmware_version.raw - x.raw);
}
-EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
+EXPORT_SYMBOL_GPL(ps3_compare_firmware_version);
static void ps3_power_save(void)
{
@@ -99,7 +107,8 @@ static void ps3_panic(char *str)
while(1);
}
-#ifdef CONFIG_FB_PS3
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
+ defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
static void prealloc(struct ps3_prealloc *p)
{
if (!p->size)
@@ -115,12 +124,15 @@ static void prealloc(struct ps3_prealloc *p)
printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
p->address);
}
+#endif
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE)
struct ps3_prealloc ps3fb_videomemory = {
- .name = "ps3fb videomemory",
- .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
- .align = 1024*1024 /* the GPU requires 1 MiB alignment */
+ .name = "ps3fb videomemory",
+ .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+ .align = 1024*1024 /* the GPU requires 1 MiB alignment */
};
+EXPORT_SYMBOL_GPL(ps3fb_videomemory);
#define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory)
static int __init early_parse_ps3fb(char *p)
@@ -137,6 +149,30 @@ early_param("ps3fb", early_parse_ps3fb);
#define prealloc_ps3fb_videomemory() do { } while (0)
#endif
+#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
+struct ps3_prealloc ps3flash_bounce_buffer = {
+ .name = "ps3flash bounce buffer",
+ .size = 256*1024,
+ .align = 256*1024
+};
+EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer);
+#define prealloc_ps3flash_bounce_buffer() prealloc(&ps3flash_bounce_buffer)
+
+static int __init early_parse_ps3flash(char *p)
+{
+ if (!p)
+ return 1;
+
+ if (!strcmp(p, "off"))
+ ps3flash_bounce_buffer.size = 0;
+
+ return 0;
+}
+early_param("ps3flash", early_parse_ps3flash);
+#else
+#define prealloc_ps3flash_bounce_buffer() do { } while (0)
+#endif
+
static int ps3_set_dabr(u64 dabr)
{
enum {DABR_USER = 1, DABR_KERNEL = 2,};
@@ -146,13 +182,13 @@ static int ps3_set_dabr(u64 dabr)
static void __init ps3_setup_arch(void)
{
- union ps3_firmware_version v;
DBG(" -> %s:%d\n", __func__, __LINE__);
- ps3_get_firmware_version(&v);
- printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor,
- v.rev);
+ lv1_get_version_info(&ps3_firmware_version.raw);
+ printk(KERN_INFO "PS3 firmware version %u.%u.%u\n",
+ ps3_firmware_version.major, ps3_firmware_version.minor,
+ ps3_firmware_version.rev);
ps3_spu_set_platform();
ps3_map_htab();
@@ -166,6 +202,8 @@ static void __init ps3_setup_arch(void)
#endif
prealloc_ps3fb_videomemory();
+ prealloc_ps3flash_bounce_buffer();
+
ppc_md.power_save = ps3_power_save;
DBG(" <- %s:%d\n", __func__, __LINE__);
@@ -184,7 +222,7 @@ static int __init ps3_probe(void)
DBG(" -> %s:%d\n", __func__, __LINE__);
dt_root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(dt_root, "PS3"))
+ if (!of_flat_dt_is_compatible(dt_root, "sony,ps3"))
return 0;
powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
@@ -201,31 +239,12 @@ static int __init ps3_probe(void)
#if defined(CONFIG_KEXEC)
static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
{
- DBG(" -> %s:%d\n", __func__, __LINE__);
-
- if (secondary) {
- int cpu;
- for_each_online_cpu(cpu)
- if (cpu)
- ps3_smp_cleanup_cpu(cpu);
- } else
- ps3_smp_cleanup_cpu(0);
-
- DBG(" <- %s:%d\n", __func__, __LINE__);
-}
-
-static void ps3_machine_kexec(struct kimage *image)
-{
- unsigned long ppe_id;
-
- DBG(" -> %s:%d\n", __func__, __LINE__);
+ int cpu = smp_processor_id();
- lv1_get_logical_ppe_id(&ppe_id);
- lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
- ps3_mm_shutdown();
- ps3_mm_vas_destroy();
+ DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
- default_machine_kexec(image);
+ ps3_smp_cleanup_cpu(cpu);
+ ps3_shutdown_IRQ(cpu);
DBG(" <- %s:%d\n", __func__, __LINE__);
}
@@ -247,7 +266,7 @@ define_machine(ps3) {
.power_off = ps3_power_off,
#if defined(CONFIG_KEXEC)
.kexec_cpu_down = ps3_kexec_cpu_down,
- .machine_kexec = ps3_machine_kexec,
+ .machine_kexec = default_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
.machine_crash_shutdown = default_machine_crash_shutdown,
#endif
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c
index 53416ec5198b..f0b12f212363 100644
--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -27,9 +27,9 @@
#include "platform.h"
#if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
#else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
#endif
static irqreturn_t ipi_function_handler(int irq, void *msg)
@@ -39,11 +39,11 @@ static irqreturn_t ipi_function_handler(int irq, void *msg)
}
/**
- * virqs - a per cpu array of virqs for ipi use
+ * ps3_ipi_virqs - a per cpu array of virqs for ipi use
*/
#define MSG_COUNT 4
-static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
+static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
static const char *names[MSG_COUNT] = {
"ipi call",
@@ -62,7 +62,7 @@ static void do_message_pass(int target, int msg)
return;
}
- virq = per_cpu(virqs, target)[msg];
+ virq = per_cpu(ps3_ipi_virqs, target)[msg];
result = ps3_send_event_locally(virq);
if (result)
@@ -94,13 +94,13 @@ static int ps3_smp_probe(void)
static void __init ps3_smp_setup_cpu(int cpu)
{
int result;
- unsigned int *virqs = per_cpu(virqs, cpu);
+ unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
/*
- * Check assumptions on virqs[] indexing. If this
+ * Check assumptions on ps3_ipi_virqs[] indexing. If this
* check fails, then a different mapping of PPC_MSG_
* to index needs to be setup.
*/
@@ -132,13 +132,13 @@ static void __init ps3_smp_setup_cpu(int cpu)
void ps3_smp_cleanup_cpu(int cpu)
{
- unsigned int *virqs = per_cpu(virqs, cpu);
+ unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
for (i = 0; i < MSG_COUNT; i++) {
- free_irq(virqs[i], (void*)(long)i);
+ /* Can't call free_irq from interrupt context. */
ps3_event_receive_port_destroy(virqs[i]);
virqs[i] = NO_IRQ;
}
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index 651437cb2c18..502d80ed982b 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -182,15 +182,18 @@ static int __init setup_areas(struct spu *spu)
{
struct table {char* name; unsigned long addr; unsigned long size;};
- spu_pdata(spu)->shadow = __ioremap(
- spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
- pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED);
+ spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr,
+ sizeof(struct spe_shadow),
+ pgprot_val(PAGE_READONLY) |
+ _PAGE_NO_CACHE);
if (!spu_pdata(spu)->shadow) {
pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
goto fail_ioremap;
}
- spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
+ spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys,
+ LS_SIZE, _PAGE_NO_CACHE);
+
if (!spu->local_store) {
pr_debug("%s:%d: ioremap local_store failed\n",
__func__, __LINE__);
@@ -199,6 +202,7 @@ static int __init setup_areas(struct spu *spu)
spu->problem = ioremap(spu->problem_phys,
sizeof(struct spu_problem));
+
if (!spu->problem) {
pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
goto fail_ioremap;
@@ -206,6 +210,7 @@ static int __init setup_areas(struct spu *spu)
spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
sizeof(struct spu_priv2));
+
if (!spu->priv2) {
pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
goto fail_ioremap;
@@ -400,11 +405,13 @@ static int __init ps3_enumerate_spus(int (*fn)(void *data))
}
}
- if (result)
+ if (result) {
printk(KERN_WARNING "%s:%d: Error initializing spus\n",
__func__, __LINE__);
+ return result;
+ }
- return result;
+ return num_resource_id;
}
const struct spu_management_ops spu_management_ps3_ops = {
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 6bda51027cc6..4bb634a17e43 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -30,22 +30,228 @@
#include "platform.h"
+static struct device ps3_system_bus = {
+ .bus_id = "ps3_system",
+};
+
+/* FIXME: need device usage counters! */
+struct {
+ struct mutex mutex;
+ int sb_11; /* usb 0 */
+ int sb_12; /* usb 0 */
+ int gpu;
+} static usage_hack;
+
+static int ps3_is_device(struct ps3_system_bus_device *dev,
+ unsigned int bus_id, unsigned int dev_id)
+{
+ return dev->bus_id == bus_id && dev->dev_id == dev_id;
+}
+
+static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+ int result;
+
+ BUG_ON(!dev->bus_id);
+ mutex_lock(&usage_hack.mutex);
+
+ if (ps3_is_device(dev, 1, 1)) {
+ usage_hack.sb_11++;
+ if (usage_hack.sb_11 > 1) {
+ result = 0;
+ goto done;
+ }
+ }
+
+ if (ps3_is_device(dev, 1, 2)) {
+ usage_hack.sb_12++;
+ if (usage_hack.sb_12 > 1) {
+ result = 0;
+ goto done;
+ }
+ }
+
+ result = lv1_open_device(dev->bus_id, dev->dev_id, 0);
+
+ if (result) {
+ pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__,
+ __LINE__, ps3_result(result));
+ result = -EPERM;
+ }
+
+done:
+ mutex_unlock(&usage_hack.mutex);
+ return result;
+}
+
+static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+ int result;
+
+ BUG_ON(!dev->bus_id);
+ mutex_lock(&usage_hack.mutex);
+
+ if (ps3_is_device(dev, 1, 1)) {
+ usage_hack.sb_11--;
+ if (usage_hack.sb_11) {
+ result = 0;
+ goto done;
+ }
+ }
+
+ if (ps3_is_device(dev, 1, 2)) {
+ usage_hack.sb_12--;
+ if (usage_hack.sb_12) {
+ result = 0;
+ goto done;
+ }
+ }
+
+ result = lv1_close_device(dev->bus_id, dev->dev_id);
+ BUG_ON(result);
+
+done:
+ mutex_unlock(&usage_hack.mutex);
+ return result;
+}
+
+static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+ int result;
+
+ mutex_lock(&usage_hack.mutex);
+
+ usage_hack.gpu++;
+ if (usage_hack.gpu > 1) {
+ result = 0;
+ goto done;
+ }
+
+ result = lv1_gpu_open(0);
+
+ if (result) {
+ pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__,
+ __LINE__, ps3_result(result));
+ result = -EPERM;
+ }
+
+done:
+ mutex_unlock(&usage_hack.mutex);
+ return result;
+}
+
+static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+ int result;
+
+ mutex_lock(&usage_hack.mutex);
+
+ usage_hack.gpu--;
+ if (usage_hack.gpu) {
+ result = 0;
+ goto done;
+ }
+
+ result = lv1_gpu_close();
+ BUG_ON(result);
+
+done:
+ mutex_unlock(&usage_hack.mutex);
+ return result;
+}
+
+int ps3_open_hv_device(struct ps3_system_bus_device *dev)
+{
+ BUG_ON(!dev);
+ pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+ switch (dev->match_id) {
+ case PS3_MATCH_ID_EHCI:
+ case PS3_MATCH_ID_OHCI:
+ case PS3_MATCH_ID_GELIC:
+ case PS3_MATCH_ID_STOR_DISK:
+ case PS3_MATCH_ID_STOR_ROM:
+ case PS3_MATCH_ID_STOR_FLASH:
+ return ps3_open_hv_device_sb(dev);
+
+ case PS3_MATCH_ID_SOUND:
+ case PS3_MATCH_ID_GRAPHICS:
+ return ps3_open_hv_device_gpu(dev);
+
+ case PS3_MATCH_ID_AV_SETTINGS:
+ case PS3_MATCH_ID_SYSTEM_MANAGER:
+ pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+ __LINE__, dev->match_id);
+ pr_debug("%s:%d: bus_id: %u\n", __func__,
+ __LINE__, dev->bus_id);
+ BUG();
+ return -EINVAL;
+
+ default:
+ break;
+ }
+
+ pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+ dev->match_id);
+ BUG();
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_open_hv_device);
+
+int ps3_close_hv_device(struct ps3_system_bus_device *dev)
+{
+ BUG_ON(!dev);
+ pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+ switch (dev->match_id) {
+ case PS3_MATCH_ID_EHCI:
+ case PS3_MATCH_ID_OHCI:
+ case PS3_MATCH_ID_GELIC:
+ case PS3_MATCH_ID_STOR_DISK:
+ case PS3_MATCH_ID_STOR_ROM:
+ case PS3_MATCH_ID_STOR_FLASH:
+ return ps3_close_hv_device_sb(dev);
+
+ case PS3_MATCH_ID_SOUND:
+ case PS3_MATCH_ID_GRAPHICS:
+ return ps3_close_hv_device_gpu(dev);
+
+ case PS3_MATCH_ID_AV_SETTINGS:
+ case PS3_MATCH_ID_SYSTEM_MANAGER:
+ pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+ __LINE__, dev->match_id);
+ pr_debug("%s:%d: bus_id: %u\n", __func__,
+ __LINE__, dev->bus_id);
+ BUG();
+ return -EINVAL;
+
+ default:
+ break;
+ }
+
+ pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+ dev->match_id);
+ BUG();
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_close_hv_device);
+
#define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
static void _dump_mmio_region(const struct ps3_mmio_region* r,
const char* func, int line)
{
- pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id,
- r->did.dev_id);
+ pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id,
+ r->dev->dev_id);
pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
pr_debug("%s:%d: len %lxh\n", func, line, r->len);
pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr);
}
-int ps3_mmio_region_create(struct ps3_mmio_region *r)
+static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r)
{
int result;
- result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id,
+ result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
r->bus_addr, r->len, r->page_size, &r->lpar_addr);
if (result) {
@@ -57,13 +263,26 @@ int ps3_mmio_region_create(struct ps3_mmio_region *r)
dump_mmio_region(r);
return result;
}
+
+static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r)
+{
+ /* device specific; do nothing currently */
+ return 0;
+}
+
+int ps3_mmio_region_create(struct ps3_mmio_region *r)
+{
+ return r->mmio_ops->create(r);
+}
EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
-int ps3_free_mmio_region(struct ps3_mmio_region *r)
+static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r)
{
int result;
- result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id,
+ dump_mmio_region(r);
+;
+ result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
r->lpar_addr);
if (result)
@@ -73,14 +292,60 @@ int ps3_free_mmio_region(struct ps3_mmio_region *r)
r->lpar_addr = 0;
return result;
}
+
+static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r)
+{
+ /* device specific; do nothing currently */
+ return 0;
+}
+
+
+int ps3_free_mmio_region(struct ps3_mmio_region *r)
+{
+ return r->mmio_ops->free(r);
+}
+
EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
+static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = {
+ .create = ps3_sb_mmio_region_create,
+ .free = ps3_sb_free_mmio_region
+};
+
+static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = {
+ .create = ps3_ioc0_mmio_region_create,
+ .free = ps3_ioc0_free_mmio_region
+};
+
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+ struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+ enum ps3_mmio_page_size page_size)
+{
+ r->dev = dev;
+ r->bus_addr = bus_addr;
+ r->len = len;
+ r->page_size = page_size;
+ switch (dev->dev_type) {
+ case PS3_DEVICE_TYPE_SB:
+ r->mmio_ops = &ps3_mmio_sb_region_ops;
+ break;
+ case PS3_DEVICE_TYPE_IOC0:
+ r->mmio_ops = &ps3_mmio_ioc0_region_ops;
+ break;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_mmio_region_init);
+
static int ps3_system_bus_match(struct device *_dev,
struct device_driver *_drv)
{
int result;
- struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv);
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
result = dev->match_id == drv->match_id;
@@ -92,32 +357,14 @@ static int ps3_system_bus_match(struct device *_dev,
static int ps3_system_bus_probe(struct device *_dev)
{
- int result;
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
- struct ps3_system_bus_driver *drv =
- to_ps3_system_bus_driver(_dev->driver);
-
- result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0);
-
- if (result) {
- pr_debug("%s:%d: lv1_open_device failed (%d)\n",
- __func__, __LINE__, result);
- result = -EACCES;
- goto clean_none;
- }
-
- if (dev->d_region->did.bus_id) {
- result = ps3_dma_region_create(dev->d_region);
+ int result = 0;
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ struct ps3_system_bus_driver *drv;
- if (result) {
- pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n",
- __func__, __LINE__, result);
- BUG_ON("check region type");
- result = -EINVAL;
- goto clean_device;
- }
- }
+ BUG_ON(!dev);
+ pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+ drv = ps3_system_bus_dev_to_system_bus_drv(dev);
BUG_ON(!drv);
if (drv->probe)
@@ -126,56 +373,127 @@ static int ps3_system_bus_probe(struct device *_dev)
pr_info("%s:%d: %s no probe method\n", __func__, __LINE__,
dev->core.bus_id);
- if (result) {
- pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__);
- goto clean_dma;
- }
-
- return result;
-
-clean_dma:
- ps3_dma_region_free(dev->d_region);
-clean_device:
- lv1_close_device(dev->did.bus_id, dev->did.dev_id);
-clean_none:
+ pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
return result;
}
static int ps3_system_bus_remove(struct device *_dev)
{
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
- struct ps3_system_bus_driver *drv =
- to_ps3_system_bus_driver(_dev->driver);
+ int result = 0;
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ struct ps3_system_bus_driver *drv;
+
+ BUG_ON(!dev);
+ pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+
+ drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+ BUG_ON(!drv);
if (drv->remove)
- drv->remove(dev);
+ result = drv->remove(dev);
else
- pr_info("%s:%d: %s no remove method\n", __func__, __LINE__,
- dev->core.bus_id);
+ dev_dbg(&dev->core, "%s:%d %s: no remove method\n",
+ __func__, __LINE__, drv->core.name);
+
+ pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
+ return result;
+}
+
+static void ps3_system_bus_shutdown(struct device *_dev)
+{
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ struct ps3_system_bus_driver *drv;
+
+ BUG_ON(!dev);
+
+ dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+ dev->match_id);
+
+ if (!dev->core.driver) {
+ dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+ __LINE__);
+ return;
+ }
+
+ drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+
+ BUG_ON(!drv);
+
+ dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__,
+ dev->core.bus_id, drv->core.name);
+
+ if (drv->shutdown)
+ drv->shutdown(dev);
+ else if (drv->remove) {
+ dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n",
+ __func__, __LINE__, drv->core.name);
+ drv->remove(dev);
+ } else {
+ dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n",
+ __func__, __LINE__, drv->core.name);
+ BUG();
+ }
+
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+}
+
+static int ps3_system_bus_uevent(struct device *_dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ int i = 0, length = 0;
- ps3_dma_region_free(dev->d_region);
- ps3_free_mmio_region(dev->m_region);
- lv1_close_device(dev->did.bus_id, dev->did.dev_id);
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "MODALIAS=ps3:%d",
+ dev->match_id))
+ return -ENOMEM;
+ envp[i] = NULL;
return 0;
}
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+ char *buf)
+{
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute ps3_system_bus_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
struct bus_type ps3_system_bus_type = {
.name = "ps3_system_bus",
.match = ps3_system_bus_match,
+ .uevent = ps3_system_bus_uevent,
.probe = ps3_system_bus_probe,
.remove = ps3_system_bus_remove,
+ .shutdown = ps3_system_bus_shutdown,
+ .dev_attrs = ps3_system_bus_dev_attrs,
};
-int __init ps3_system_bus_init(void)
+static int __init ps3_system_bus_init(void)
{
int result;
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
return -ENODEV;
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ mutex_init(&usage_hack.mutex);
+
+ result = device_register(&ps3_system_bus);
+ BUG_ON(result);
+
result = bus_register(&ps3_system_bus_type);
BUG_ON(result);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result;
}
@@ -185,16 +503,13 @@ core_initcall(ps3_system_bus_init);
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
-
static void * ps3_alloc_coherent(struct device *_dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag)
{
int result;
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
unsigned long virt_addr;
- BUG_ON(!dev->d_region->bus_addr);
-
flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
flag |= __GFP_ZERO;
@@ -205,7 +520,8 @@ static void * ps3_alloc_coherent(struct device *_dev, size_t size,
goto clean_none;
}
- result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle);
+ result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
+ IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
if (result) {
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -226,7 +542,7 @@ clean_none:
static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
ps3_dma_unmap(dev->d_region, dma_handle, size);
free_pages((unsigned long)vaddr, get_order(size));
@@ -239,15 +555,16 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
* byte within the page as vaddr.
*/
-static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
+static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size,
enum dma_data_direction direction)
{
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
unsigned long bus_addr;
result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
- &bus_addr);
+ &bus_addr,
+ IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M);
if (result) {
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -257,10 +574,44 @@ static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
return bus_addr;
}
+static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr,
+ size_t size,
+ enum dma_data_direction direction)
+{
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+ int result;
+ unsigned long bus_addr;
+ u64 iopte_flag;
+
+ iopte_flag = IOPTE_M;
+ switch (direction) {
+ case DMA_BIDIRECTIONAL:
+ iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW;
+ break;
+ case DMA_TO_DEVICE:
+ iopte_flag |= IOPTE_PP_R | IOPTE_SO_R;
+ break;
+ case DMA_FROM_DEVICE:
+ iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW;
+ break;
+ default:
+ /* not happned */
+ BUG();
+ };
+ result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
+ &bus_addr, iopte_flag);
+
+ if (result) {
+ pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
+ __func__, __LINE__, result);
+ }
+ return bus_addr;
+}
+
static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction)
{
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
result = ps3_dma_unmap(dev->d_region, dma_addr, size);
@@ -271,20 +622,20 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
}
}
-static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
+static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
BUG_ON("do");
return -EPERM;
#else
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int i;
for (i = 0; i < nents; i++, sg++) {
int result = ps3_dma_map(dev->d_region,
page_to_phys(sg->page) + sg->offset, sg->length,
- &sg->dma_address);
+ &sg->dma_address, 0);
if (result) {
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -299,7 +650,15 @@ static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
#endif
}
-static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
+static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
+ int nents,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return 0;
+}
+
+static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
@@ -307,18 +666,34 @@ static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
#endif
}
+static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+{
+ BUG();
+}
+
static int ps3_dma_supported(struct device *_dev, u64 mask)
{
return mask >= DMA_32BIT_MASK;
}
-static struct dma_mapping_ops ps3_dma_ops = {
+static struct dma_mapping_ops ps3_sb_dma_ops = {
.alloc_coherent = ps3_alloc_coherent,
.free_coherent = ps3_free_coherent,
- .map_single = ps3_map_single,
+ .map_single = ps3_sb_map_single,
.unmap_single = ps3_unmap_single,
- .map_sg = ps3_map_sg,
- .unmap_sg = ps3_unmap_sg,
+ .map_sg = ps3_sb_map_sg,
+ .unmap_sg = ps3_sb_unmap_sg,
+ .dma_supported = ps3_dma_supported
+};
+
+static struct dma_mapping_ops ps3_ioc0_dma_ops = {
+ .alloc_coherent = ps3_alloc_coherent,
+ .free_coherent = ps3_free_coherent,
+ .map_single = ps3_ioc0_map_single,
+ .unmap_single = ps3_unmap_single,
+ .map_sg = ps3_ioc0_map_sg,
+ .unmap_sg = ps3_ioc0_unmap_sg,
.dma_supported = ps3_dma_supported
};
@@ -328,7 +703,7 @@ static struct dma_mapping_ops ps3_dma_ops = {
static void ps3_system_bus_release_device(struct device *_dev)
{
- struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+ struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
kfree(dev);
}
@@ -343,19 +718,38 @@ static void ps3_system_bus_release_device(struct device *_dev)
int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
{
int result;
- static unsigned int dev_count = 1;
+ static unsigned int dev_ioc0_count;
+ static unsigned int dev_sb_count;
+ static unsigned int dev_vuart_count;
- dev->core.parent = NULL;
+ if (!dev->core.parent)
+ dev->core.parent = &ps3_system_bus;
dev->core.bus = &ps3_system_bus_type;
dev->core.release = ps3_system_bus_release_device;
+ switch (dev->dev_type) {
+ case PS3_DEVICE_TYPE_IOC0:
+ dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops;
+ snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+ "ioc0_%02x", ++dev_ioc0_count);
+ break;
+ case PS3_DEVICE_TYPE_SB:
+ dev->core.archdata.dma_ops = &ps3_sb_dma_ops;
+ snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+ "sb_%02x", ++dev_sb_count);
+
+ break;
+ case PS3_DEVICE_TYPE_VUART:
+ snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+ "vuart_%02x", ++dev_vuart_count);
+ break;
+ default:
+ BUG();
+ };
+
dev->core.archdata.of_node = NULL;
- dev->core.archdata.dma_ops = &ps3_dma_ops;
dev->core.archdata.numa_node = 0;
- snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x",
- dev_count++);
-
pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
result = device_register(&dev->core);
@@ -368,9 +762,15 @@ int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv)
{
int result;
+ pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
+
+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return -ENODEV;
+
drv->core.bus = &ps3_system_bus_type;
result = driver_register(&drv->core);
+ pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
return result;
}
@@ -378,7 +778,9 @@ EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register);
void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
{
+ pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
driver_unregister(&drv->core);
+ pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
}
EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 1bae8b19b363..802a9ccacb5e 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -39,7 +39,7 @@ static void _dump_tm(const struct rtc_time *tm, const char* func, int line)
}
#define dump_time(_a) _dump_time(_a, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_time(int time, const char* func,
+static void __maybe_unused _dump_time(int time, const char *func,
int line)
{
struct rtc_time tm;
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index ae1fc92dc1c9..992ba6753cf2 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -8,7 +8,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
-obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
obj-$(CONFIG_PCI_MSI) += msi.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 5f3e6d8659fe..b8770395013d 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1,6 +1,8 @@
/*
* eeh.c
- * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation
+ * Copyright IBM Corporation 2001, 2005, 2006
+ * Copyright Dave Engebretsen & Todd Inglett 2001
+ * Copyright Linas Vepstas 2005, 2006
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,6 +17,8 @@
* 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
+ *
+ * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
*/
#include <linux/delay.h>
@@ -117,7 +121,6 @@ static unsigned long no_cfg_addr;
static unsigned long ignored_check;
static unsigned long total_mmio_ffs;
static unsigned long false_positives;
-static unsigned long ignored_failures;
static unsigned long slot_resets;
#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
@@ -505,6 +508,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
ret, dn->full_name);
false_positives++;
+ pdn->eeh_false_positives ++;
rc = 0;
goto dn_unlock;
}
@@ -513,6 +517,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
* they are empty when they don't have children. */
if ((rets[0] == 5) && (dn->child == NULL)) {
false_positives++;
+ pdn->eeh_false_positives ++;
rc = 0;
goto dn_unlock;
}
@@ -522,6 +527,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
ret, dn->full_name);
false_positives++;
+ pdn->eeh_false_positives ++;
rc = 0;
goto dn_unlock;
}
@@ -529,6 +535,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
/* If not the kind of error we know about, punt. */
if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
false_positives++;
+ pdn->eeh_false_positives ++;
rc = 0;
goto dn_unlock;
}
@@ -921,6 +928,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
pdn->eeh_mode = 0;
pdn->eeh_check_count = 0;
pdn->eeh_freeze_count = 0;
+ pdn->eeh_false_positives = 0;
if (status && strcmp(status, "ok") != 0)
return NULL; /* ignore devices with bad status */
@@ -1139,7 +1147,8 @@ static void eeh_add_device_late(struct pci_dev *dev)
pdn = PCI_DN(dn);
pdn->pcidev = dev;
- pci_addr_cache_insert_device (dev);
+ pci_addr_cache_insert_device(dev);
+ eeh_sysfs_add_device(dev);
}
void eeh_add_device_tree_late(struct pci_bus *bus)
@@ -1178,6 +1187,7 @@ static void eeh_remove_device(struct pci_dev *dev)
printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
#endif
pci_addr_cache_remove_device(dev);
+ eeh_sysfs_remove_device(dev);
dn = pci_device_to_OF_node(dev);
if (PCI_DN(dn)->pcidev) {
@@ -1214,11 +1224,10 @@ static int proc_eeh_show(struct seq_file *m, void *v)
"check not wanted=%ld\n"
"eeh_total_mmio_ffs=%ld\n"
"eeh_false_positives=%ld\n"
- "eeh_ignored_failures=%ld\n"
"eeh_slot_resets=%ld\n",
no_device, no_dn, no_cfg_addr,
ignored_check, total_mmio_ffs,
- false_positives, ignored_failures,
+ false_positives,
slot_resets);
}
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index f2bae04424f8..e49c815eae23 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -2,7 +2,8 @@
* eeh_cache.c
* PCI address cache; allows the lookup of PCI devices based on I/O address
*
- * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
+ * Copyright IBM Corporation 2004
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2004
*
* 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
@@ -295,6 +296,8 @@ void __init pci_addr_cache_build(void)
continue;
pci_dev_get (dev); /* matching put is in eeh_remove_device() */
PCI_DN(dn)->pcidev = dev;
+
+ eeh_sysfs_add_device(dev);
}
#ifdef DEBUG
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 161a5844ab6c..15e015ef6865 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -1,6 +1,7 @@
/*
* PCI Error Recovery Driver for RPA-compliant PPC64 platform.
- * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+ * Copyright IBM Corp. 2004 2005
+ * Copyright Linas Vepstas <linas@linas.org> 2004, 2005
*
* All rights reserved.
*
@@ -19,8 +20,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Send feedback to <linas@us.ibm.com>
- *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
*/
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c
new file mode 100644
index 000000000000..15e13b568904
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c
@@ -0,0 +1,87 @@
+/*
+ * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
+ * Copyright IBM Corporation 2007
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
+ *
+ * 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, 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.
+ *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
+ */
+#include <linux/pci.h>
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+#include <linux/kobject.h>
+
+/**
+ * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
+ * @_name: name of file in sysfs directory
+ * @_memb: name of member in struct pci_dn to access
+ * @_format: printf format for display
+ *
+ * All of the attributes look very similar, so just
+ * auto-gen a cut-n-paste routine to display them.
+ */
+#define EEH_SHOW_ATTR(_name,_memb,_format) \
+static ssize_t eeh_show_##_name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct pci_dev *pdev = to_pci_dev(dev); \
+ struct device_node *dn = pci_device_to_OF_node(pdev); \
+ struct pci_dn *pdn; \
+ \
+ if (!dn || PCI_DN(dn) == NULL) \
+ return 0; \
+ \
+ pdn = PCI_DN(dn); \
+ return sprintf(buf, _format "\n", pdn->_memb); \
+} \
+static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
+
+
+EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x");
+EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d");
+EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d");
+EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
+
+void eeh_sysfs_add_device(struct pci_dev *pdev)
+{
+ int rc=0;
+
+ rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
+ rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
+ rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+ rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
+ rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
+ rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+
+ if (rc)
+ printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
+}
+
+void eeh_sysfs_remove_device(struct pci_dev *pdev)
+{
+ device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
+ device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
+ device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+ device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
+ device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
+ device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+}
+
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 362dfbc260a6..8cc6eeeaae2f 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -373,12 +373,23 @@ static void pSeries_lpar_hptab_clear(void)
{
unsigned long size_bytes = 1UL << ppc64_pft_size;
unsigned long hpte_count = size_bytes >> 4;
- unsigned long dummy1, dummy2;
+ unsigned long dummy1, dummy2, dword0;
+ long lpar_rc;
int i;
/* TODO: Use bulk call */
- for (i = 0; i < hpte_count; i++)
- plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+ for (i = 0; i < hpte_count; i++) {
+ /* dont remove HPTEs with VRMA mappings */
+ lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG,
+ &dummy1, &dummy2);
+ if (lpar_rc == H_NOT_FOUND) {
+ lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1);
+ if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK)
+ != HPTE_V_VRMA_MASK))
+ /* Can be hpte for 1TB Seg. So remove it */
+ plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+ }
+ }
}
/*
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index ffaf6c5c517b..47f0e0857f0e 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -110,8 +110,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
}
}
}
-
- eeh_add_device_tree_late(bus);
}
EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
@@ -139,6 +137,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
/* Make the discovered devices available */
pci_bus_add_devices(child_bus);
+
+ eeh_add_device_tree_late(child_bus);
return 0;
}
@@ -171,6 +171,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
if (!list_empty(&bus->devices)) {
pcibios_fixup_new_pci_devices(bus, 0);
pci_bus_add_devices(bus);
+ eeh_add_device_tree_late(bus);
}
} else if (mode == PCI_PROBE_NORMAL) {
/* use legacy probe */
@@ -179,6 +180,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
if (num) {
pcibios_fixup_new_pci_devices(bus, 1);
pci_bus_add_devices(bus);
+ eeh_add_device_tree_late(bus);
}
list_for_each_entry(dev, &bus->devices, bus_list)
@@ -200,8 +202,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
rtas_setup_phb(phb);
pci_process_bridge_OF_ranges(phb, dn, 0);
- pci_setup_phb_io_dynamic(phb, primary);
-
pci_devs_phb_init_dynamic(phb);
if (dn->child)
@@ -210,6 +210,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
scan_phb(phb);
pcibios_fixup_new_pci_devices(phb->bus, 0);
pci_bus_add_devices(phb->bus);
+ eeh_add_device_tree_late(phb->bus);
return phb;
}
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 2e4d10c9eea8..d003c80fa31d 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -108,6 +108,21 @@ static inline long plpar_pte_read(unsigned long flags, unsigned long ptex,
return rc;
}
+/* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */
+static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex,
+ unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
+{
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex);
+
+ *old_pteh_ret = retbuf[0];
+ *old_ptel_ret = retbuf[1];
+
+ return rc;
+}
+
static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
unsigned long avpn)
{
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 2729d559fd91..61e19f78b923 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -33,6 +33,8 @@ static inline void setup_kexec_cpu_down_xics(void) { }
static inline void setup_kexec_cpu_down_mpic(void) { }
#endif
+extern void pSeries_final_fixup(void);
+
/* Poweron flag used for enabling auto ups restart */
extern unsigned long rtas_poweron_auto;
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 5aa97aff3391..c02f8742c54d 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -123,7 +123,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
strcpy(np->full_name, path);
np->properties = proplist;
- OF_MARK_DYNAMIC(np);
+ of_node_set_flag(np, OF_DYNAMIC);
kref_init(&np->kref);
np->parent = derive_parent(path);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index a031d99becb7..59e69f085cb4 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -399,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void)
* a good time to find other work to dispatch.
*/
get_lppaca()->idle = 1;
+ get_lppaca()->donate_dedicated_cpu = 1;
/*
* We come in with interrupts disabled, and need_resched()
@@ -431,6 +432,7 @@ static void pseries_dedicated_idle_sleep(void)
out:
HMT_medium();
+ get_lppaca()->donate_dedicated_cpu = 0;
get_lppaca()->idle = 0;
}
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index f1df942072bb..5bd90a7eb763 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
#ifdef CONFIG_SMP
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
{
- unsigned int server;
+ int server;
/* For the moment only implement delivery to all cpus or one cpu */
cpumask_t cpumask = irq_desc[virq].affinity;
cpumask_t tmp = CPU_MASK_NONE;
@@ -166,22 +166,25 @@ static int get_irq_server(unsigned int virq)
if (!distribute_irqs)
return default_server;
- if (cpus_equal(cpumask, CPU_MASK_ALL)) {
- server = default_distrib_server;
- } else {
+ if (!cpus_equal(cpumask, CPU_MASK_ALL)) {
cpus_and(tmp, cpu_online_map, cpumask);
- if (cpus_empty(tmp))
- server = default_distrib_server;
- else
- server = get_hard_smp_processor_id(first_cpu(tmp));
+ server = first_cpu(tmp);
+
+ if (server < NR_CPUS)
+ return get_hard_smp_processor_id(server);
+
+ if (strict_check)
+ return -1;
}
- return server;
+ if (cpus_equal(cpu_online_map, cpu_present_map))
+ return default_distrib_server;
+ return default_server;
}
#else
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
{
return default_server;
}
@@ -192,7 +195,7 @@ static void xics_unmask_irq(unsigned int virq)
{
unsigned int irq;
int call_status;
- unsigned int server;
+ int server;
pr_debug("xics: unmask virq %d\n", virq);
@@ -201,7 +204,7 @@ static void xics_unmask_irq(unsigned int virq)
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
return;
- server = get_irq_server(virq);
+ server = get_irq_server(virq, 0);
call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
DEFAULT_PRIORITY);
@@ -398,8 +401,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
unsigned int irq;
int status;
int xics_status[2];
- unsigned long newmask;
- cpumask_t tmp = CPU_MASK_NONE;
+ int irq_server;
irq = (unsigned int)irq_map[virq].hwirq;
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -413,18 +415,21 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
return;
}
- /* For the moment only implement delivery to all cpus or one cpu */
- if (cpus_equal(cpumask, CPU_MASK_ALL)) {
- newmask = default_distrib_server;
- } else {
- cpus_and(tmp, cpu_online_map, cpumask);
- if (cpus_empty(tmp))
- return;
- newmask = get_hard_smp_processor_id(first_cpu(tmp));
+ /*
+ * For the moment only implement delivery to all cpus or one cpu.
+ * Get current irq_server for the given irq
+ */
+ irq_server = get_irq_server(irq, 1);
+ if (irq_server == -1) {
+ char cpulist[128];
+ cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+ printk(KERN_WARNING "xics_set_affinity: No online cpus in "
+ "the mask %s for irq %d\n", cpulist, virq);
+ return;
}
status = rtas_call(ibm_set_xive, 3, 1, NULL,
- irq, newmask, xics_status[1]);
+ irq, irq_server, xics_status[1]);
if (status) {
printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index c3ce0bd12c0b..f65078c3d3b3 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,7 +5,6 @@ endif
mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
-obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
obj-$(CONFIG_PPC_DCR) += dcr.o
obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o
@@ -13,16 +12,19 @@ obj-$(CONFIG_PPC_PMI) += pmi.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
-obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
mv64x60-$(CONFIG_PCI) += mv64x60_pci.o
obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o
+obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
# contains only the suspend handler for time
+ifeq ($(CONFIG_RTC_CLASS),)
obj-$(CONFIG_PM) += timer.o
+endif
ifeq ($(CONFIG_PPC_MERGE),y)
+obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_PPC_83xx) += ipic.o
obj-$(CONFIG_4xx) += uic.o
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c
deleted file mode 100644
index 041c07e8b665..000000000000
--- a/arch/powerpc/sysdev/fsl_pcie.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Support for indirect PCI bridges.
- *
- * Copyright (C) 1998 Gabriel Paubert.
- *
- * 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.
- *
- * "Temporary" MPC8548 Errata file -
- * The standard indirect_pci code should work with future silicon versions.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#define PCI_CFG_OUT out_be32
-
-/* ERRATA PCI-Ex 14 PCIE Controller timeout */
-#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
-
-
-static int
-indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- volatile void __iomem *cfg_data;
- u32 temp;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Possible artifact of CDCpp50937 needs further investigation */
- if (devfn != 0x0 && bus->number == 0xff)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- PCIE_FIX;
- if (bus->number == 0xff) {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000000 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- } else {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000001 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- }
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
- cfg_data = hose->cfg_data;
- PCIE_FIX;
- temp = in_le32(cfg_data);
- switch (len) {
- case 1:
- *val = (temp >> (((offset & 3))*8)) & 0xff;
- break;
- case 2:
- *val = (temp >> (((offset & 3))*8)) & 0xffff;
- break;
- default:
- *val = temp;
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- volatile void __iomem *cfg_data;
- u32 temp;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Possible artifact of CDCpp50937 needs further investigation */
- if (devfn != 0x0 && bus->number == 0xff)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- PCIE_FIX;
- if (bus->number == 0xff) {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000000 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- } else {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000001 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- }
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
- cfg_data = hose->cfg_data;
- switch (len) {
- case 1:
- PCIE_FIX;
- temp = in_le32(cfg_data);
- temp = (temp & ~(0xff << ((offset & 3) * 8))) |
- (val << ((offset & 3) * 8));
- PCIE_FIX;
- out_le32(cfg_data, temp);
- break;
- case 2:
- PCIE_FIX;
- temp = in_le32(cfg_data);
- temp = (temp & ~(0xffff << ((offset & 3) * 8)));
- temp |= (val << ((offset & 3) * 8)) ;
- PCIE_FIX;
- out_le32(cfg_data, temp);
- break;
- default:
- PCIE_FIX;
- out_le32(cfg_data, val);
- break;
- }
- PCIE_FIX;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops indirect_pcie_ops = {
- indirect_read_config_pcie,
- indirect_write_config_pcie
-};
-
-void __init
-setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
- void __iomem * cfg_data)
-{
- hose->cfg_addr = cfg_addr;
- hose->cfg_data = cfg_data;
- hose->ops = &indirect_pcie_ops;
-}
-
-void __init
-setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
-{
- unsigned long base = cfg_addr & PAGE_MASK;
- void __iomem *mbase, *addr, *data;
-
- mbase = ioremap(base, PAGE_SIZE);
- addr = mbase + (cfg_addr & ~PAGE_MASK);
- if ((cfg_data & PAGE_MASK) != base)
- mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
- data = mbase + (cfg_data & ~PAGE_MASK);
- setup_indirect_pcie_nomap(hose, addr, data);
-}
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index cad175724359..c0ddc80d8160 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -1028,6 +1028,19 @@ err:
arch_initcall(fs_enet_of_init);
+static int __init fsl_pcmcia_of_init(void)
+{
+ struct device_node *np = NULL;
+ /*
+ * Register all the devices which type is "pcmcia"
+ */
+ while ((np = of_find_compatible_node(np,
+ "pcmcia", "fsl,pq-pcmcia")) != NULL)
+ of_platform_device_create(np, "m8xx-pcmcia", NULL);
+ return 0;
+}
+
+arch_initcall(fsl_pcmcia_of_init);
static const char *smc_regs = "regs";
static const char *smc_pram = "pram";
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index e71488469704..c7e6e859b393 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -33,18 +33,27 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
struct pci_controller *hose = bus->sysdata;
volatile void __iomem *cfg_data;
u8 cfg_type = 0;
+ u32 bus_no, reg;
if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (hose->set_cfg_type)
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
if (bus->number != hose->first_busno)
cfg_type = 1;
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000000 | ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+ bus_no = (bus->number == hose->first_busno) ?
+ hose->self_busno : bus->number;
+
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+ reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+ else
+ reg = offset & 0xfc;
+
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | (bus_no << 16)
+ | (devfn << 8) | reg | cfg_type));
/*
* Note: the caller has already checked that offset is
@@ -72,18 +81,33 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
struct pci_controller *hose = bus->sysdata;
volatile void __iomem *cfg_data;
u8 cfg_type = 0;
+ u32 bus_no, reg;
if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (hose->set_cfg_type)
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
if (bus->number != hose->first_busno)
cfg_type = 1;
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000000 | ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+ bus_no = (bus->number == hose->first_busno) ?
+ hose->self_busno : bus->number;
+
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+ reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+ else
+ reg = offset & 0xfc;
+
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | (bus_no << 16)
+ | (devfn << 8) | reg | cfg_type));
+
+ /* surpress setting of PCI_PRIMARY_BUS */
+ if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
+ if ((offset == PCI_PRIMARY_BUS) &&
+ (bus->number == hose->first_busno))
+ val &= 0xffffff00;
/*
* Note: the caller has already checked that offset is
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
index afa2ee6717c1..9fe00eebdc8b 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.h
+++ b/arch/powerpc/sysdev/mpc8xx_pic.h
@@ -4,9 +4,16 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
-extern struct hw_interrupt_type mpc8xx_pic;
-
int mpc8xx_pic_init(void);
unsigned int mpc8xx_get_irq(void);
+/*
+ * Some internal interrupt registers use an 8-bit mask for the interrupt
+ * level instead of a number.
+ */
+static inline uint mk_int_int_mask(uint mask)
+{
+ return (1 << (7 - (mask/2)));
+}
+
#endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 4b0a9c88eeb3..b618fa60aef3 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -12,6 +12,7 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/console.h>
#include <linux/mv643xx.h>
#include <linux/platform_device.h>
@@ -420,3 +421,30 @@ error:
return err;
}
arch_initcall(mv64x60_device_setup);
+
+static int __init mv64x60_add_mpsc_console(void)
+{
+ struct device_node *np = NULL;
+ const char *prop;
+
+ prop = of_get_property(of_chosen, "linux,stdout-path", NULL);
+ if (prop == NULL)
+ goto not_mpsc;
+
+ np = of_find_node_by_path(prop);
+ if (!np)
+ goto not_mpsc;
+
+ if (!of_device_is_compatible(np, "marvell,mpsc"))
+ goto not_mpsc;
+
+ prop = of_get_property(np, "block-index", NULL);
+ if (!prop)
+ goto not_mpsc;
+
+ add_preferred_console("ttyMM", *(int *)prop, NULL);
+
+not_mpsc:
+ return 0;
+}
+console_initcall(mv64x60_add_mpsc_console);
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
index b5aef4cbc8d2..45db86c2363c 100644
--- a/arch/powerpc/sysdev/mv64x60_pci.c
+++ b/arch/powerpc/sysdev/mv64x60_pci.c
@@ -137,18 +137,15 @@ static int __init mv64x60_add_bridge(struct device_node *dev)
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
- hose->arch_data = dev;
- hose->set_cfg_type = 1;
-
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
setup_indirect_pci(hose, rsrc.start, rsrc.start + 4);
- hose->bus_offset = hose->first_busno;
+ hose->self_busno = hose->first_busno;
printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. "
"Firmware bus number: %d->%d\n",
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index ac12a44d516f..f970e5415ac0 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
+#include <linux/module.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -40,6 +41,7 @@ int ucc_set_qe_mux_mii_mng(int ucc_num)
return 0;
}
+EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
int ucc_set_type(int ucc_num, struct ucc_common *regs,
enum ucc_speed_type speed)
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 9143236853fc..3df202e8d332 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -19,6 +19,7 @@
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/immap_qe.h>
@@ -70,6 +71,7 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
(u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
}
+EXPORT_SYMBOL(ucc_fast_dump_regs);
u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
{
@@ -85,11 +87,13 @@ u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
default: return QE_CR_SUBBLOCK_INVALID;
}
}
+EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock);
void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
{
out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
}
+EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
{
@@ -110,6 +114,7 @@ void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
}
out_be32(&uf_regs->gumr, gumr);
}
+EXPORT_SYMBOL(ucc_fast_enable);
void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
{
@@ -130,6 +135,7 @@ void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
}
out_be32(&uf_regs->gumr, gumr);
}
+EXPORT_SYMBOL(ucc_fast_disable);
int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
{
@@ -341,6 +347,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
*uccf_ret = uccf;
return 0;
}
+EXPORT_SYMBOL(ucc_fast_init);
void ucc_fast_free(struct ucc_fast_private * uccf)
{
@@ -355,3 +362,4 @@ void ucc_fast_free(struct ucc_fast_private * uccf)
kfree(uccf);
}
+EXPORT_SYMBOL(ucc_fast_free);
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
new file mode 100644
index 000000000000..e276048b8c5f
--- /dev/null
+++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
@@ -0,0 +1,49 @@
+/*
+ * Setup code for PC-style Real-Time Clock.
+ *
+ * Author: Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/prom.h>
+
+static int __init add_rtc(void)
+{
+ struct device_node *np;
+ struct platform_device *pd;
+ struct resource res;
+ int ret;
+
+ np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00");
+ if (!np)
+ return -ENODEV;
+
+ ret = of_address_to_resource(np, 0, &res);
+ of_node_put(np);
+ if (ret)
+ return ret;
+
+ /*
+ * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h. Verify that the
+ * address provided by the device node matches.
+ */
+ if (res.start != RTC_PORT(0))
+ return -EINVAL;
+
+ pd = platform_device_register_simple("rtc_cmos", -1,
+ &res, 1);
+ if (IS_ERR(pd))
+ return PTR_ERR(pd);
+
+ return 0;
+}
+fs_initcall(add_rtc);
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c
index 4a01748b4217..e81e7ec2e799 100644
--- a/arch/powerpc/sysdev/timer.c
+++ b/arch/powerpc/sysdev/timer.c
@@ -24,7 +24,12 @@ static int timer_resume(struct sys_device *dev)
/* get current RTC time and convert to seconds */
get_rtc_time(&cur_rtc_tm);
- rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time);
+ cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
+ cur_rtc_tm.tm_mon + 1,
+ cur_rtc_tm.tm_mday,
+ cur_rtc_tm.tm_hour,
+ cur_rtc_tm.tm_min,
+ cur_rtc_tm.tm_sec);
diff = cur_rtc_time - suspend_rtc_time;
@@ -44,7 +49,12 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state)
WARN_ON(!ppc_md.get_rtc_time);
get_rtc_time(&suspend_rtc_tm);
- rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time);
+ suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
+ suspend_rtc_tm.tm_mon + 1,
+ suspend_rtc_tm.tm_mday,
+ suspend_rtc_tm.tm_hour,
+ suspend_rtc_tm.tm_min,
+ suspend_rtc_tm.tm_sec);
return 0;
}
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 7d3b09b7d544..a113d800cbf0 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -72,12 +72,11 @@ static int __init tsi108_eth_of_init(void)
int ret;
for (np = NULL, i = 0;
- (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+ (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL;
i++) {
struct resource r[2];
- struct device_node *phy;
+ struct device_node *phy, *mdio;
hw_info tsi_eth_data;
- const unsigned int *id;
const unsigned int *phy_id;
const void *mac_addr;
const phandle *ph;
@@ -111,6 +110,13 @@ static int __init tsi108_eth_of_init(void)
if (mac_addr)
memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
+ ph = of_get_property(np, "mdio-handle", NULL);
+ mdio = of_find_node_by_phandle(*ph);
+ ret = of_address_to_resource(mdio, 0, &res);
+ of_node_put(mdio);
+ if (ret)
+ goto unreg;
+
ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
@@ -119,20 +125,25 @@ static int __init tsi108_eth_of_init(void)
goto unreg;
}
- id = of_get_property(phy, "reg", NULL);
- phy_id = of_get_property(phy, "phy-id", NULL);
- ret = of_address_to_resource(phy, 0, &res);
- if (ret) {
- of_node_put(phy);
- goto unreg;
- }
+ phy_id = of_get_property(phy, "reg", NULL);
+
tsi_eth_data.regs = r[0].start;
tsi_eth_data.phyregs = res.start;
tsi_eth_data.phy = *phy_id;
tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
- if (of_device_is_compatible(phy, "bcm54xx"))
+
+ /* Some boards with the TSI108 bridge (e.g. Holly)
+ * have a miswiring of the ethernet PHYs which
+ * requires a workaround. The special
+ * "txc-rxc-delay-disable" property enables this
+ * workaround. FIXME: Need to port the tsi108_eth
+ * driver itself to phylib and use a non-misleading
+ * name for the workaround flag - it's not actually to
+ * do with the model of PHY in use */
+ if (of_get_property(phy, "txc-rxc-delay-disable", NULL))
tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
of_node_put(phy);
+
ret =
platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
sizeof(hw_info));
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 2153163fa593..90db8a720fed 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -64,9 +64,10 @@ tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
int offset, int len, u32 val)
{
volatile unsigned char *cfg_addr;
+ struct pci_controller *hose = bus->sysdata;
if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfunc))
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfunc))
return PCIBIOS_DEVICE_NOT_FOUND;
cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -149,10 +150,11 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 * val)
{
volatile unsigned char *cfg_addr;
+ struct pci_controller *hose = bus->sysdata;
u32 temp;
if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
+ if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -219,14 +221,12 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
" bus 0\n", dev->full_name);
}
- hose = pcibios_alloc_controller();
+ hose = pcibios_alloc_controller(dev);
if (!hose) {
printk("PCI Host bridge init failed\n");
return -ENOMEM;
}
- hose->arch_data = dev;
- hose->set_cfg_type = 1;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 28fdf4f50c27..669e6566ad70 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2634,7 +2634,7 @@ static int __init setup_xmon_sysrq(void)
__initcall(setup_xmon_sysrq);
#endif /* CONFIG_MAGIC_SYSRQ */
-int __initdata xmon_early, xmon_off;
+static int __initdata xmon_early, xmon_off;
static int __init early_parse_xmon(char *p)
{
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index d319f9ba2379..0da55368655c 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -328,7 +328,7 @@ BEGIN_FTR_SECTION
mtspr SPRN_L1CSR0,r3
isync
blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
mfspr r3,SPRN_L1CSR1
ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
mtspr SPRN_L1CSR1,r3
@@ -355,7 +355,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
_GLOBAL(__flush_icache_range)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
li r5,L1_CACHE_BYTES-1
andc r3,r3,r5
subf r4,r3,r4
@@ -472,7 +472,7 @@ _GLOBAL(flush_dcache_all)
_GLOBAL(__flush_dcache_icache)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
mtctr r4
@@ -500,7 +500,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
_GLOBAL(__flush_dcache_icache_phys)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
mfmsr r10
rlwinm r0,r10,0,28,26 /* clear DR */
mtmsr r0
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index a4165209ac7c..63f0a987139b 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -64,7 +64,6 @@ extern unsigned long mm_ptov (unsigned long paddr);
EXPORT_SYMBOL(clear_pages);
EXPORT_SYMBOL(clear_user_page);
-EXPORT_SYMBOL(do_signal);
EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
EXPORT_SYMBOL(machine_check_exception);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index c79704f5409c..967c1ef59a6b 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -526,7 +526,7 @@ void __init setup_arch(char **cmdline_p)
* Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value.
*/
- if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+ if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
dcache_bsize = cur_cpu_spec->dcache_bsize;
icache_bsize = cur_cpu_spec->icache_bsize;
ucache_bsize = 0;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index aea100be52c8..3f3b292eb773 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -92,6 +92,7 @@ int die(const char * str, struct pt_regs * fp, long err)
if (nl)
printk("\n");
show_regs(fp);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
/* do_exit() should take care of panic'ing from an interrupt
* context so we don't handle it here
@@ -619,7 +620,7 @@ void program_check_exception(struct pt_regs *regs)
return;
if (!(regs->msr & MSR_PR) && /* not user-mode */
- report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
+ report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
regs->nip += 4;
return;
}
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index fa29740a28f5..4ff260bc9dd1 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/highmem.h>
+#include <linux/pagemap.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 6f21110a9747..3c56654bfc6f 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -69,9 +69,6 @@
TODC_ALLOC();
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
extern unsigned char prep_nvram_read_val(int addr);
extern void prep_nvram_write_val(int addr,
unsigned char val);
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 95694159b226..543795be58c8 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -7,6 +7,7 @@ CFLAGS_btext.o += -fPIC
wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o
+obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o
obj-$(CONFIG_PPC_OCP) += ocp.o
obj-$(CONFIG_IBM_OCP) += ibm_ocp.o
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
new file mode 100644
index 000000000000..83b323a7d029
--- /dev/null
+++ b/arch/ppc/syslib/indirect_pci.c
@@ -0,0 +1,134 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * 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/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#ifdef CONFIG_PPC_INDIRECT_PCI_BE
+#define PCI_CFG_OUT out_be32
+#else
+#define PCI_CFG_OUT out_le32
+#endif
+
+static int
+indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+ u8 cfg_type = 0;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (bus->number != hose->first_busno)
+ cfg_type = 1;
+
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + (offset & 3);
+ switch (len) {
+ case 1:
+ *val = in_8(cfg_data);
+ break;
+ case 2:
+ *val = in_le16(cfg_data);
+ break;
+ default:
+ *val = in_le32(cfg_data);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+ u8 cfg_type = 0;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (bus->number != hose->first_busno)
+ cfg_type = 1;
+
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + (offset & 3);
+ switch (len) {
+ case 1:
+ out_8(cfg_data, val);
+ break;
+ case 2:
+ out_le16(cfg_data, val);
+ break;
+ default:
+ out_le32(cfg_data, val);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pci_ops =
+{
+ indirect_read_config,
+ indirect_write_config
+};
+
+void __init
+setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+ void __iomem * cfg_data)
+{
+ hose->cfg_addr = cfg_addr;
+ hose->cfg_data = cfg_data;
+ hose->ops = &indirect_pci_ops;
+}
+
+void __init
+setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+ unsigned long base = cfg_addr & PAGE_MASK;
+ void __iomem *mbase, *addr, *data;
+
+ mbase = ioremap(base, PAGE_SIZE);
+ addr = mbase + (cfg_addr & ~PAGE_MASK);
+ if ((cfg_data & PAGE_MASK) != base)
+ mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+ data = mbase + (cfg_data & ~PAGE_MASK);
+ setup_indirect_pci_nomap(hose, addr, data);
+}
diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c
index 16546788e23b..ace4ec08de51 100644
--- a/arch/ppc/syslib/virtex_devices.c
+++ b/arch/ppc/syslib/virtex_devices.c
@@ -71,6 +71,21 @@
}, \
}
+/*
+ * ML300/ML403 Video Device: shortcut macro for single instance
+ */
+#define XPAR_TFT(num) { \
+ .name = "xilinxfb", \
+ .id = num, \
+ .num_resources = 1, \
+ .resource = (struct resource[]) { \
+ { \
+ .start = XPAR_TFT_##num##_BASEADDR, \
+ .end = XPAR_TFT_##num##_BASEADDR+7, \
+ .flags = IORESOURCE_IO, \
+ }, \
+ }, \
+}
/* UART 8250 driver platform data table */
struct plat_serial8250_port virtex_serial_platform_data[] = {
@@ -146,20 +161,17 @@ struct platform_device virtex_platform_devices[] = {
XPAR_SYSACE(1),
#endif
- /* ML300/403 reference design framebuffer */
#if defined(XPAR_TFT_0_BASEADDR)
- {
- .name = "xilinxfb",
- .id = 0,
- .num_resources = 1,
- .resource = (struct resource[]) {
- {
- .start = XPAR_TFT_0_BASEADDR,
- .end = XPAR_TFT_0_BASEADDR+7,
- .flags = IORESOURCE_IO,
- },
- },
- },
+ XPAR_TFT(0),
+#endif
+#if defined(XPAR_TFT_1_BASEADDR)
+ XPAR_TFT(1),
+#endif
+#if defined(XPAR_TFT_2_BASEADDR)
+ XPAR_TFT(2),
+#endif
+#if defined(XPAR_TFT_3_BASEADDR)
+ XPAR_TFT(3),
#endif
};
diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h
index 3d4be1412f60..9f38d92ae536 100644
--- a/arch/ppc/syslib/virtex_devices.h
+++ b/arch/ppc/syslib/virtex_devices.h
@@ -31,4 +31,11 @@ void __init virtex_early_serial_map(void);
*/
int virtex_device_fixup(struct platform_device *dev);
+/* SPI Controller IP */
+struct xspi_platform_data {
+ s16 bus_num;
+ u16 num_chipselect;
+ u32 speed_hz;
+};
+
#endif /* __ASM_VIRTEX_DEVICES_H__ */
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 485b60c1983c..2aae23dba4bb 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Thu May 10 15:18:19 2007
+# Linux kernel version: 2.6.22
+# Tue Jul 17 12:50:23 2007
#
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
@@ -32,12 +32,11 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
CONFIG_IKCONFIG=y
@@ -61,20 +60,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLUB_DEBUG=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
@@ -82,12 +80,9 @@ CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
-
-#
-# Block layer
-#
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_BLK_DEV_BSG=y
#
# IO Schedulers
@@ -151,6 +146,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
CONFIG_HOLES_IN_ZONE=y
#
@@ -248,25 +244,13 @@ CONFIG_IPV6_SIT=y
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not set
CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -293,6 +277,7 @@ CONFIG_NET_SCH_CBQ=m
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RR=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
@@ -317,10 +302,14 @@ CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
CONFIG_NET_CLS_POLICE=y
# CONFIG_NET_CLS_IND is not set
-CONFIG_NET_ESTIMATOR=y
#
# Network testing
@@ -329,6 +318,7 @@ CONFIG_NET_ESTIMATOR=y
# CONFIG_NET_TCPPROBE is not set
# CONFIG_AF_RXRPC is not set
# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
# CONFIG_PCMCIA is not set
CONFIG_CCW=y
@@ -345,15 +335,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
CONFIG_SYS_HYPERVISOR=y
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
# CONFIG_CONNECTOR is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -376,17 +359,15 @@ CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
CONFIG_DASD_DIAG=y
CONFIG_DASD_EER=y
-
-#
-# Misc devices
-#
-# CONFIG_BLINK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
@@ -447,40 +428,21 @@ CONFIG_DM_MIRROR=y
CONFIG_DM_ZERO=y
CONFIG_DM_MULTIPATH=y
# CONFIG_DM_MULTIPATH_EMC is not set
+# CONFIG_DM_MULTIPATH_RDAC is not set
# CONFIG_DM_DELAY is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_IFB is not set
CONFIG_DUMMY=m
CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
CONFIG_EQUALIZER=m
CONFIG_TUN=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
# CONFIG_TR is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
#
@@ -511,10 +473,6 @@ CONFIG_CCWGROUP=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=m
# CONFIG_R3964 is not set
@@ -554,6 +512,8 @@ CONFIG_S390_TAPE_34XX=m
# CONFIG_VMCP is not set
# CONFIG_MONREADER is not set
CONFIG_MONWRITER=m
+CONFIG_S390_VMUR=m
+# CONFIG_POWER_SUPPLY is not set
#
# File systems
@@ -655,7 +615,6 @@ CONFIG_SUNRPC=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -712,6 +671,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
@@ -740,10 +700,6 @@ CONFIG_FORCED_INLINING=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -782,10 +738,7 @@ CONFIG_CRYPTO_FCRYPT=m
# CONFIG_CRYPTO_CRC32C is not set
CONFIG_CRYPTO_CAMELLIA=m
# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_SHA1_S390 is not set
# CONFIG_CRYPTO_SHA256_S390 is not set
# CONFIG_CRYPTO_DES_S390 is not set
@@ -800,6 +753,7 @@ CONFIG_ZCRYPT=m
CONFIG_BITREVERSE=m
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index a057ebf108a7..d3057318f2bf 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -240,8 +240,8 @@ static const unsigned char formats[][7] = {
[INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },/* e.g. ley */
[INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */
[INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */
- [INSTR_RX_URRD] = { 0x00, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */
- [INSTR_SI_URD] = { 0x00, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */
+ [INSTR_RX_URRD] = { 0xff, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */
+ [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */
[INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */
[INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */
[INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 },
@@ -1190,7 +1190,8 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
else if (operand->flags & OPERAND_CR)
ptr += sprintf(ptr, "%%c%i", value);
else if (operand->flags & OPERAND_PCREL)
- ptr += sprintf(ptr, "%lx", value + addr);
+ ptr += sprintf(ptr, "%lx", (signed int) value
+ + addr);
else if (operand->flags & OPERAND_SIGNED)
ptr += sprintf(ptr, "%i", value);
else
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 2a8f0872ea8b..f4503ca27630 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -294,7 +294,6 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
static int
do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
{
- unsigned long tmp;
ptrace_area parea;
int copied, ret;
@@ -304,10 +303,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
/* Remove high order bit from address (only for 31 bit). */
addr &= PSW_ADDR_INSN;
/* read word at location addr. */
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (copied != sizeof(tmp))
- return -EIO;
- return put_user(tmp, (unsigned long __force __user *) data);
+ return generic_ptrace_peekdata(child, addr, data);
case PTRACE_PEEKUSR:
/* read the word at location addr in the USER area. */
@@ -318,10 +314,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
/* Remove high order bit from address (only for 31 bit). */
addr &= PSW_ADDR_INSN;
/* write the word at location addr. */
- copied = access_process_vm(child, addr, &data, sizeof(data),1);
- if (copied != sizeof(data))
- return -EIO;
- return 0;
+ return generic_ptrace_pokedata(child, addr, data);
case PTRACE_POKEUSR:
/* write the word at location addr in the USER area */
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 515ff9011dd7..da6924729964 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -12,7 +12,6 @@
#include <linux/kallsyms.h>
static unsigned long save_context_stack(struct stack_trace *trace,
- unsigned int *skip,
unsigned long sp,
unsigned long low,
unsigned long high)
@@ -28,10 +27,10 @@ static unsigned long save_context_stack(struct stack_trace *trace,
sf = (struct stack_frame *)sp;
while(1) {
addr = sf->gprs[8] & PSW_ADDR_INSN;
- if (!(*skip))
+ if (!trace->skip)
trace->entries[trace->nr_entries++] = addr;
else
- (*skip)--;
+ trace->skip--;
if (trace->nr_entries >= trace->max_entries)
return sp;
low = sp;
@@ -48,10 +47,10 @@ static unsigned long save_context_stack(struct stack_trace *trace,
return sp;
regs = (struct pt_regs *)sp;
addr = regs->psw.addr & PSW_ADDR_INSN;
- if (!(*skip))
+ if (!trace->skip)
trace->entries[trace->nr_entries++] = addr;
else
- (*skip)--;
+ trace->skip--;
if (trace->nr_entries >= trace->max_entries)
return sp;
low = sp;
@@ -65,20 +64,17 @@ void save_stack_trace(struct stack_trace *trace)
unsigned long orig_sp, new_sp;
orig_sp = sp & PSW_ADDR_INSN;
-
- new_sp = save_context_stack(trace, &trace->skip, orig_sp,
- S390_lowcore.panic_stack - PAGE_SIZE,
- S390_lowcore.panic_stack);
+ new_sp = save_context_stack(trace, orig_sp,
+ S390_lowcore.panic_stack - PAGE_SIZE,
+ S390_lowcore.panic_stack);
if (new_sp != orig_sp)
return;
- new_sp = save_context_stack(trace, &trace->skip, new_sp,
- S390_lowcore.async_stack - ASYNC_SIZE,
- S390_lowcore.async_stack);
+ new_sp = save_context_stack(trace, new_sp,
+ S390_lowcore.async_stack - ASYNC_SIZE,
+ S390_lowcore.async_stack);
if (new_sp != orig_sp)
return;
-
- save_context_stack(trace, &trace->skip, new_sp,
+ save_context_stack(trace, new_sp,
S390_lowcore.thread_info,
S390_lowcore.thread_info + THREAD_SIZE);
- return;
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index ee9186f8fb08..8ec9def83ccb 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -262,6 +262,7 @@ void die(const char * str, struct pt_regs * regs, long err)
print_modules();
show_regs(regs);
bust_spinlocks(0);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -319,7 +320,7 @@ static void __kprobes inline do_trap(long interruption_code, int signr,
else {
enum bug_trap_type btt;
- btt = report_bug(regs->psw.addr & PSW_ADDR_INSN);
+ btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
if (btt == BUG_TRAP_TYPE_WARN)
return;
die(str, regs, interruption_code);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 038179ecf6a9..d8ed6676ae86 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -55,8 +55,21 @@ config GENERIC_TIME
config GENERIC_CLOCKEVENTS
def_bool n
+config SYS_SUPPORTS_PM
+ bool
+
config SYS_SUPPORTS_APM_EMULATION
bool
+ select SYS_SUPPORTS_PM
+
+config SYS_SUPPORTS_SMP
+ bool
+
+config SYS_SUPPORTS_NUMA
+ bool
+
+config SYS_SUPPORTS_PCI
+ bool
config ARCH_MAY_HAVE_PC_FDC
bool
@@ -81,24 +94,146 @@ source "init/Kconfig"
menu "System type"
-config SOLUTION_ENGINE
- bool
+source "arch/sh/mm/Kconfig"
+
+menu "Processor features"
choice
- prompt "SuperH system type"
- default SH_UNKNOWN
+ prompt "Endianess selection"
+ default CPU_LITTLE_ENDIAN
+ help
+ Some SuperH machines can be configured for either little or big
+ endian byte order. These modes require different kernels.
+
+config CPU_LITTLE_ENDIAN
+ bool "Little Endian"
+
+config CPU_BIG_ENDIAN
+ bool "Big Endian"
+
+endchoice
+
+config SH_FPU
+ bool "FPU support"
+ depends on CPU_SH4
+ default y
+ help
+ Selecting this option will enable support for SH processors that
+ have FPU units (ie, SH77xx).
+
+ This option must be set in order to enable the FPU.
+
+config SH_FPU_EMU
+ bool "FPU emulation support"
+ depends on !SH_FPU && EXPERIMENTAL
+ default n
+ help
+ Selecting this option will enable support for software FPU emulation.
+ Most SH-3 users will want to say Y here, whereas most SH-4 users will
+ want to say N.
+
+config SH_DSP
+ bool "DSP support"
+ default y if SH4AL_DSP || !CPU_SH4
+ default n
+ help
+ Selecting this option will enable support for SH processors that
+ have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP).
+
+ This option must be set in order to enable the DSP.
+
+config SH_ADC
+ bool "ADC support"
+ depends on CPU_SH3
+ default y
+ help
+ Selecting this option will allow the Linux kernel to use SH3 on-chip
+ ADC module.
+
+ If unsure, say N.
+
+config SH_STORE_QUEUES
+ bool "Support for Store Queues"
+ depends on CPU_SH4
+ help
+ Selecting this option will enable an in-kernel API for manipulating
+ the store queues integrated in the SH-4 processors.
+
+config SPECULATIVE_EXECUTION
+ bool "Speculative subroutine return"
+ depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL
+ help
+ This enables support for a speculative instruction fetch for
+ subroutine return. There are various pitfalls associated with
+ this, as outlined in the SH7780 hardware manual.
+
+ If unsure, say N.
+
+config CPU_HAS_INTEVT
+ bool
+
+config CPU_HAS_PINT_IRQ
+ bool
+
+config CPU_HAS_MASKREG_IRQ
+ bool
+
+config CPU_HAS_INTC2_IRQ
+ bool
+
+config CPU_HAS_IPR_IRQ
+ bool
+
+config CPU_HAS_SR_RB
+ bool "CPU has SR.RB"
+ depends on CPU_SH3 || CPU_SH4
+ default y
+ help
+ This will enable the use of SR.RB register bank usage. Processors
+ that are lacking this bit must have another method in place for
+ accomplishing what is taken care of by the banked registers.
+
+ See <file:Documentation/sh/register-banks.txt> for further
+ information on SR.RB and register banking in the kernel in general.
+
+config CPU_HAS_PTEA
+ bool
+
+endmenu
+
+menu "Board support"
+
+config SOLUTION_ENGINE
+ bool
config SH_SOLUTION_ENGINE
bool "SolutionEngine"
select SOLUTION_ENGINE
+ depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750
help
Select SolutionEngine if configuring for a Hitachi SH7709
or SH7750 evaluation board.
+config SH_7206_SOLUTION_ENGINE
+ bool "SolutionEngine7206"
+ select SOLUTION_ENGINE
+ depends on CPU_SUBTYPE_SH7206
+ help
+ Select 7206 SolutionEngine if configuring for a Hitachi SH7206
+ evaluation board.
+
+config SH_7619_SOLUTION_ENGINE
+ bool "SolutionEngine7619"
+ select SOLUTION_ENGINE
+ depends on CPU_SUBTYPE_SH7619
+ help
+ Select 7619 SolutionEngine if configuring for a Hitachi SH7619
+ evaluation board.
+
config SH_7722_SOLUTION_ENGINE
bool "SolutionEngine7722"
select SOLUTION_ENGINE
- select CPU_SUBTYPE_SH7722
+ depends on CPU_SUBTYPE_SH7722
help
Select 7722 SolutionEngine if configuring for a Hitachi SH772
evaluation board.
@@ -106,7 +241,7 @@ config SH_7722_SOLUTION_ENGINE
config SH_7751_SOLUTION_ENGINE
bool "SolutionEngine7751"
select SOLUTION_ENGINE
- select CPU_SUBTYPE_SH7751
+ depends on CPU_SUBTYPE_SH7751
help
Select 7751 SolutionEngine if configuring for a Hitachi SH7751
evaluation board.
@@ -114,7 +249,8 @@ config SH_7751_SOLUTION_ENGINE
config SH_7780_SOLUTION_ENGINE
bool "SolutionEngine7780"
select SOLUTION_ENGINE
- select CPU_SUBTYPE_SH7780
+ select SYS_SUPPORTS_PCI
+ depends on CPU_SUBTYPE_SH7780
help
Select 7780 SolutionEngine if configuring for a Renesas SH7780
evaluation board.
@@ -122,7 +258,7 @@ config SH_7780_SOLUTION_ENGINE
config SH_7300_SOLUTION_ENGINE
bool "SolutionEngine7300"
select SOLUTION_ENGINE
- select CPU_SUBTYPE_SH7300
+ depends on CPU_SUBTYPE_SH7300
help
Select 7300 SolutionEngine if configuring for a Hitachi
SH7300(SH-Mobile V) evaluation board.
@@ -130,22 +266,22 @@ config SH_7300_SOLUTION_ENGINE
config SH_7343_SOLUTION_ENGINE
bool "SolutionEngine7343"
select SOLUTION_ENGINE
- select CPU_SUBTYPE_SH7343
+ depends on CPU_SUBTYPE_SH7343
help
Select 7343 SolutionEngine if configuring for a Hitachi
SH7343 (SH-Mobile 3AS) evaluation board.
config SH_73180_SOLUTION_ENGINE
- bool "SolutionEngine73180"
+ bool "SolutionEngine73180"
select SOLUTION_ENGINE
- select CPU_SUBTYPE_SH73180
+ depends on CPU_SUBTYPE_SH73180
help
Select 73180 SolutionEngine if configuring for a Hitachi
SH73180(SH-Mobile 3) evaluation board.
config SH_7751_SYSTEMH
bool "SystemH7751R"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
help
Select SystemH if you are configuring for a Renesas SystemH
7751R evaluation board.
@@ -153,20 +289,17 @@ config SH_7751_SYSTEMH
config SH_HP6XX
bool "HP6XX"
select SYS_SUPPORTS_APM_EMULATION
+ select HD6446X_SERIES
+ depends on CPU_SUBTYPE_SH7709
help
Select HP6XX if configuring for a HP jornada HP6xx.
More information (hardware only) at
<http://www.hp.com/jornada/>.
-config SH_SATURN
- bool "Saturn"
- select CPU_SUBTYPE_SH7604
- help
- Select Saturn if configuring for a SEGA Saturn.
-
config SH_DREAMCAST
bool "Dreamcast"
- select CPU_SUBTYPE_SH7091
+ select SYS_SUPPORTS_PCI
+ depends on CPU_SUBTYPE_SH7091
help
Select Dreamcast if configuring for a SEGA Dreamcast.
More information at
@@ -175,6 +308,7 @@ config SH_DREAMCAST
config SH_MPC1211
bool "Interface MPC1211"
+ depends on CPU_SUBTYPE_SH7751 && BROKEN
help
CTP/PCI-SH02 is a CPU module computer that is produced
by Interface Corporation.
@@ -182,6 +316,8 @@ config SH_MPC1211
config SH_SH03
bool "Interface CTP/PCI-SH03"
+ depends on CPU_SUBTYPE_SH7751 && BROKEN
+ select SYS_SUPPORTS_PCI
help
CTP/PCI-SH03 is a CPU module computer that is produced
by Interface Corporation.
@@ -189,7 +325,8 @@ config SH_SH03
config SH_SECUREEDGE5410
bool "SecureEdge5410"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
+ select SYS_SUPPORTS_PCI
help
Select SecureEdge5410 if configuring for a SnapGear SH board.
This includes both the OEM SecureEdge products as well as the
@@ -197,246 +334,76 @@ config SH_SECUREEDGE5410
config SH_HS7751RVOIP
bool "HS7751RVOIP"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
help
Select HS7751RVOIP if configuring for a Renesas Technology
Sales VoIP board.
config SH_7710VOIPGW
bool "SH7710-VOIP-GW"
- select CPU_SUBTYPE_SH7710
+ depends on CPU_SUBTYPE_SH7710
help
Select this option to build a kernel for the SH7710 based
VOIP GW.
config SH_RTS7751R2D
bool "RTS7751R2D"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
+ select SYS_SUPPORTS_PCI
help
Select RTS7751R2D if configuring for a Renesas Technology
Sales SH-Graphics board.
config SH_HIGHLANDER
bool "Highlander"
+ depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
+ select SYS_SUPPORTS_PCI
config SH_EDOSK7705
bool "EDOSK7705"
- select CPU_SUBTYPE_SH7705
+ depends on CPU_SUBTYPE_SH7705
config SH_SH4202_MICRODEV
bool "SH4-202 MicroDev"
- select CPU_SUBTYPE_SH4_202
+ depends on CPU_SUBTYPE_SH4_202
help
Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
with an SH4-202 CPU.
config SH_LANDISK
bool "LANDISK"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
+ select SYS_SUPPORTS_PCI
help
I-O DATA DEVICE, INC. "LANDISK Series" support.
config SH_TITAN
bool "TITAN"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
+ select SYS_SUPPORTS_PCI
help
Select Titan if you are configuring for a Nimble Microsystems
NetEngine NP51R.
config SH_SHMIN
bool "SHMIN"
- select CPU_SUBTYPE_SH7706
+ depends on CPU_SUBTYPE_SH7706
help
Select SHMIN if configuring for the SHMIN board.
-config SH_7206_SOLUTION_ENGINE
- bool "SolutionEngine7206"
- select CPU_SUBTYPE_SH7206
- help
- Select 7206 SolutionEngine if configuring for a Hitachi SH7206
- evaluation board.
-
-config SH_7619_SOLUTION_ENGINE
- bool "SolutionEngine7619"
- select CPU_SUBTYPE_SH7619
- help
- Select 7619 SolutionEngine if configuring for a Hitachi SH7619
- evaluation board.
-
config SH_LBOX_RE2
bool "L-BOX RE2"
- select CPU_SUBTYPE_SH7751R
+ depends on CPU_SUBTYPE_SH7751R
+ select SYS_SUPPORTS_PCI
help
Select L-BOX RE2 if configuring for the NTT COMWARE L-BOX RE2.
-config SH_UNKNOWN
- bool "BareCPU"
- help
- "Bare CPU" aka "unknown" means an SH-based system which is not one
- of the specific ones mentioned above, which means you need to enter
- all sorts of stuff like CONFIG_MEMORY_START because the config
- system doesn't already know what it is. You get a machine vector
- without any platform-specific code in it, so things like the RTC may
- not work.
-
- This option is for the early stages of porting to a new machine.
-
-endchoice
+endmenu
source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
source "arch/sh/boards/renesas/r7780rp/Kconfig"
-source "arch/sh/mm/Kconfig"
-
-config CF_ENABLER
- bool "Compact Flash Enabler support"
- depends on SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_SH03
- ---help---
- Compact Flash is a small, removable mass storage device introduced
- in 1994 originally as a PCMCIA device. If you say `Y' here, you
- compile in support for Compact Flash devices directly connected to
- a SuperH processor. A Compact Flash FAQ is available at
- <http://www.compactflash.org/faqs/faq.htm>.
-
- If your board has "Directly Connected" CompactFlash at area 5 or 6,
- you may want to enable this option. Then, you can use CF as
- primary IDE drive (only tested for SanDisk).
-
- If in doubt, select 'N'.
-
-choice
- prompt "Compact Flash Connection Area"
- depends on CF_ENABLER
- default CF_AREA6
-
-config CF_AREA5
- bool "Area5"
- help
- If your board has "Directly Connected" CompactFlash, You should
- select the area where your CF is connected to.
-
- - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
- - "Area6" if it is connected to Area 6 (0x18000000)
-
- "Area6" will work for most boards.
-
-config CF_AREA6
- bool "Area6"
-
-endchoice
-
-config CF_BASE_ADDR
- hex
- depends on CF_ENABLER
- default "0xb8000000" if CF_AREA6
- default "0xb4000000" if CF_AREA5
-
-menu "Processor features"
-
-choice
- prompt "Endianess selection"
- default CPU_LITTLE_ENDIAN
- help
- Some SuperH machines can be configured for either little or big
- endian byte order. These modes require different kernels.
-
-config CPU_LITTLE_ENDIAN
- bool "Little Endian"
-
-config CPU_BIG_ENDIAN
- bool "Big Endian"
-
-endchoice
-
-config SH_FPU
- bool "FPU support"
- depends on !CPU_SH3
- default y
- help
- Selecting this option will enable support for SH processors that
- have FPU units (ie, SH77xx).
-
- This option must be set in order to enable the FPU.
-
-config SH_FPU_EMU
- bool "FPU emulation support"
- depends on !SH_FPU && EXPERIMENTAL
- default n
- help
- Selecting this option will enable support for software FPU emulation.
- Most SH-3 users will want to say Y here, whereas most SH-4 users will
- want to say N.
-
-config SH_DSP
- bool "DSP support"
- default y if SH4AL_DSP || !CPU_SH4
- default n
- help
- Selecting this option will enable support for SH processors that
- have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP).
-
- This option must be set in order to enable the DSP.
-
-config SH_ADC
- bool "ADC support"
- depends on CPU_SH3
- default y
- help
- Selecting this option will allow the Linux kernel to use SH3 on-chip
- ADC module.
-
- If unsure, say N.
-
-config SH_STORE_QUEUES
- bool "Support for Store Queues"
- depends on CPU_SH4
- help
- Selecting this option will enable an in-kernel API for manipulating
- the store queues integrated in the SH-4 processors.
-
-config SPECULATIVE_EXECUTION
- bool "Speculative subroutine return"
- depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL
- help
- This enables support for a speculative instruction fetch for
- subroutine return. There are various pitfalls associated with
- this, as outlined in the SH7780 hardware manual.
-
- If unsure, say N.
-
-config CPU_HAS_INTEVT
- bool
-
-config CPU_HAS_PINT_IRQ
- bool
-
-config CPU_HAS_MASKREG_IRQ
- bool
-
-config CPU_HAS_INTC2_IRQ
- bool
-
-config CPU_HAS_IPR_IRQ
- bool
-
-config CPU_HAS_SR_RB
- bool "CPU has SR.RB"
- depends on CPU_SH3 || CPU_SH4
- default y
- help
- This will enable the use of SR.RB register bank usage. Processors
- that are lacking this bit must have another method in place for
- accomplishing what is taken care of by the banked registers.
-
- See <file:Documentation/sh/register-banks.txt> for further
- information on SR.RB and register banking in the kernel in general.
-
-config CPU_HAS_PTEA
- bool
-
-endmenu
-
menu "Timer and clock configuration"
config SH_TMU
@@ -473,13 +440,13 @@ config SH_PCLK_FREQ
int "Peripheral clock frequency (in Hz)"
default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
default "31250000" if CPU_SUBTYPE_SH7619
+ default "32000000" if CPU_SUBTYPE_SH7722
default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
CPU_SUBTYPE_SH7206
- default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 || \
- CPU_SUBTYPE_SH7785
- default "60000000" if CPU_SUBTYPE_SH7751
+ default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
default "66000000" if CPU_SUBTYPE_SH4_202
+ default "50000000"
help
This option is used to specify the peripheral clock frequency.
This is necessary for determining the reference clock value on
@@ -487,8 +454,10 @@ config SH_PCLK_FREQ
config SH_CLK_MD
int "CPU Mode Pin Setting"
- default 0
depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
+ default 6 if CPU_SUBTYPE_SH7206
+ default 5 if CPU_SUBTYPE_SH7619
+ default 0
help
MD2 - MD0 pin setting.
@@ -560,6 +529,7 @@ config CRASH_DUMP
config SMP
bool "Symmetric multi-processing support"
+ depends on SYS_SUPPORTS_SMP
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
@@ -584,6 +554,7 @@ config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
depends on SMP
+ default "4" if CPU_SHX3
default "2"
help
This allows you to specify the maximum number of CPUs which this
@@ -623,6 +594,7 @@ config BOOT_LINK_OFFSET
config UBC_WAKEUP
bool "Wakeup UBC on startup"
+ depends on CPU_SH4
help
Selecting this option will wakeup the User Break Controller (UBC) on
startup. Although the UBC is left in an awake state when the processor
@@ -651,8 +623,8 @@ menu "Bus options"
# we're not using PCMCIA, so we make it dependent on
# PCMCIA outright. -- PFM.
config ISA
- bool
- default y if PCMCIA
+ def_bool y
+ depends on PCMCIA && HD6446X_SERIES
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -690,6 +662,49 @@ config SUPERHYWAY
tristate "SuperHyway Bus support"
depends on CPU_SUBTYPE_SH4_202
+config CF_ENABLER
+ bool "Compact Flash Enabler support"
+ depends on SOLUTION_ENGINE || SH_SH03
+ ---help---
+ Compact Flash is a small, removable mass storage device introduced
+ in 1994 originally as a PCMCIA device. If you say `Y' here, you
+ compile in support for Compact Flash devices directly connected to
+ a SuperH processor. A Compact Flash FAQ is available at
+ <http://www.compactflash.org/faqs/faq.htm>.
+
+ If your board has "Directly Connected" CompactFlash at area 5 or 6,
+ you may want to enable this option. Then, you can use CF as
+ primary IDE drive (only tested for SanDisk).
+
+ If in doubt, select 'N'.
+
+choice
+ prompt "Compact Flash Connection Area"
+ depends on CF_ENABLER
+ default CF_AREA6
+
+config CF_AREA5
+ bool "Area5"
+ help
+ If your board has "Directly Connected" CompactFlash, You should
+ select the area where your CF is connected to.
+
+ - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
+ - "Area6" if it is connected to Area 6 (0x18000000)
+
+ "Area6" will work for most boards.
+
+config CF_AREA6
+ bool "Area6"
+
+endchoice
+
+config CF_BASE_ADDR
+ hex
+ depends on CF_ENABLER
+ default "0xb8000000" if CF_AREA6
+ default "0xb4000000" if CF_AREA5
+
source "arch/sh/drivers/pci/Kconfig"
source "drivers/pci/Kconfig"
@@ -707,7 +722,7 @@ source "fs/Kconfig.binfmt"
endmenu
menu "Power management options (EXPERIMENTAL)"
-depends on EXPERIMENTAL
+depends on EXPERIMENTAL && SYS_SUPPORTS_PM
source kernel/power/Kconfig
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index b56307294b67..52f6a99c8ecc 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -52,6 +52,10 @@ config EARLY_PRINTK
select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
the kernel command line option to toggle back and forth.
+config DEBUG_BOOTMEM
+ depends on DEBUG_KERNEL
+ bool "Debug BOOTMEM initialization"
+
config DEBUG_STACKOVERFLOW
bool "Check for stack overflows"
depends on DEBUG_KERNEL
@@ -82,6 +86,7 @@ config SH_KGDB
bool "Include KGDB kernel debugger"
select FRAME_POINTER
select DEBUG_INFO
+ depends on CPU_SH3 || CPU_SH4
help
Include in-kernel hooks for kgdb, the Linux kernel source level
debugger. See <http://kgdb.sourceforge.net/> for more information.
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 883b03b040c4..77fecc62a056 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -34,20 +34,20 @@ isa-y := $(isa-y)-nofpu
endif
endif
-cflags-$(CONFIG_CPU_SH2) := -m2
-cflags-$(CONFIG_CPU_SH2A) := -m2a $(call cc-option,-m2a-nofpu,)
-cflags-$(CONFIG_CPU_SH3) := -m3
-cflags-$(CONFIG_CPU_SH4) := -m4 \
+cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,)
+cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \
+ $(call cc-option,-m2a-nofpu,)
+cflags-$(CONFIG_CPU_SH3) := $(call cc-option,-m3,)
+cflags-$(CONFIG_CPU_SH4) := $(call cc-option,-m4,) \
$(call cc-option,-mno-implicit-fp,-m4-nofpu)
-cflags-$(CONFIG_CPU_SH4A) := $(call cc-option,-m4a,) $(call cc-option,-m4a-nofpu,)
+cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a,) \
+ $(call cc-option,-m4a-nofpu,)
cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding
-cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
-
cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \
$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
@@ -87,39 +87,37 @@ core-y += arch/sh/kernel/ arch/sh/mm/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
# Boards
-machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x
-machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE) := se/7722
-machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751
-machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE) := se/7780
-machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300
-machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE) := se/7343
-machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180
-machdir-$(CONFIG_SH_HP6XX) := hp6xx
-machdir-$(CONFIG_SH_SATURN) := saturn
-machdir-$(CONFIG_SH_DREAMCAST) := dreamcast
-machdir-$(CONFIG_SH_MPC1211) := mpc1211
-machdir-$(CONFIG_SH_SH03) := sh03
-machdir-$(CONFIG_SH_SECUREEDGE5410) := snapgear
-machdir-$(CONFIG_SH_HS7751RVOIP) := renesas/hs7751rvoip
-machdir-$(CONFIG_SH_RTS7751R2D) := renesas/rts7751r2d
-machdir-$(CONFIG_SH_7751_SYSTEMH) := renesas/systemh
-machdir-$(CONFIG_SH_EDOSK7705) := renesas/edosk7705
-machdir-$(CONFIG_SH_HIGHLANDER) := renesas/r7780rp
-machdir-$(CONFIG_SH_7710VOIPGW) := renesas/sh7710voipgw
-machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
-machdir-$(CONFIG_SH_LANDISK) := landisk
-machdir-$(CONFIG_SH_TITAN) := titan
-machdir-$(CONFIG_SH_SHMIN) := shmin
-machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206
-machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619
-machdir-$(CONFIG_SH_LBOX_RE2) := lboxre2
-machdir-$(CONFIG_SH_UNKNOWN) := unknown
-
-incdir-y := $(notdir $(machdir-y))
-incdir-$(CONFIG_SH_HP6XX) := hp6xx
+machdir-$(CONFIG_SH_SOLUTION_ENGINE) += se/770x
+machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE) += se/7722
+machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) += se/7751
+machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE) += se/7780
+machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) += se/7300
+machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE) += se/7343
+machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) += se/73180
+machdir-$(CONFIG_SH_HP6XX) += hp6xx
+machdir-$(CONFIG_SH_DREAMCAST) += dreamcast
+machdir-$(CONFIG_SH_MPC1211) += mpc1211
+machdir-$(CONFIG_SH_SH03) += sh03
+machdir-$(CONFIG_SH_SECUREEDGE5410) += snapgear
+machdir-$(CONFIG_SH_HS7751RVOIP) += renesas/hs7751rvoip
+machdir-$(CONFIG_SH_RTS7751R2D) += renesas/rts7751r2d
+machdir-$(CONFIG_SH_7751_SYSTEMH) += renesas/systemh
+machdir-$(CONFIG_SH_EDOSK7705) += renesas/edosk7705
+machdir-$(CONFIG_SH_HIGHLANDER) += renesas/r7780rp
+machdir-$(CONFIG_SH_7710VOIPGW) += renesas/sh7710voipgw
+machdir-$(CONFIG_SH_SH4202_MICRODEV) += superh/microdev
+machdir-$(CONFIG_SH_LANDISK) += landisk
+machdir-$(CONFIG_SH_TITAN) += titan
+machdir-$(CONFIG_SH_SHMIN) += shmin
+machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) += se/7206
+machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) += se/7619
+machdir-$(CONFIG_SH_LBOX_RE2) += lboxre2
+
+incdir-y := $(notdir $(machdir-y))
ifneq ($(machdir-y),)
-core-y += arch/sh/boards/$(machdir-y)/
+core-y += $(addprefix arch/sh/boards/, \
+ $(filter-out ., $(patsubst %,%/,$(machdir-y))))
endif
# Companion chips
@@ -157,19 +155,31 @@ include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) \
# Most boards have their own mach directories. For the ones that
# don't, just reference the parent directory so the semantics are
# kept roughly the same.
+#
+# When multiple boards are compiled in at the same time, preference
+# for the mach link is given to whichever has a directory for its
+# headers. However, this is only a workaround until platforms that
+# can live in the same kernel image back away from relying on the
+# mach link.
include/asm-sh/.mach: $(wildcard include/config/sh/*.h) \
include/config/auto.conf FORCE
- @echo -n ' SYMLINK include/asm-sh/mach -> '
$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
- $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
- echo -e 'include/asm-sh/$(incdir-y)'; \
- ln -fsn $(incdir-prefix)$(incdir-y) \
+ $(Q)rm -f include/asm-sh/mach
+ $(Q)for i in $(incdir-y); do \
+ if [ -d $(incdir-prefix)$$i ]; then \
+ echo -n ' SYMLINK include/asm-sh/mach -> '; \
+ echo -e "include/asm-sh/$$i"; \
+ ln -fsn $(incdir-prefix)$$i \
include/asm-sh/mach; \
else \
- echo -e 'include/asm-sh'; \
- ln -fsn $(incdir-prefix) include/asm-sh/mach; \
- fi
+ if [ ! -d include/asm-sh/mach ]; then \
+ echo -n ' SYMLINK include/asm-sh/mach -> '; \
+ echo -e 'include/asm-sh'; \
+ ln -fsn $(incdir-prefix) include/asm-sh/mach; \
+ fi; \
+ fi; \
+ done
@touch $@
archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools
@@ -188,7 +198,9 @@ compressed: zImage
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-CLEAN_FILES += include/asm-sh/machtypes.h
+CLEAN_FILES += include/asm-sh/machtypes.h \
+ include/asm-sh/cpu include/asm-sh/.cpu \
+ include/asm-sh/mach include/asm-sh/.mach
define archhelp
@echo '* zImage - Compressed kernel image'
diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c
index f13017eeeb27..8799df6e866a 100644
--- a/arch/sh/boards/dreamcast/setup.c
+++ b/arch/sh/boards/dreamcast/setup.c
@@ -60,7 +60,7 @@ static void __init dreamcast_setup(char **cmdline_p)
#endif
}
-struct sh_machine_vector mv_dreamcast __initmv = {
+static struct sh_machine_vector mv_dreamcast __initmv = {
.mv_name = "Sega Dreamcast",
.mv_setup = dreamcast_setup,
.mv_irq_demux = systemasic_irq_demux,
@@ -70,4 +70,3 @@ struct sh_machine_vector mv_dreamcast __initmv = {
.mv_consistent_free = dreamcast_consistent_free,
#endif
};
-ALIAS_MV(dreamcast)
diff --git a/arch/sh/boards/hp6xx/mach.c b/arch/sh/boards/hp6xx/mach.c
deleted file mode 100644
index 08dbba910f74..000000000000
--- a/arch/sh/boards/hp6xx/mach.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/sh/boards/hp6xx/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the HP680
- */
-#include <asm/machvec.h>
-#include <asm/hd64461.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-struct sh_machine_vector mv_hp6xx __initmv = {
- .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
-
- .mv_inb = hd64461_inb,
- .mv_inw = hd64461_inw,
- .mv_inl = hd64461_inl,
- .mv_outb = hd64461_outb,
- .mv_outw = hd64461_outw,
- .mv_outl = hd64461_outl,
-
- .mv_inb_p = hd64461_inb_p,
- .mv_inw_p = hd64461_inw,
- .mv_inl_p = hd64461_inl,
- .mv_outb_p = hd64461_outb_p,
- .mv_outw_p = hd64461_outw,
- .mv_outl_p = hd64461_outl,
-
- .mv_insb = hd64461_insb,
- .mv_insw = hd64461_insw,
- .mv_insl = hd64461_insl,
- .mv_outsb = hd64461_outsb,
- .mv_outsw = hd64461_outsw,
- .mv_outsl = hd64461_outsl,
-
- .mv_readw = hd64461_readw,
- .mv_writew = hd64461_writew,
-
- .mv_irq_demux = hd64461_irq_demux,
-};
-
-ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 6aeee85c9785..7ae708930bac 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -98,10 +98,9 @@ static void __init hp6xx_setup(char **cmdline_p)
}
device_initcall(hp6xx_devices_setup);
-struct sh_machine_vector mv_hp6xx __initmv = {
+static struct sh_machine_vector mv_hp6xx __initmv = {
.mv_name = "hp6xx",
.mv_setup = hp6xx_setup,
.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
.mv_irq_demux = hd64461_irq_demux,
};
-ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index f953c7427769..eda71763ecc5 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -97,10 +97,9 @@ static void __init landisk_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_landisk __initmv = {
+static struct sh_machine_vector mv_landisk __initmv = {
.mv_name = "LANDISK",
.mv_nr_irqs = 72,
.mv_setup = landisk_setup,
.mv_init_irq = init_landisk_IRQ,
};
-ALIAS_MV(landisk)
diff --git a/arch/sh/boards/lboxre2/setup.c b/arch/sh/boards/lboxre2/setup.c
index 4e20f7c63bf3..9c830fdc411b 100644
--- a/arch/sh/boards/lboxre2/setup.c
+++ b/arch/sh/boards/lboxre2/setup.c
@@ -77,9 +77,8 @@ device_initcall(lboxre2_devices_setup);
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_lboxre2 __initmv = {
+static struct sh_machine_vector mv_lboxre2 __initmv = {
.mv_name = "L-BOX RE2",
.mv_nr_irqs = 72,
.mv_init_irq = init_lboxre2_IRQ,
};
-ALIAS_MV(lboxre2)
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 1a0604b23ce0..8ce03e00b0ae 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -338,11 +338,10 @@ static void __init mpc1211_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_mpc1211 __initmv = {
+static struct sh_machine_vector mv_mpc1211 __initmv = {
.mv_name = "Interface MPC-1211(CTP/PCI/MPC-SH02)",
.mv_setup = mpc1211_setup,
.mv_nr_irqs = 48,
.mv_irq_demux = mpc1211_irq_demux,
.mv_init_irq = init_mpc1211_IRQ,
};
-ALIAS_MV(mpc1211)
diff --git a/arch/sh/boards/renesas/edosk7705/setup.c b/arch/sh/boards/renesas/edosk7705/setup.c
index ec5be0107719..f076c45308dd 100644
--- a/arch/sh/boards/renesas/edosk7705/setup.c
+++ b/arch/sh/boards/renesas/edosk7705/setup.c
@@ -21,7 +21,7 @@ static void __init sh_edosk7705_init_irq(void)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_edosk7705 __initmv = {
+static struct sh_machine_vector mv_edosk7705 __initmv = {
.mv_name = "EDOSK7705",
.mv_nr_irqs = 80,
@@ -41,4 +41,3 @@ struct sh_machine_vector mv_edosk7705 __initmv = {
.mv_isa_port2addr = sh_edosk7705_isa_port2addr,
.mv_init_irq = sh_edosk7705_init_irq,
};
-ALIAS_MV(edosk7705)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
index f7d0e304d899..fa5fa3920222 100644
--- a/arch/sh/boards/renesas/hs7751rvoip/setup.c
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -89,7 +89,7 @@ static void __init hs7751rvoip_setup(char **cmdline_p)
printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
}
-struct sh_machine_vector mv_hs7751rvoip __initmv = {
+static struct sh_machine_vector mv_hs7751rvoip __initmv = {
.mv_name = "HS7751RVoIP",
.mv_setup = hs7751rvoip_setup,
.mv_nr_irqs = 72,
@@ -118,4 +118,3 @@ struct sh_machine_vector mv_hs7751rvoip __initmv = {
.mv_init_irq = hs7751rvoip_init_irq,
.mv_ioport_map = hs7751rvoip_ioport_map,
};
-ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/r7780rp/Kconfig b/arch/sh/boards/renesas/r7780rp/Kconfig
index 9fb11641fe13..fc8f28e04ba3 100644
--- a/arch/sh/boards/renesas/r7780rp/Kconfig
+++ b/arch/sh/boards/renesas/r7780rp/Kconfig
@@ -6,18 +6,18 @@ choice
config SH_R7780RP
bool "R7780RP-1 board support"
- select CPU_SUBTYPE_SH7780
+ depends on CPU_SUBTYPE_SH7780
config SH_R7780MP
bool "R7780MP board support"
- select CPU_SUBTYPE_SH7780
+ depends on CPU_SUBTYPE_SH7780
help
Selecting this option will enable support for the mass-production
version of the R7780RP. If in doubt, say Y.
config SH_R7785RP
bool "R7785RP board support"
- select CPU_SUBTYPE_SH7785
+ depends on CPU_SUBTYPE_SH7785
endchoice
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index 0727ef92f2b3..5afb864a1ec5 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -166,10 +166,9 @@ static void __init highlander_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_highlander __initmv = {
+static struct sh_machine_vector mv_highlander __initmv = {
.mv_name = "Highlander",
.mv_nr_irqs = 109,
.mv_setup = highlander_setup,
.mv_init_irq = highlander_init_irq,
};
-ALIAS_MV(highlander)
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 593f26a85e9c..656fda30ef70 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -176,7 +176,7 @@ static void __init rts7751r2d_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_rts7751r2d __initmv = {
+static struct sh_machine_vector mv_rts7751r2d __initmv = {
.mv_name = "RTS7751R2D",
.mv_setup = rts7751r2d_setup,
.mv_nr_irqs = 72,
@@ -189,4 +189,3 @@ struct sh_machine_vector mv_rts7751r2d __initmv = {
.mv_consistent_free = voyagergx_consistent_free,
#endif
};
-ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
index 180810b12107..2dce8bd97f90 100644
--- a/arch/sh/boards/renesas/sh7710voipgw/setup.c
+++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c
@@ -88,9 +88,8 @@ static void __init sh7710voipgw_init_irq(void)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_sh7710voipgw __initmv = {
+static struct sh_machine_vector mv_sh7710voipgw __initmv = {
.mv_name = "SH7710 VoIP Gateway",
.mv_nr_irqs = 104,
.mv_init_irq = sh7710voipgw_init_irq,
};
-ALIAS_MV(sh7710voipgw)
diff --git a/arch/sh/boards/renesas/systemh/setup.c b/arch/sh/boards/renesas/systemh/setup.c
index 936117659b74..ee78af842778 100644
--- a/arch/sh/boards/renesas/systemh/setup.c
+++ b/arch/sh/boards/renesas/systemh/setup.c
@@ -28,7 +28,7 @@ static void __init sh7751systemh_init_irq(void)
make_systemh_irq(0xb); /* Ethernet interrupt */
}
-struct sh_machine_vector mv_7751systemh __initmv = {
+static struct sh_machine_vector mv_7751systemh __initmv = {
.mv_name = "7751 SystemH",
.mv_nr_irqs = 72,
@@ -55,4 +55,3 @@ struct sh_machine_vector mv_7751systemh __initmv = {
.mv_init_irq = sh7751systemh_init_irq,
};
-ALIAS_MV(7751systemh)
diff --git a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile
deleted file mode 100644
index 75a3042e252e..000000000000
--- a/arch/sh/boards/saturn/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Sega Saturn specific parts of the kernel
-#
-
-obj-y := setup.o io.o irq.o
-
-obj-$(CONFIG_SMP) += smp.o
-
diff --git a/arch/sh/boards/saturn/io.c b/arch/sh/boards/saturn/io.c
deleted file mode 100644
index c6e4f7f2e686..000000000000
--- a/arch/sh/boards/saturn/io.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/sh/boards/saturn/io.c
- *
- * I/O routines for the Sega Saturn.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <asm/saturn/io.h>
-#include <asm/machvec.h>
-
-unsigned long saturn_isa_port2addr(unsigned long offset)
-{
- return offset;
-}
-
-void *saturn_ioremap(unsigned long offset, unsigned long size)
-{
- return (void *)offset;
-}
-
-void saturn_iounmap(void *addr)
-{
-}
-
diff --git a/arch/sh/boards/saturn/irq.c b/arch/sh/boards/saturn/irq.c
deleted file mode 100644
index 15d1d3f0f787..000000000000
--- a/arch/sh/boards/saturn/irq.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * arch/sh/boards/saturn/irq.c
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-/*
- * Interrupts map out as follows:
- *
- * Vector Name Mask
- *
- * 64 VBLANKIN 0x0001
- * 65 VBLANKOUT 0x0002
- * 66 HBLANKIN 0x0004
- * 67 TIMER0 0x0008
- * 68 TIMER1 0x0010
- * 69 DSPEND 0x0020
- * 70 SOUNDREQUEST 0x0040
- * 71 SYSTEMMANAGER 0x0080
- * 72 PAD 0x0100
- * 73 LEVEL2DMAEND 0x0200
- * 74 LEVEL1DMAEND 0x0400
- * 75 LEVEL0DMAEND 0x0800
- * 76 DMAILLEGAL 0x1000
- * 77 SRITEDRAWEND 0x2000
- * 78 ABUS 0x8000
- *
- */
-#define SATURN_IRQ_MIN 64 /* VBLANKIN */
-#define SATURN_IRQ_MAX 78 /* ABUS */
-
-#define SATURN_IRQ_MASK 0xbfff
-
-static inline u32 saturn_irq_mask(unsigned int irq_nr)
-{
- u32 mask;
-
- mask = (1 << (irq_nr - SATURN_IRQ_MIN));
- mask <<= (irq_nr == SATURN_IRQ_MAX);
- mask &= SATURN_IRQ_MASK;
-
- return mask;
-}
-
-static inline void mask_saturn_irq(unsigned int irq_nr)
-{
- u32 mask;
-
- mask = ctrl_inl(SATURN_IMR);
- mask |= saturn_irq_mask(irq_nr);
- ctrl_outl(mask, SATURN_IMR);
-}
-
-static inline void unmask_saturn_irq(unsigned int irq_nr)
-{
- u32 mask;
-
- mask = ctrl_inl(SATURN_IMR);
- mask &= ~saturn_irq_mask(irq_nr);
- ctrl_outl(mask, SATURN_IMR);
-}
-
-static void disable_saturn_irq(unsigned int irq_nr)
-{
- mask_saturn_irq(irq_nr);
-}
-
-static void enable_saturn_irq(unsigned int irq_nr)
-{
- unmask_saturn_irq(irq_nr);
-}
-
-static void mask_and_ack_saturn_irq(unsigned int irq_nr)
-{
- mask_saturn_irq(irq_nr);
-}
-
-static void end_saturn_irq(unsigned int irq_nr)
-{
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- unmask_saturn_irq(irq_nr);
-}
-
-static unsigned int startup_saturn_irq(unsigned int irq_nr)
-{
- unmask_saturn_irq(irq_nr);
-
- return 0;
-}
-
-static void shutdown_saturn_irq(unsigned int irq_nr)
-{
- mask_saturn_irq(irq_nr);
-}
-
-static struct hw_interrupt_type saturn_int = {
- .typename = "Saturn",
- .enable = enable_saturn_irq,
- .disable = disable_saturn_irq,
- .ack = mask_and_ack_saturn_irq,
- .end = end_saturn_irq,
- .startup = startup_saturn_irq,
- .shutdown = shutdown_saturn_irq,
-};
-
-int saturn_irq_demux(int irq_nr)
-{
- /* FIXME */
- return irq_nr;
-}
-
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
deleted file mode 100644
index a3a37c9aad2e..000000000000
--- a/arch/sh/boards/saturn/setup.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/sh/boards/saturn/setup.c
- *
- * Hardware support for the Sega Saturn.
- *
- * Copyright (c) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/io.h>
-
-extern int saturn_irq_demux(int irq_nr);
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_saturn __initmv = {
- .mv_name = "Sega Saturn",
- .mv_nr_irqs = 80, /* Fix this later */
-
- .mv_isa_port2addr = saturn_isa_port2addr,
- .mv_irq_demux = saturn_irq_demux,
-
- .mv_ioremap = saturn_ioremap,
- .mv_iounmap = saturn_iounmap,
-};
-ALIAS_MV(saturn)
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
deleted file mode 100644
index 76460918c9cd..000000000000
--- a/arch/sh/boards/saturn/smp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/sh/boards/saturn/smp.c
- *
- * SMP support for the Sega Saturn.
- *
- * Copyright (c) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/saturn/smpc.h>
-
-extern void start_secondary(void);
-
-void __smp_send_ipi(unsigned int cpu, unsigned int action)
-{
- /* Nothing here yet .. */
-}
-
-unsigned int __smp_probe_cpus(void)
-{
- /*
- * This is just a straightforward master/slave configuration,
- * and probing isn't really supported..
- */
- return 2;
-}
-
-/*
- * We're only allowed to do byte-access to SMPC registers. In
- * addition to which, we treat them as write-only, since
- * reading from them will return undefined data.
- */
-static inline void smpc_slave_stop(unsigned int cpu)
-{
- smpc_barrier();
- ctrl_outb(1, SMPC_STATUS);
-
- ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
- smpc_barrier();
-}
-
-static inline void smpc_slave_start(unsigned int cpu)
-{
- ctrl_outb(1, SMPC_STATUS);
- ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
-
- smpc_barrier();
-}
-
-void __smp_slave_init(unsigned int cpu)
-{
- register unsigned long vbr;
- void **entry;
-
- __asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
- entry = (void **)(vbr + 0x310 + 0x94);
-
- smpc_slave_stop(cpu);
-
- *(void **)entry = (void *)start_secondary;
-
- smpc_slave_start(cpu);
-}
-
diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c
index ca714879f559..a074b62505ef 100644
--- a/arch/sh/boards/se/7206/setup.c
+++ b/arch/sh/boards/se/7206/setup.c
@@ -70,7 +70,7 @@ __initcall(se7206_devices_setup);
* The Machine Vector
*/
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 256,
.mv_inb = se7206_inb,
@@ -96,4 +96,3 @@ struct sh_machine_vector mv_se __initmv = {
.mv_init_irq = init_se7206_IRQ,
};
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
index f1960956bad0..eb469f5b6e97 100644
--- a/arch/sh/boards/se/7300/setup.c
+++ b/arch/sh/boards/se/7300/setup.c
@@ -46,7 +46,7 @@ __initcall(se7300_devices_setup);
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_7300se __initmv = {
+static struct sh_machine_vector mv_7300se __initmv = {
.mv_name = "SolutionEngine 7300",
.mv_nr_irqs = 109,
.mv_inb = sh7300se_inb,
@@ -72,4 +72,3 @@ struct sh_machine_vector mv_7300se __initmv = {
.mv_init_irq = init_7300se_IRQ,
};
-ALIAS_MV(7300se)
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index e143017c8975..1deee8556642 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -46,7 +46,7 @@ __initcall(se73180_devices_setup);
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_73180se __initmv = {
+static struct sh_machine_vector mv_73180se __initmv = {
.mv_name = "SolutionEngine 73180",
.mv_nr_irqs = 108,
.mv_inb = sh73180se_inb,
@@ -73,4 +73,3 @@ struct sh_machine_vector mv_73180se __initmv = {
.mv_init_irq = init_73180se_IRQ,
.mv_irq_demux = shmse_irq_demux,
};
-ALIAS_MV(73180se)
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
index 3fdb16f2cef1..8fec155e2ff7 100644
--- a/arch/sh/boards/se/7343/setup.c
+++ b/arch/sh/boards/se/7343/setup.c
@@ -64,7 +64,7 @@ static void __init sh7343se_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_7343se __initmv = {
+static struct sh_machine_vector mv_7343se __initmv = {
.mv_name = "SolutionEngine 7343",
.mv_setup = sh7343se_setup,
.mv_nr_irqs = 108,
@@ -92,4 +92,3 @@ struct sh_machine_vector mv_7343se __initmv = {
.mv_init_irq = init_7343se_IRQ,
.mv_irq_demux = shmse_irq_demux,
};
-ALIAS_MV(7343se)
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
index 52d2c4d5d2fa..1d0ef7faa10d 100644
--- a/arch/sh/boards/se/7619/setup.c
+++ b/arch/sh/boards/se/7619/setup.c
@@ -15,8 +15,7 @@
* The Machine Vector
*/
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 108,
};
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
index c8eccff77a04..cdb0807928a5 100644
--- a/arch/sh/boards/se/770x/irq.c
+++ b/arch/sh/boards/se/770x/irq.c
@@ -15,46 +15,7 @@
#include <asm/io.h>
#include <asm/se.h>
-/*
- * If the problem of make_ipr_irq is solved,
- * this code will become unnecessary. :-)
- */
-static void se770x_disable_ipr_irq(unsigned int irq)
-{
- struct ipr_data *p = get_irq_chip_data(irq);
-
- ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
-}
-
-static void se770x_enable_ipr_irq(unsigned int irq)
-{
- struct ipr_data *p = get_irq_chip_data(irq);
-
- ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
-}
-
-static struct irq_chip se770x_irq_chip = {
- .name = "MS770xSE-FPGA",
- .mask = se770x_disable_ipr_irq,
- .unmask = se770x_enable_ipr_irq,
- .mask_ack = se770x_disable_ipr_irq,
-};
-
-void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
-{
- int i;
-
- for (i = 0; i < nr_irqs; i++) {
- unsigned int irq = table[i].irq;
- disable_irq_nosync(irq);
- set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
- handle_level_irq, "level");
- set_irq_chip_data(irq, &table[i]);
- se770x_enable_ipr_irq(irq);
- }
-}
-
-static struct ipr_data se770x_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
/*
* Super I/O (Just mimic PC):
* 1: keyboard
@@ -68,46 +29,67 @@ static struct ipr_data se770x_ipr_map[] = {
*/
#if defined(CONFIG_CPU_SUBTYPE_SH7705)
/* This is default value */
- { 13, 0, 8, 0x0f-13 ,BCR_ILCRA},
- { 5 , 0, 4, 0x0f- 5 ,BCR_ILCRA},
- { 10, 0, 0, 0x0f-10, BCR_ILCRB},
- { 7 , 0, 4, 0x0f- 7, BCR_ILCRC},
- { 3 , 0, 0, 0x0f- 3, BCR_ILCRC},
- { 1 , 0, 12, 0x0f- 1, BCR_ILCRD},
- { 12, 0, 4, 0x0f-12, BCR_ILCRD}, /* LAN */
- { 2 , 0, 8, 0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */
- { 6 , 0, 4, 0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */
- { 14, 0, 0, 0x0f-14, BCR_ILCRE}, /* PCIRQ0 */
- { 0 , 0, 12, 0x0f , BCR_ILCRF},
- { 4 , 0, 4, 0x0f- 4, BCR_ILCRF},
- { 8 , 0, 12, 0x0f- 8, BCR_ILCRG},
- { 9 , 0, 8, 0x0f- 9, BCR_ILCRG},
- { 11, 0, 4, 0x0f-11, BCR_ILCRG},
+ { 13, 0, 8, 0x0f-13, },
+ { 5 , 0, 4, 0x0f- 5, },
+ { 10, 1, 0, 0x0f-10, },
+ { 7 , 2, 4, 0x0f- 7, },
+ { 3 , 2, 0, 0x0f- 3, },
+ { 1 , 3, 12, 0x0f- 1, },
+ { 12, 3, 4, 0x0f-12, }, /* LAN */
+ { 2 , 4, 8, 0x0f- 2, }, /* PCIRQ2 */
+ { 6 , 4, 4, 0x0f- 6, }, /* PCIRQ1 */
+ { 14, 4, 0, 0x0f-14, }, /* PCIRQ0 */
+ { 0 , 5, 12, 0x0f , },
+ { 4 , 5, 4, 0x0f- 4, },
+ { 8 , 6, 12, 0x0f- 8, },
+ { 9 , 6, 8, 0x0f- 9, },
+ { 11, 6, 4, 0x0f-11, },
#else
- { 14, 0, 8, 0x0f-14 ,BCR_ILCRA},
- { 12, 0, 4, 0x0f-12 ,BCR_ILCRA},
- { 8, 0, 4, 0x0f- 8 ,BCR_ILCRB},
- { 6, 0, 12, 0x0f- 6 ,BCR_ILCRC},
- { 5, 0, 8, 0x0f- 5 ,BCR_ILCRC},
- { 4, 0, 4, 0x0f- 4 ,BCR_ILCRC},
- { 3, 0, 0, 0x0f- 3 ,BCR_ILCRC},
- { 1, 0, 12, 0x0f- 1 ,BCR_ILCRD},
+ { 14, 0, 8, 0x0f-14, },
+ { 12, 0, 4, 0x0f-12, },
+ { 8, 1, 4, 0x0f- 8, },
+ { 6, 2, 12, 0x0f- 6, },
+ { 5, 2, 8, 0x0f- 5, },
+ { 4, 2, 4, 0x0f- 4, },
+ { 3, 2, 0, 0x0f- 3, },
+ { 1, 3, 12, 0x0f- 1, },
#if defined(CONFIG_STNIC)
/* ST NIC */
- { 10, 0, 4, 0x0f-10 ,BCR_ILCRD}, /* LAN */
+ { 10, 3, 4, 0x0f-10, }, /* LAN */
#endif
/* MRSHPC IRQs setting */
- { 0, 0, 12, 0x0f- 0 ,BCR_ILCRE}, /* PCIRQ3 */
- { 11, 0, 8, 0x0f-11 ,BCR_ILCRE}, /* PCIRQ2 */
- { 9, 0, 4, 0x0f- 9 ,BCR_ILCRE}, /* PCIRQ1 */
- { 7, 0, 0, 0x0f- 7 ,BCR_ILCRE}, /* PCIRQ0 */
+ { 0, 4, 12, 0x0f- 0, }, /* PCIRQ3 */
+ { 11, 4, 8, 0x0f-11, }, /* PCIRQ2 */
+ { 9, 4, 4, 0x0f- 9, }, /* PCIRQ1 */
+ { 7, 4, 0, 0x0f- 7, }, /* PCIRQ0 */
/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
/* NOTE: #2 and #13 are not used on PC */
- { 13, 0, 4, 0x0f-13 ,BCR_ILCRG}, /* SLOTIRQ2 */
- { 2, 0, 0, 0x0f- 2 ,BCR_ILCRG}, /* SLOTIRQ1 */
+ { 13, 6, 4, 0x0f-13, }, /* SLOTIRQ2 */
+ { 2, 6, 0, 0x0f- 2, }, /* SLOTIRQ1 */
#endif
};
+static unsigned long ipr_offsets[] = {
+ BCR_ILCRA,
+ BCR_ILCRB,
+ BCR_ILCRC,
+ BCR_ILCRD,
+ BCR_ILCRE,
+ BCR_ILCRF,
+ BCR_ILCRG,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+ .chip = {
+ .name = "IPR-se770x",
+ },
+};
+
/*
* Initialize IRQ setting
*/
@@ -122,5 +104,5 @@ void __init init_se_IRQ(void)
ctrl_outw(0, BCR_ILCRF);
ctrl_outw(0, BCR_ILCRG);
- make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
index 17a2631de3ba..2962da148f3f 100644
--- a/arch/sh/boards/se/770x/setup.c
+++ b/arch/sh/boards/se/770x/setup.c
@@ -122,7 +122,7 @@ device_initcall(se_devices_setup);
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_se __initmv = {
+static struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_setup = smsc_setup,
#if defined(CONFIG_CPU_SH4)
@@ -160,4 +160,3 @@ struct sh_machine_vector mv_se __initmv = {
.mv_init_irq = init_se_IRQ,
};
-ALIAS_MV(se)
diff --git a/arch/sh/boards/se/7722/irq.c b/arch/sh/boards/se/7722/irq.c
index 099e5deb77f8..26cff0efda40 100644
--- a/arch/sh/boards/se/7722/irq.c
+++ b/arch/sh/boards/se/7722/irq.c
@@ -19,15 +19,24 @@
#define INTC_INTMSK0 0xFFD00044
#define INTC_INTMSKCLR0 0xFFD00064
+struct se7722_data {
+ unsigned char irq;
+ unsigned char ipr_idx;
+ unsigned char shift;
+ unsigned short priority;
+ unsigned long addr;
+};
+
+
static void disable_se7722_irq(unsigned int irq)
{
- struct ipr_data *p = get_irq_chip_data(irq);
+ struct se7722_data *p = get_irq_chip_data(irq);
ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
}
static void enable_se7722_irq(unsigned int irq)
{
- struct ipr_data *p = get_irq_chip_data(irq);
+ struct se7722_data *p = get_irq_chip_data(irq);
ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
}
@@ -38,7 +47,7 @@ static struct irq_chip se7722_irq_chip __read_mostly = {
.mask_ack = disable_se7722_irq,
};
-static struct ipr_data ipr_irq_table[] = {
+static struct se7722_data ipr_irq_table[] = {
/* irq ,idx,sft, priority , addr */
{ MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
{ MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index 636ca6c987e0..6cca6cbc8069 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -137,7 +137,7 @@ static void __init se7722_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_se7722 __initmv = {
+static struct sh_machine_vector mv_se7722 __initmv = {
.mv_name = "Solution Engine 7722" ,
.mv_setup = se7722_setup ,
.mv_nr_irqs = 109 ,
@@ -145,4 +145,3 @@ struct sh_machine_vector mv_se7722 __initmv = {
.mv_irq_demux = se7722_irq_demux,
};
-ALIAS_MV(se7722)
diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c
index e4c63a48296c..c3d12590e5db 100644
--- a/arch/sh/boards/se/7751/irq.c
+++ b/arch/sh/boards/se/7751/irq.c
@@ -14,44 +14,31 @@
#include <asm/irq.h>
#include <asm/se7751.h>
-static struct ipr_data se7751_ipr_map[] = {
- /* Leave old Solution Engine code in for reference. */
-#if defined(CONFIG_SH_SOLUTION_ENGINE)
- /*
- * Super I/O (Just mimic PC):
- * 1: keyboard
- * 3: serial 0
- * 4: serial 1
- * 5: printer
- * 6: floppy
- * 8: rtc
- * 12: mouse
- * 14: ide0
- */
- { 14, BCR_ILCRA, 2, 0x0f-14 },
- { 12, BCR_ILCRA, 1, 0x0f-12 },
- { 8, BCR_ILCRB, 1, 0x0f- 8 },
- { 6, BCR_ILCRC, 3, 0x0f- 6 },
- { 5, BCR_ILCRC, 2, 0x0f- 5 },
- { 4, BCR_ILCRC, 1, 0x0f- 4 },
- { 3, BCR_ILCRC, 0, 0x0f- 3 },
- { 1, BCR_ILCRD, 3, 0x0f- 1 },
+static struct ipr_data ipr_irq_table[] = {
+ { 13, 3, 3, 2 },
+ /* Add additional entries here as drivers are added and tested. */
+};
- { 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */
+static unsigned long ipr_offsets[] = {
+ BCR_ILCRA,
+ BCR_ILCRB,
+ BCR_ILCRC,
+ BCR_ILCRD,
+ BCR_ILCRE,
+ BCR_ILCRF,
+ BCR_ILCRG,
+};
- { 0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */
- { 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */
- { 9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */
- { 7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
- /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
- /* NOTE: #2 and #13 are not used on PC */
- { 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */
- { 2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */
-#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
- { 13, BCR_ILCRD, 3, 2 },
- /* Add additional entries here as drivers are added and tested. */
-#endif
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-se7751",
+ },
};
/*
@@ -59,5 +46,5 @@ static struct ipr_data se7751_ipr_map[] = {
*/
void __init init_7751se_IRQ(void)
{
- make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
index 52c7bfa57c2c..7873d07e40c1 100644
--- a/arch/sh/boards/se/7751/setup.c
+++ b/arch/sh/boards/se/7751/setup.c
@@ -48,7 +48,7 @@ __initcall(se7751_devices_setup);
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_7751se __initmv = {
+static struct sh_machine_vector mv_7751se __initmv = {
.mv_name = "7751 SolutionEngine",
.mv_nr_irqs = 72,
@@ -71,4 +71,3 @@ struct sh_machine_vector mv_7751se __initmv = {
.mv_init_irq = init_7751se_IRQ,
};
-ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7780/irq.c b/arch/sh/boards/se/7780/irq.c
index 3d0625c2d07b..874914746009 100644
--- a/arch/sh/boards/se/7780/irq.c
+++ b/arch/sh/boards/se/7780/irq.c
@@ -16,28 +16,6 @@
#include <asm/io.h>
#include <asm/se7780.h>
-#define INTC_INTMSK0 0xFFD00044
-#define INTC_INTMSKCLR0 0xFFD00064
-
-static void disable_se7780_irq(unsigned int irq)
-{
- struct intc2_data *p = get_irq_chip_data(irq);
- ctrl_outl(1 << p->msk_shift, INTC_INTMSK0 + p->msk_offset);
-}
-
-static void enable_se7780_irq(unsigned int irq)
-{
- struct intc2_data *p = get_irq_chip_data(irq);
- ctrl_outl(1 << p->msk_shift, INTC_INTMSKCLR0 + p->msk_offset);
-}
-
-static struct irq_chip se7780_irq_chip __read_mostly = {
- .name = "SE7780",
- .mask = disable_se7780_irq,
- .unmask = enable_se7780_irq,
- .mask_ack = disable_se7780_irq,
-};
-
static struct intc2_data intc2_irq_table[] = {
{ 2, 0, 31, 0, 31, 3 }, /* daughter board EXTINT1 */
{ 4, 0, 30, 0, 30, 3 }, /* daughter board EXTINT2 */
@@ -51,13 +29,24 @@ static struct intc2_data intc2_irq_table[] = {
{ 0 , 0, 24, 0, 24, 3 }, /* SM501 */
};
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+ .prio_base = 0, /* N/A */
+ .msk_base = 0xffd00044,
+ .mskclr_base = 0xffd00064,
+
+ .intc2_data = intc2_irq_table,
+ .nr_irqs = ARRAY_SIZE(intc2_irq_table),
+
+ .chip = {
+ .name = "INTC2-se7780",
+ },
+};
+
/*
* Initialize IRQ setting
*/
void __init init_se7780_IRQ(void)
{
- int i ;
-
/* enable all interrupt at FPGA */
ctrl_outw(0, FPGA_INTMSK1);
/* mask SM501 interrupt */
@@ -79,11 +68,5 @@ void __init init_se7780_IRQ(void)
/* FPGA + 0x0A */
ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
- for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) {
- disable_irq_nosync(intc2_irq_table[i].irq);
- set_irq_chip_and_handler_name( intc2_irq_table[i].irq, &se7780_irq_chip,
- handle_level_irq, "level");
- set_irq_chip_data( intc2_irq_table[i].irq, &intc2_irq_table[i] );
- disable_se7780_irq(intc2_irq_table[i].irq);
- }
+ register_intc2_controller(&intc2_irq_desc);
}
diff --git a/arch/sh/boards/se/7780/setup.c b/arch/sh/boards/se/7780/setup.c
index df7d08a24c9f..723f2fd4d55b 100644
--- a/arch/sh/boards/se/7780/setup.c
+++ b/arch/sh/boards/se/7780/setup.c
@@ -113,10 +113,9 @@ static void __init se7780_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_se7780 __initmv = {
+static struct sh_machine_vector mv_se7780 __initmv = {
.mv_name = "Solution Engine 7780" ,
.mv_setup = se7780_setup ,
.mv_nr_irqs = 111 ,
.mv_init_irq = init_se7780_IRQ,
};
-ALIAS_MV(se7780)
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
index c069c444b4ec..9c031a8c0a1c 100644
--- a/arch/sh/boards/sh03/setup.c
+++ b/arch/sh/boards/sh03/setup.c
@@ -15,17 +15,33 @@
#include <asm/sh03/sh03.h>
#include <asm/addrspace.h>
-static struct ipr_data sh03_ipr_map[] = {
- { IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY },
- { IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY },
- { IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY },
- { IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY },
+static struct ipr_data ipr_irq_table[] = {
+ { IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
+ { IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
+ { IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
+ { IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
+};
+
+static unsigned long ipr_offsets[] = {
+ INTC_IPRD,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh03",
+ },
};
static void __init init_sh03_IRQ(void)
{
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
- make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
extern void *cf_io_base;
@@ -74,11 +90,10 @@ static int __init sh03_devices_setup(void)
}
__initcall(sh03_devices_setup);
-struct sh_machine_vector mv_sh03 __initmv = {
+static struct sh_machine_vector mv_sh03 __initmv = {
.mv_name = "Interface (CTP/PCI-SH03)",
.mv_setup = sh03_setup,
.mv_nr_irqs = 48,
.mv_ioport_map = sh03_ioport_map,
.mv_init_irq = init_sh03_IRQ,
};
-ALIAS_MV(sh03)
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
index 4a9df4a6b034..dfd124509f42 100644
--- a/arch/sh/boards/shmin/setup.c
+++ b/arch/sh/boards/shmin/setup.c
@@ -6,28 +6,44 @@
* SHMIN Support.
*/
#include <linux/init.h>
+#include <linux/irq.h>
#include <asm/machvec.h>
#include <asm/shmin.h>
#include <asm/clock.h>
-#include <asm/irq.h>
#include <asm/io.h>
#define PFC_PHCR 0xa400010eUL
#define INTC_ICR1 0xa4000010UL
#define INTC_IPRC 0xa4000016UL
-static struct ipr_data shmin_ipr_map[] = {
- { .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 },
- { .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 },
- { .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 },
- { .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 },
+static struct ipr_data ipr_irq_table[] = {
+ { 32, 0, 0, 0 },
+ { 33, 0, 4, 0 },
+ { 34, 0, 8, 8 },
+ { 35, 0, 12, 0 },
+};
+
+static unsigned long ipr_offsets[] = {
+ INTC_IPRC,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-shmin",
+ },
};
static void __init init_shmin_irq(void)
{
ctrl_outw(0x2a00, PFC_PHCR); // IRQ0-3=IRQ
ctrl_outw(0x0aaa, INTC_ICR1); // IRQ0-3=IRQ-mode,Low-active.
- make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
@@ -43,9 +59,8 @@ static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
}
-struct sh_machine_vector mv_shmin __initmv = {
+static struct sh_machine_vector mv_shmin __initmv = {
.mv_name = "SHMIN",
.mv_init_irq = init_shmin_irq,
.mv_ioport_map = shmin_ioport_map,
};
-ALIAS_MV(shmin)
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index 650fb3645947..84271d85a8dd 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -68,11 +68,27 @@ module_init(eraseconfig_init);
* IRL3 = crypto
*/
-static struct ipr_data snapgear_ipr_map[] = {
- make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
- make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
- make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
- make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
+static struct ipr_data ipr_irq_table[] = {
+ { IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
+ { IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
+ { IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
+ { IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
+};
+
+static unsigned long ipr_offsets[] = {
+ INTC_IPRD,
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-snapgear",
+ },
};
static void __init init_snapgear_IRQ(void)
@@ -82,7 +98,7 @@ static void __init init_snapgear_IRQ(void)
printk("Setup SnapGear IRQ/IPR ...\n");
- make_ipr_irq(snapgear_ipr_map, ARRAY_SIZE(snapgear_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
/*
@@ -96,7 +112,7 @@ static void __init snapgear_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_snapgear __initmv = {
+static struct sh_machine_vector mv_snapgear __initmv = {
.mv_name = "SnapGear SecureEdge5410",
.mv_setup = snapgear_setup,
.mv_nr_irqs = 72,
@@ -117,4 +133,3 @@ struct sh_machine_vector mv_snapgear __initmv = {
.mv_init_irq = init_snapgear_IRQ,
};
-ALIAS_MV(snapgear)
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
index 6396cea1c896..fc8cd06d66cf 100644
--- a/arch/sh/boards/superh/microdev/setup.c
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -371,7 +371,7 @@ static void __init microdev_setup(char **cmdline_p)
/*
* The Machine Vector
*/
-struct sh_machine_vector mv_sh4202_microdev __initmv = {
+static struct sh_machine_vector mv_sh4202_microdev __initmv = {
.mv_name = "SH4-202 MicroDev",
.mv_setup = microdev_setup,
.mv_nr_irqs = 72, /* QQQ need to check this - use the MACRO */
@@ -403,4 +403,3 @@ struct sh_machine_vector mv_sh4202_microdev __initmv = {
.mv_heartbeat = microdev_heartbeat,
#endif
};
-ALIAS_MV(sh4202_microdev)
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
index 6bcd939bfaed..606d25a4b870 100644
--- a/arch/sh/boards/titan/setup.c
+++ b/arch/sh/boards/titan/setup.c
@@ -12,7 +12,7 @@
#include <asm/titan.h>
#include <asm/io.h>
-static struct ipr_data titan_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR idx, shift, prio */
{ TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */
{ TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */
@@ -20,15 +20,33 @@ static struct ipr_data titan_ipr_map[] = {
{ TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */
};
+static unsigned long ipr_offsets[] = { /* stolen from setup-sh7750.c */
+ 0xffd00004UL, /* 0: IPRA */
+ 0xffd00008UL, /* 1: IPRB */
+ 0xffd0000cUL, /* 2: IPRC */
+ 0xffd00010UL, /* 3: IPRD */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-titan",
+ },
+};
static void __init init_titan_irq(void)
{
/* enable individual interrupt mode for externals */
ipr_irq_enable_irlm();
/* register ipr irqs */
- make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
-struct sh_machine_vector mv_titan __initmv = {
+static struct sh_machine_vector mv_titan __initmv = {
.mv_name = "Titan",
.mv_inb = titan_inb,
@@ -52,4 +70,3 @@ struct sh_machine_vector mv_titan __initmv = {
.mv_init_irq = init_titan_irq,
};
-ALIAS_MV(titan)
diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile
deleted file mode 100644
index 7d18f408b0c5..000000000000
--- a/arch/sh/boards/unknown/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for unknown SH boards
-#
-
-obj-y := setup.o
-
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
deleted file mode 100644
index bee4612de59b..000000000000
--- a/arch/sh/boards/unknown/setup.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/arch/sh/boards/unknown/setup.c
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Setup code for an unknown machine (internal peripherals only)
- *
- * This is the simplest of all boards, and serves only as a quick and dirty
- * method to start debugging a new board during bring-up until proper board
- * setup code is written.
- */
-#include <linux/init.h>
-#include <asm/machvec.h>
-
-struct sh_machine_vector mv_unknown __initmv = {
- .mv_name = "Unknown",
-};
-ALIAS_MV(unknown)
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig
index 0582ca8346b6..2e516e9a6ede 100644
--- a/arch/sh/cchips/Kconfig
+++ b/arch/sh/cchips/Kconfig
@@ -13,10 +13,8 @@ config VOYAGERGX
are additional GPIO bits that can be used to interface to
external as well.
-# A board must have defined HD6446X_SERIES in order to see these
config HD6446X_SERIES
- bool "HD6446x support"
- default n
+ bool
choice
prompt "HD6446x options"
@@ -25,7 +23,6 @@ choice
config HD64461
bool "Hitachi HD64461 companion chip support"
- depends on CPU_SUBTYPE_SH7709
---help---
The Hitachi HD64461 provides an interface for
the SH7709 CPU, supporting a LCD controller,
@@ -40,7 +37,6 @@ config HD64461
config HD64465
bool "Hitachi HD64465 companion chip support"
- depends on CPU_SUBTYPE_SH7750
---help---
The Hitachi HD64465 provides an interface for
the SH7750 CPU, supporting a LCD controller,
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
index 8b6b5a779de8..3fdd270eecf7 100644
--- a/arch/sh/configs/dreamcast_defconfig
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -1,15 +1,23 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct 3 10:51:55 2006
+# Linux kernel version: 2.6.22-rc4
+# Sat Jul 7 03:47:45 2007
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -28,6 +36,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
@@ -35,8 +44,10 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -50,14 +61,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -93,44 +109,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# System type
#
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-CONFIG_SH_DREAMCAST=y
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
CONFIG_CPU_SH4=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
-
-#
-# SH-3 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -138,79 +119,93 @@ CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7708 is not set
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
-CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
CONFIG_CPU_SUBTYPE_SH7091=y
-CONFIG_CPU_SUBTYPE_SH7750R=y
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
# CONFIG_CPU_SUBTYPE_SH7750S is not set
# CONFIG_CPU_SUBTYPE_SH7751 is not set
# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
#
# Memory management options
#
+CONFIG_QUICKLIST=y
CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x01000000
CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
#
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
#
# Processor features
#
CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_SH_FPU=y
# CONFIG_SH_DSP is not set
CONFIG_SH_STORE_QUEUES=y
CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
#
-# Timer support
+# Board support
+#
+CONFIG_SH_DREAMCAST=y
+
+#
+# Timer and clock configuration
#
CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
CONFIG_SH_PCLK_FREQ=49876504
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
#
# CPU Frequency scaling
@@ -232,6 +227,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
#
# DMA support
#
+CONFIG_SH_DMA_API=y
CONFIG_SH_DMA=y
CONFIG_NR_ONCHIP_DMA_CHANNELS=4
CONFIG_NR_DMA_CHANNELS_BOOL=y
@@ -240,17 +236,23 @@ CONFIG_NR_DMA_CHANNELS=9
#
# Companion Chips
#
-# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
#
# Kernel features
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
# CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
@@ -269,33 +271,23 @@ CONFIG_CMDLINE="console=ttySC1,115200 panic=3"
# Bus options
#
CONFIG_PCI=y
-# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
# CONFIG_BINFMT_MISC is not set
#
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
# Networking
#
CONFIG_NET=y
@@ -303,13 +295,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -327,30 +319,20 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -376,7 +358,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -394,10 +385,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -408,6 +395,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -421,13 +409,16 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
-# ATA/ATAPI/MFM/RLL support
+# Misc devices
#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -436,10 +427,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -455,6 +442,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -470,15 +458,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -521,47 +501,16 @@ CONFIG_8139TOO=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_SC92031 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -604,17 +553,19 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_ATKBD is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -660,10 +611,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -680,14 +627,8 @@ CONFIG_SH_WDT=y
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -695,11 +636,7 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -711,44 +648,51 @@ CONFIG_HW_RANDOM=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
-#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Misc devices
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -763,13 +707,17 @@ CONFIG_FB_PVR2=y
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -789,10 +737,6 @@ CONFIG_FONT_8x16=y
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
@@ -800,7 +744,6 @@ CONFIG_LOGO=y
# CONFIG_LOGO_SUPERH_MONO is not set
# CONFIG_LOGO_SUPERH_VGA16 is not set
CONFIG_LOGO_SUPERH_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -808,6 +751,12 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -823,10 +772,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -874,10 +819,12 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -957,6 +904,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
CONFIG_PROFILING=y
@@ -965,17 +917,18 @@ CONFIG_PROFILING=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
+# CONFIG_SH_KGDB is not set
#
# Security options
@@ -991,8 +944,13 @@ CONFIG_LOG_BUF_SHIFT=14
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig
new file mode 100644
index 000000000000..17f7402b31d8
--- /dev/null
+++ b/arch/sh/configs/r7780mp_defconfig
@@ -0,0 +1,1223 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 10:24:57 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+# CONFIG_32BIT is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_DSP is not set
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_SPECULATIVE_EXECUTION=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+# CONFIG_SH_7780_SOLUTION_ENGINE is not set
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_R7780RP is not set
+CONFIG_SH_R7780MP=y
+# CONFIG_SH_R7785RP is not set
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_PCLK_FREQ=32000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+CONFIG_PUSH_SWITCH=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_PCNET32_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+# CONFIG_VIA_RHINE_NAPI is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OSS_OBSOLETE is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
index 0f5ec649daf8..5c29338532da 100644
--- a/arch/sh/configs/r7785rp_defconfig
+++ b/arch/sh/configs/r7785rp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Mon Mar 12 14:26:33 2007
+# Linux kernel version: 2.6.22-rc4
+# Thu Jul 12 12:33:15 2007
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,7 +11,9 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -43,6 +45,7 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -60,13 +63,18 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -102,55 +110,11 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
# System type
#
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-CONFIG_SH_HIGHLANDER=y
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_UNKNOWN is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_R7780MP is not set
-CONFIG_SH_R7785RP=y
-
-#
-# Processor selection
-#
CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
CONFIG_CPU_SHX2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
# CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -158,10 +122,7 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7708 is not set
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -170,23 +131,12 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
CONFIG_CPU_SUBTYPE_SH7785=y
-
-#
-# SH4AL-DSP Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
@@ -194,6 +144,7 @@ CONFIG_CPU_SUBTYPE_SH7785=y
#
# Memory management options
#
+CONFIG_QUICKLIST=y
CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x08000000
@@ -201,6 +152,12 @@ CONFIG_MEMORY_SIZE=0x08000000
CONFIG_32BIT=y
# CONFIG_X2TLB is not set
CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
@@ -215,17 +172,17 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
#
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
#
# Processor features
@@ -241,12 +198,22 @@ CONFIG_CPU_HAS_SR_RB=y
CONFIG_CPU_HAS_PTEA=y
#
+# Board support
+#
+CONFIG_SH_HIGHLANDER=y
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_R7780MP is not set
+CONFIG_SH_R7785RP=y
+
+#
# Timer and clock configuration
#
CONFIG_SH_TMU=y
CONFIG_SH_TIMER_IRQ=28
-CONFIG_NO_IDLE_HZ=y
CONFIG_SH_PCLK_FREQ=50000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
#
# CPU Frequency scaling
@@ -261,7 +228,6 @@ CONFIG_SH_PCLK_FREQ=50000000
#
# Companion Chips
#
-# CONFIG_HD6446X_SERIES is not set
#
# Additional SuperH Device Drivers
@@ -278,7 +244,7 @@ CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_KEXEC=y
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
@@ -300,31 +266,22 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
# CONFIG_BINFMT_MISC is not set
#
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
# Networking
#
CONFIG_NET=y
@@ -332,7 +289,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -377,20 +333,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
CONFIG_BRIDGE=m
@@ -417,8 +361,16 @@ CONFIG_LLC=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -438,10 +390,6 @@ CONFIG_FW_LOADER=m
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -475,12 +423,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -509,6 +455,7 @@ CONFIG_CHR_DEV_SG=m
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -554,10 +501,6 @@ CONFIG_CHR_DEV_SG=m
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
@@ -580,6 +523,7 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -629,6 +573,7 @@ CONFIG_PATA_PLATFORM=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -644,15 +589,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -673,10 +610,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -689,55 +623,26 @@ CONFIG_R8169=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -789,6 +694,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -831,14 +737,8 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_DRM is not set
@@ -848,10 +748,7 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -864,16 +761,15 @@ CONFIG_HW_RANDOM=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -885,22 +781,30 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -908,7 +812,7 @@ CONFIG_FB=y
# CONFIG_FB_TILEBLITTING is not set
#
-# Frambuffer hardware drivers
+# Frame buffer hardware drivers
#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
@@ -930,12 +834,11 @@ CONFIG_FB=y
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
-
-#
-# Logo configuration
-#
# CONFIG_LOGO is not set
#
@@ -952,13 +855,10 @@ CONFIG_SOUND=m
# Open Sound System
#
CONFIG_SOUND_PRIME=m
-# CONFIG_OBSOLETE_OSS is not set
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_ICH is not set
+# CONFIG_OSS_OBSOLETE is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
#
# HID Devices
@@ -982,10 +882,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1026,18 +922,30 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
#
-# RTC drivers
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
#
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_SH=y
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
@@ -1051,14 +959,6 @@ CONFIG_RTC_DRV_SH=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1157,6 +1057,7 @@ CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1239,7 +1140,6 @@ CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1266,6 +1166,7 @@ CONFIG_FORCED_INLINING=y
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_4KSTACKS is not set
@@ -1300,6 +1201,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
@@ -1328,7 +1230,9 @@ CONFIG_CRYPTO_DES=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 87ab9080fd1d..f2f2a3c9c32d 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,18 +1,22 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec 6 14:40:15 2006
+# Linux kernel version: 2.6.22-rc4
+# Fri Jun 15 19:37:46 2007
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -34,8 +38,10 @@ CONFIG_LOCALVERSION=""
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -48,12 +54,17 @@ CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
# CONFIG_BASE_FULL is not set
# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
-CONFIG_SLAB=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -83,53 +94,10 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
# System type
#
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-CONFIG_SH_7206_SOLUTION_ENGINE=y
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
CONFIG_CPU_SH2=y
CONFIG_CPU_SH2A=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
# CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
CONFIG_CPU_SUBTYPE_SH7206=y
-
-#
-# SH-3 Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -137,10 +105,7 @@ CONFIG_CPU_SUBTYPE_SH7206=y
# CONFIG_CPU_SUBTYPE_SH7708 is not set
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -149,32 +114,28 @@ CONFIG_CPU_SUBTYPE_SH7206=y
# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
# CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
#
# Memory management options
#
+CONFIG_QUICKLIST=y
CONFIG_PAGE_OFFSET=0x00000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
@@ -184,35 +145,42 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
#
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
#
# Processor features
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_SH_FPU is not set
# CONFIG_SH_FPU_EMU is not set
# CONFIG_SH_DSP is not set
+CONFIG_CPU_HAS_IPR_IRQ=y
+
+#
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7206_SOLUTION_ENGINE=y
#
-# Timer support
+# Timer and clock configuration
#
CONFIG_SH_CMT=y
# CONFIG_SH_MTU2 is not set
CONFIG_SH_TIMER_IRQ=140
-# CONFIG_NO_IDLE_HZ is not set
CONFIG_SH_PCLK_FREQ=33333333
CONFIG_SH_CLK_MD=6
+# CONFIG_TICK_ONESHOT is not set
#
# CPU Frequency scaling
@@ -227,11 +195,11 @@ CONFIG_SH_CLK_MD=6
#
# Companion Chips
#
-# CONFIG_HD6446X_SERIES is not set
#
# Additional SuperH Device Drivers
#
+# CONFIG_HEARTBEAT is not set
# CONFIG_PUSH_SWITCH is not set
#
@@ -239,10 +207,11 @@ CONFIG_SH_CLK_MD=6
#
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
# CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -252,23 +221,18 @@ CONFIG_PREEMPT_NONE=y
#
CONFIG_ZERO_PAGE_OFFSET=0x00001000
CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
# CONFIG_CMDLINE_BOOL is not set
#
# Bus options
#
-# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
#
-# PCI Hotplug Support
-#
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
@@ -277,11 +241,6 @@ CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_MISC is not set
#
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
# Networking
#
CONFIG_NET=y
@@ -289,7 +248,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
# CONFIG_NET_KEY is not set
@@ -314,25 +272,14 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -358,7 +305,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -375,10 +331,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
@@ -393,6 +345,7 @@ CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
@@ -424,7 +377,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -452,16 +404,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -471,6 +420,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -479,18 +429,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -499,10 +444,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -511,19 +452,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# CONFIG_MD is not set
#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -531,10 +459,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -544,27 +468,14 @@ CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -604,6 +515,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -639,29 +551,15 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -674,27 +572,30 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
#
@@ -703,6 +604,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -717,10 +624,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -802,7 +705,6 @@ CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
# CONFIG_SYSFS is not set
# CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -816,7 +718,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
@@ -849,6 +750,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -861,14 +767,11 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_UNWIND_INFO is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
#
# Security options
@@ -883,8 +786,13 @@ CONFIG_LOG_BUF_SHIFT=14
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
index 20ac7f4c53fb..3a3c3c1f507d 100644
--- a/arch/sh/configs/se7619_defconfig
+++ b/arch/sh/configs/se7619_defconfig
@@ -1,18 +1,22 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Wed Dec 6 16:35:36 2006
+# Linux kernel version: 2.6.22-rc4
+# Fri Jun 15 19:43:06 2007
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -31,8 +35,10 @@ CONFIG_LOCALVERSION=""
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_UTS_NS is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -45,12 +51,17 @@ CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
# CONFIG_BASE_FULL is not set
# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
-CONFIG_SLAB=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -80,52 +91,9 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
# System type
#
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_R7780RP is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-CONFIG_SH_7619_SOLUTION_ENGINE=y
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
CONFIG_CPU_SH2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
CONFIG_CPU_SUBTYPE_SH7619=y
-
-#
-# SH-2A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -133,10 +101,7 @@ CONFIG_CPU_SUBTYPE_SH7619=y
# CONFIG_CPU_SUBTYPE_SH7708 is not set
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
-
-#
-# SH-4 Processor Support
-#
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -145,32 +110,28 @@ CONFIG_CPU_SUBTYPE_SH7619=y
# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
# CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
#
# Memory management options
#
+CONFIG_QUICKLIST=y
CONFIG_PAGE_OFFSET=0x00000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
@@ -180,34 +141,41 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_STATIC=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
#
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
CONFIG_SH_WRITETHROUGH=y
-# CONFIG_SH_OCRAM is not set
#
# Processor features
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_SH_FPU is not set
# CONFIG_SH_FPU_EMU is not set
# CONFIG_SH_DSP is not set
+CONFIG_CPU_HAS_IPR_IRQ=y
+
+#
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7619_SOLUTION_ENGINE=y
#
-# Timer support
+# Timer and clock configuration
#
CONFIG_SH_CMT=y
CONFIG_SH_TIMER_IRQ=86
-# CONFIG_NO_IDLE_HZ is not set
CONFIG_SH_PCLK_FREQ=31250000
CONFIG_SH_CLK_MD=5
+# CONFIG_TICK_ONESHOT is not set
#
# CPU Frequency scaling
@@ -222,11 +190,11 @@ CONFIG_SH_CLK_MD=5
#
# Companion Chips
#
-# CONFIG_HD6446X_SERIES is not set
#
# Additional SuperH Device Drivers
#
+# CONFIG_HEARTBEAT is not set
# CONFIG_PUSH_SWITCH is not set
#
@@ -234,10 +202,11 @@ CONFIG_SH_CLK_MD=5
#
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
# CONFIG_KEXEC is not set
-# CONFIG_SMP is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -247,23 +216,18 @@ CONFIG_PREEMPT_NONE=y
#
CONFIG_ZERO_PAGE_OFFSET=0x00001000
CONFIG_BOOT_LINK_OFFSET=0x00800000
-# CONFIG_UBC_WAKEUP is not set
# CONFIG_CMDLINE_BOOL is not set
#
# Bus options
#
-# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
#
-# PCI Hotplug Support
-#
-
-#
# Executable file formats
#
CONFIG_BINFMT_FLAT=y
@@ -272,11 +236,6 @@ CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_MISC is not set
#
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
# Networking
#
# CONFIG_NET is not set
@@ -295,10 +254,6 @@ CONFIG_BINFMT_ZFLAT=y
#
# Connector - unified userspace <-> kernelspace linker
#
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
@@ -313,6 +268,7 @@ CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
@@ -344,7 +300,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -372,16 +327,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -391,6 +343,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -398,17 +351,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -417,10 +365,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -429,19 +373,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MD is not set
#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
@@ -471,6 +402,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -506,29 +438,15 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -541,26 +459,29 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
#
@@ -569,6 +490,12 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -583,10 +510,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -668,7 +591,6 @@ CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
# CONFIG_SYSFS is not set
# CONFIG_TMPFS is not set
-# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -682,7 +604,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
@@ -715,14 +636,11 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_UNWIND_INFO is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_KGDB is not set
#
# Security options
@@ -737,8 +655,13 @@ CONFIG_LOG_BUF_SHIFT=14
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
index ca4c663dfa37..764b813c4051 100644
--- a/arch/sh/configs/se7722_defconfig
+++ b/arch/sh/configs/se7722_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Fri Apr 27 16:30:30 2007
+# Linux kernel version: 2.6.22-rc4
+# Wed Jun 20 18:08:04 2007
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,7 +11,9 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_GENERIC_TIME is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -43,6 +45,7 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -60,14 +63,20 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -103,57 +112,12 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
# System type
#
-CONFIG_SOLUTION_ENGINE=y
-# CONFIG_SH_SOLUTION_ENGINE is not set
-CONFIG_SH_7722_SOLUTION_ENGINE=y
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7780_SOLUTION_ENGINE is not set
-# CONFIG_SH_7300_SOLUTION_ENGINE is not set
-# CONFIG_SH_7343_SOLUTION_ENGINE is not set
-# CONFIG_SH_73180_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_HP6XX is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SH03 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
-# CONFIG_SH_7710VOIPGW is not set
-# CONFIG_SH_RTS7751R2D is not set
-# CONFIG_SH_HIGHLANDER is not set
-# CONFIG_SH_EDOSK7705 is not set
-# CONFIG_SH_SH4202_MICRODEV is not set
-# CONFIG_SH_LANDISK is not set
-# CONFIG_SH_TITAN is not set
-# CONFIG_SH_SHMIN is not set
-# CONFIG_SH_7206_SOLUTION_ENGINE is not set
-# CONFIG_SH_7619_SOLUTION_ENGINE is not set
-# CONFIG_SH_LBOX_RE2 is not set
-# CONFIG_SH_UNKNOWN is not set
-
-#
-# Processor selection
-#
CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
CONFIG_CPU_SH4AL_DSP=y
CONFIG_CPU_SHX2=y
-
-#
-# SH-2 Processor Support
-#
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
# CONFIG_CPU_SUBTYPE_SH7619 is not set
-
-#
-# SH-2A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7206 is not set
-
-#
-# SH-3 Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
@@ -162,10 +126,6 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
# CONFIG_CPU_SUBTYPE_SH7712 is not set
-
-#
-# SH-4 Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -174,23 +134,11 @@ CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-
-#
-# ST40 Processor Support
-#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-
-#
-# SH-4A Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
# CONFIG_CPU_SUBTYPE_SH7785 is not set
-
-#
-# SH4AL-DSP Processor Support
-#
# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
CONFIG_CPU_SUBTYPE_SH7722=y
@@ -198,15 +146,21 @@ CONFIG_CPU_SUBTYPE_SH7722=y
#
# Memory management options
#
+CONFIG_QUICKLIST=y
CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x04000000
-# CONFIG_32BIT is not set
# CONFIG_X2TLB is not set
CONFIG_VSYSCALL=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=1
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=2
CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
@@ -216,26 +170,25 @@ CONFIG_HUGETLB_PAGE_SIZE_64K=y
# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
#
# Cache configuration
#
# CONFIG_SH_DIRECT_MAPPED is not set
# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
#
# Processor features
@@ -252,12 +205,20 @@ CONFIG_CPU_HAS_SR_RB=y
CONFIG_CPU_HAS_PTEA=y
#
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7722_SOLUTION_ENGINE=y
+
+#
# Timer and clock configuration
#
CONFIG_SH_TMU=y
CONFIG_SH_TIMER_IRQ=16
-CONFIG_NO_IDLE_HZ=y
CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
#
# CPU Frequency scaling
@@ -272,7 +233,6 @@ CONFIG_SH_PCLK_FREQ=33333333
#
# Companion Chips
#
-# CONFIG_HD6446X_SERIES is not set
#
# Additional SuperH Device Drivers
@@ -290,7 +250,6 @@ CONFIG_HZ_250=y
CONFIG_HZ=250
CONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set
-# CONFIG_SMP is not set
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
@@ -307,7 +266,11 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
# Bus options
#
-# CONFIG_PCI is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -315,22 +278,12 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
# CONFIG_BINFMT_MISC is not set
#
-# Power management options (EXPERIMENTAL)
-#
-# CONFIG_PM is not set
-
-#
# Networking
#
CONFIG_NET=y
@@ -338,7 +291,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -375,20 +327,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -414,7 +354,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -432,10 +381,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -464,10 +409,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -496,6 +438,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -511,10 +454,6 @@ CONFIG_BLK_DEV_SD=y
#
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_PATA_PLATFORM=y
@@ -525,19 +464,6 @@ CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -545,10 +471,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -558,27 +480,14 @@ CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -627,6 +536,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -667,14 +577,8 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -682,10 +586,6 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -698,16 +598,15 @@ CONFIG_HW_RANDOM=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -719,16 +618,19 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
#
@@ -757,10 +659,6 @@ CONFIG_HID=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -800,18 +698,30 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
#
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_SH=y
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
@@ -825,14 +735,6 @@ CONFIG_RTC_DRV_SH=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -937,23 +839,24 @@ CONFIG_MSDOS_PARTITION=y
#
# Profiling support
#
-# CONFIG_PROFILING is not set
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
# CONFIG_SH_KGDB is not set
#
@@ -973,8 +876,10 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig
new file mode 100644
index 000000000000..219bad558b10
--- /dev/null
+++ b/arch/sh/configs/shx3_defconfig
@@ -0,0 +1,756 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Wed Jun 20 14:09:27 2007
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_UTS_NS is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+CONFIG_CPU_SUBTYPE_SHX3=y
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Board support
+#
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 ip=192.168.1.2:::255.255.255.0 root=/dev/nfs nfsroot=192.168.1.1:/exports/devel/rfs/mobiler noaliencache earlyprintk=bios ignore_loglevel"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# Misc devices
+#
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_PATA_PLATFORM=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SLAB_LEAK=y
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_LOCKDEP=y
+CONFIG_DEBUG_LOCKDEP=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_4KSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 99935f9daf4b..333898077c7c 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -36,23 +36,6 @@ config NR_DMA_CHANNELS
support. Setting this to a higher value allows for cascading DMACs
with additional channels.
-config DMA_PAGE_OPS
- bool "Use DMAC for page copy/clear"
- depends on SH_DMA && BROKEN
- help
- Selecting this option will use a dual-address mode configured channel
- in the SH DMAC for copy_page()/clear_page(). Primarily a performance
- hack.
-
-config DMA_PAGE_OPS_CHANNEL
- depends on DMA_PAGE_OPS
- int "DMA channel for sh memory-manager page copy/clear"
- default "3"
- help
- This allows the specification of the dual address dma channel,
- in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
- are dual-address capable.
-
config SH_DMABRG
bool "SH7760 DMABRG support"
depends on CPU_SUBTYPE_SH7760
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index 6d1cbbe6745c..fbc6f2c8649f 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -1,5 +1,6 @@
config PCI
bool "PCI support"
+ depends on SYS_SUPPORTS_PCI
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 9104b6257644..1f141a8ba17c 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -4,10 +4,9 @@
extra-y := head.o init_task.o vmlinux.lds
-obj-y := process.o signal.o traps.o irq.o \
- ptrace.o setup.o time.o sys_sh.o semaphore.o \
- io.o io_generic.o sh_ksyms.o syscalls.o \
- debugtraps.o
+obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \
+ semaphore.o setup.o signal.o sys_sh.o syscalls.o \
+ time.o topology.o traps.o
obj-y += cpu/ timers/
obj-$(CONFIG_VSYSCALL) += vsyscall/
@@ -17,7 +16,7 @@ obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
-obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_MODULES) += sh_ksyms.o module.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index ebc73b85094a..1c3b99642e1c 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -75,11 +75,7 @@ static int __init cf_init_default(void)
#if defined(CONFIG_CPU_SH4)
allocate_cf_area();
#endif
-#if defined(CONFIG_SH_UNKNOWN)
- /* This should be done in each board's init_xxx_irq. */
- make_imask_irq(14);
- disable_irq(14);
-#endif
+
return 0;
}
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 6451ad630174..9172e97dc26a 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -21,8 +21,7 @@
#include <asm/cacheflush.h>
#include <asm/cache.h>
#include <asm/io.h>
-
-extern void detect_cpu_and_cache_system(void);
+#include <asm/ubc.h>
/*
* Generic wrapper for command line arguments to disable on-chip
@@ -152,15 +151,6 @@ static void __init cache_init(void)
flags |= CCR_CACHE_CB;
#endif
-#ifdef CONFIG_SH_OCRAM
- /* Turn on OCRAM -- halve the OC */
- flags |= CCR_CACHE_ORA;
- current_cpu_data.dcache.sets >>= 1;
-
- current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
- current_cpu_data.dcache.linesz;
-#endif
-
ctrl_outl(flags, CCR);
back_to_P1();
}
@@ -269,7 +259,6 @@ asmlinkage void __init sh_cpu_init(void)
}
#endif
-#ifdef CONFIG_UBC_WAKEUP
/*
* Some brain-damaged loaders decided it would be a good idea to put
* the UBC to sleep. This causes some issues when it comes to things
@@ -277,7 +266,5 @@ asmlinkage void __init sh_cpu_init(void)
* we wake it up and hope that all is well.
*/
ubc_wakeup();
-#endif
-
speculative_execution_init();
}
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index d8e22f4ff0f0..cc5221390e09 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -13,36 +13,31 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <asm/smp.h>
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define INTC2_BASE 0xfe080000
-#define INTC2_INTMSK (INTC2_BASE + 0x40)
-#define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785)
-#define INTC2_BASE 0xffd40000
-#define INTC2_INTMSK (INTC2_BASE + 0x38)
-#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
-#endif
+static inline struct intc2_desc *get_intc2_desc(unsigned int irq)
+{
+ struct irq_chip *chip = get_irq_chip(irq);
+ return (void *)((char *)chip - offsetof(struct intc2_desc, chip));
+}
static void disable_intc2_irq(unsigned int irq)
{
struct intc2_data *p = get_irq_chip_data(irq);
- ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
+ struct intc2_desc *d = get_intc2_desc(irq);
+
+ ctrl_outl(1 << p->msk_shift, d->msk_base + p->msk_offset +
+ (hard_smp_processor_id() * 4));
}
static void enable_intc2_irq(unsigned int irq)
{
struct intc2_data *p = get_irq_chip_data(irq);
- ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
-}
+ struct intc2_desc *d = get_intc2_desc(irq);
-static struct irq_chip intc2_irq_chip = {
- .name = "INTC2",
- .mask = disable_intc2_irq,
- .unmask = enable_intc2_irq,
- .mask_ack = disable_intc2_irq,
-};
+ ctrl_outl(1 << p->msk_shift, d->mskclr_base + p->msk_offset +
+ (hard_smp_processor_id() * 4));
+}
/*
* Setup an INTC2 style interrupt.
@@ -56,30 +51,36 @@ static struct irq_chip intc2_irq_chip = {
*
* in the intc2_data table.
*/
-void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
+void register_intc2_controller(struct intc2_desc *desc)
{
int i;
- for (i = 0; i < nr_irqs; i++) {
+ desc->chip.mask = disable_intc2_irq;
+ desc->chip.unmask = enable_intc2_irq;
+ desc->chip.mask_ack = disable_intc2_irq;
+
+ for (i = 0; i < desc->nr_irqs; i++) {
unsigned long ipr, flags;
- struct intc2_data *p = table + i;
+ struct intc2_data *p = desc->intc2_data + i;
disable_irq_nosync(p->irq);
- /* Set the priority level */
- local_irq_save(flags);
+ if (desc->prio_base) {
+ /* Set the priority level */
+ local_irq_save(flags);
- ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
- ipr &= ~(0xf << p->ipr_shift);
- ipr |= p->priority << p->ipr_shift;
- ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
+ ipr = ctrl_inl(desc->prio_base + p->ipr_offset);
+ ipr &= ~(0xf << p->ipr_shift);
+ ipr |= p->priority << p->ipr_shift;
+ ctrl_outl(ipr, desc->prio_base + p->ipr_offset);
- local_irq_restore(flags);
+ local_irq_restore(flags);
+ }
- set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
+ set_irq_chip_and_handler_name(p->irq, &desc->chip,
handle_level_irq, "level");
set_irq_chip_data(p->irq, p);
- enable_intc2_irq(p->irq);
+ disable_intc2_irq(p->irq);
}
}
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 210280b6fddf..98e84f40c713 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -22,58 +22,57 @@
#include <linux/io.h>
#include <linux/interrupt.h>
+static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
+{
+ struct irq_chip *chip = get_irq_chip(irq);
+ return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
+}
+
static void disable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
+ unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
/* Set the priority in IPR to 0 */
- ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
+ ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
}
static void enable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
+ unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
/* Set priority in IPR back to original value */
- ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
+ ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
}
-static struct irq_chip ipr_irq_chip = {
- .name = "IPR",
- .mask = disable_ipr_irq,
- .unmask = enable_ipr_irq,
- .mask_ack = disable_ipr_irq,
-};
-
-unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
-unsigned int map_ipridx_to_addr(int idx)
-{
- return 0;
-}
+/*
+ * The shift value is now the number of bits to shift, not the number of
+ * bits/4. This is to make it easier to read the value directly from the
+ * datasheets. The IPR address is calculated using the ipr_offset table.
+ */
-void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
+void register_ipr_controller(struct ipr_desc *desc)
{
int i;
- for (i = 0; i < nr_irqs; i++) {
- unsigned int irq = table[i].irq;
+ desc->chip.mask = disable_ipr_irq;
+ desc->chip.unmask = enable_ipr_irq;
+ desc->chip.mask_ack = disable_ipr_irq;
- if (!irq)
- irq = table[i].irq = i;
+ for (i = 0; i < desc->nr_irqs; i++) {
+ struct ipr_data *p = desc->ipr_data + i;
- /* could the IPR index be mapped, if not we ignore this */
- if (!table[i].addr) {
- table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
- if (!table[i].addr)
- continue;
- }
+ BUG_ON(p->ipr_idx >= desc->nr_offsets);
+ BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
- disable_irq_nosync(irq);
- set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
+ disable_irq_nosync(p->irq);
+ set_irq_chip_and_handler_name(p->irq, &desc->chip,
handle_level_irq, "level");
- set_irq_chip_data(irq, &table[i]);
- enable_ipr_irq(irq);
+ set_irq_chip_data(p->irq, p);
+ disable_ipr_irq(p->irq);
}
}
-EXPORT_SYMBOL(make_ipr_irq);
+
+EXPORT_SYMBOL(register_ipr_controller);
#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
int ipr_irq_demux(int irq)
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index c16dc8fec489..ee8f1fe84b08 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -311,6 +311,7 @@ restore_all:
rte
nop
+ .align 2
#ifdef CONFIG_TRACE_IRQFLAGS
1: .long trace_hardirqs_off
#endif
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index 108e81b682ed..abbf17427e52 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -9,23 +9,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-
-
#include <linux/init.h>
+#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/cache.h>
int __init detect_cpu_and_cache_system(void)
{
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
- current_cpu_data.type = CPU_SH7604;
- current_cpu_data.dcache.ways = 4;
- current_cpu_data.dcache.way_incr = (1<<10);
- current_cpu_data.dcache.sets = 64;
- current_cpu_data.dcache.entry_shift = 4;
- current_cpu_data.dcache.linesz = L1_CACHE_BYTES;
- current_cpu_data.dcache.flags = 0;
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
current_cpu_data.type = CPU_SH7619;
current_cpu_data.dcache.ways = 4;
current_cpu_data.dcache.way_incr = (1<<12);
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index f83ff8a68f35..1a107fe22dde 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -52,7 +52,7 @@ static int __init sh7619_devices_setup(void)
}
__initcall(sh7619_devices_setup);
-static struct ipr_data sh7619_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
{ 86, 0, 4, 2 }, /* CMI0 */
{ 88, 1, 12, 3 }, /* SCIF0_ERI */
{ 89, 1, 12, 3 }, /* SCIF0_RXI */
@@ -68,7 +68,7 @@ static struct ipr_data sh7619_ipr_map[] = {
{ 99, 1, 4, 3 }, /* SCIF2_TXI */
};
-static unsigned int ipr_offsets[] = {
+static unsigned long ipr_offsets[] = {
0xf8080000, /* IPRC */
0xf8080002, /* IPRD */
0xf8080004, /* IPRE */
@@ -76,15 +76,19 @@ static unsigned int ipr_offsets[] = {
0xf8080008, /* IPRG */
};
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
- if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
- return 0;
- return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7619",
+ },
+};
void __init init_IRQ_ipr(void)
{
- make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index 4ed9110632bc..b6e3a6351fa6 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -57,7 +57,7 @@ static int __init sh7206_devices_setup(void)
}
__initcall(sh7206_devices_setup);
-static struct ipr_data sh7206_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
{ 140, 7, 12, 2 }, /* CMI0 */
{ 164, 8, 4, 2 }, /* MTU2_TGI1A */
{ 240, 13, 12, 3 }, /* SCIF0_BRI */
@@ -78,7 +78,7 @@ static struct ipr_data sh7206_ipr_map[] = {
{ 255, 13, 0, 3 }, /* SCIF3_TXI */
};
-static unsigned int ipr_offsets[] = {
+static unsigned long ipr_offsets[] = {
0xfffe0818, /* IPR01 */
0xfffe081a, /* IPR02 */
0, /* unused */
@@ -95,15 +95,19 @@ static unsigned int ipr_offsets[] = {
0xfffe0c10, /* IPR14 */
};
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
- if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
- return 0;
- return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7206",
+ },
+};
void __init init_IRQ_ipr(void)
{
- make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index b0b59d4a33ca..d8e122971c3e 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -340,8 +340,27 @@ ENTRY(vbr_base)
general_exception:
mov.l 1f, k2
mov.l 2f, k3
+#ifdef CONFIG_CPU_SUBTYPE_SHX3
+ mov.l @k2, k2
+
+ ! Is EXPEVT larger than 0x800?
+ mov #0x8, k0
+ shll8 k0
+ cmp/hs k0, k2
+ bf 0f
+
+ ! then add 0x580 (k2 is 0xd80 or 0xda0)
+ mov #0x58, k0
+ shll2 k0
+ shll2 k0
+ add k0, k2
+0:
+ bra handle_exception
+ nop
+#else
bra handle_exception
mov.l @k2, k2
+#endif
.align 2
1: .long EXPEVT
2: .long ret_from_exception
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 1983fb7ad6ea..a55b8ce2c54c 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -48,7 +48,7 @@ static int __init sh7705_devices_setup(void)
}
__initcall(sh7705_devices_setup);
-static struct ipr_data sh7705_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -70,25 +70,29 @@ static struct ipr_data sh7705_ipr_map[] = {
};
static unsigned long ipr_offsets[] = {
- 0xFFFFFEE2 /* 0: IPRA */
-, 0xFFFFFEE4 /* 1: IPRB */
-, 0xA4000016 /* 2: IPRC */
-, 0xA4000018 /* 3: IPRD */
-, 0xA400001A /* 4: IPRE */
-, 0xA4080000 /* 5: IPRF */
-, 0xA4080002 /* 6: IPRG */
-, 0xA4080004 /* 7: IPRH */
+ 0xFFFFFEE2, /* 0: IPRA */
+ 0xFFFFFEE4, /* 1: IPRB */
+ 0xA4000016, /* 2: IPRC */
+ 0xA4000018, /* 3: IPRD */
+ 0xA400001A, /* 4: IPRE */
+ 0xA4080000, /* 5: IPRF */
+ 0xA4080002, /* 6: IPRG */
+ 0xA4080004, /* 7: IPRH */
};
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
- if (idx >= ARRAY_SIZE(ipr_offsets))
- return 0;
- return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7705",
+ },
+};
-void __init init_IRQ_ipr()
+void __init init_IRQ_ipr(void)
{
- make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
index c7d7c35fc834..d79ec0c0522f 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
@@ -12,6 +12,26 @@
#include <linux/serial.h>
#include <asm/sci.h>
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xfffffec0,
+ .end = 0xfffffec0 + 0x1e,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .start = 20,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = 21,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 22,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xfffffe80,
@@ -41,8 +61,16 @@ static struct platform_device sci_device = {
},
};
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
static struct platform_device *sh7709_devices[] __initdata = {
&sci_device,
+ &rtc_device,
};
static int __init sh7709_devices_setup(void)
@@ -52,32 +80,66 @@ static int __init sh7709_devices_setup(void)
}
__initcall(sh7709_devices_setup);
-#define IPRx(A,N) .addr=A, .shift=N
-#define IPRA(N) IPRx(0xfffffee2UL,N)
-#define IPRB(N) IPRx(0xfffffee4UL,N)
-#define IPRC(N) IPRx(0xa4000016UL,N)
-#define IPRD(N) IPRx(0xa4000018UL,N)
-#define IPRE(N) IPRx(0xa400001aUL,N)
-
-static struct ipr_data sh7709_ipr_map[] = {
- [16] = { IPRA(12), 2 }, /* TMU TUNI0 */
- [17] = { IPRA(8), 4 }, /* TMU TUNI1 */
- [18 ... 19] = { IPRA(4), 1 }, /* TMU TUNI1 */
- [20 ... 22] = { IPRA(0), 2 }, /* RTC CUI */
- [23 ... 26] = { IPRB(4), 3 }, /* SCI */
- [27] = { IPRB(12), 2 }, /* WDT ITI */
- [32] = { IPRC(0), 1 }, /* IRQ 0 */
- [33] = { IPRC(4), 1 }, /* IRQ 1 */
- [34] = { IPRC(8), 1 }, /* IRQ 2 APM */
- [35] = { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */
- [36] = { IPRD(0), 1 }, /* IRQ 4 */
- [37] = { IPRD(4), 1 }, /* IRQ 5 */
- [48 ... 51] = { IPRE(12), 7 }, /* DMA */
- [52 ... 55] = { IPRE(8), 3 }, /* IRDA */
- [56 ... 59] = { IPRE(4), 3 }, /* SCIF */
+static struct ipr_data ipr_irq_table[] = {
+ { 16, 0, 12, 2 }, /* TMU TUNI0 */
+ { 17, 0, 8, 4 }, /* TMU TUNI1 */
+ { 18, 0, 4, 1 }, /* TMU TUNI1 */
+ { 19, 0, 4, 1 }, /* TMU TUNI1 */
+ { 20, 0, 0, 2 }, /* RTC CUI */
+ { 21, 0, 0, 2 }, /* RTC CUI */
+ { 22, 0, 0, 2 }, /* RTC CUI */
+
+ { 23, 1, 4, 3 }, /* SCI */
+ { 24, 1, 4, 3 }, /* SCI */
+ { 25, 1, 4, 3 }, /* SCI */
+ { 26, 1, 4, 3 }, /* SCI */
+ { 27, 1, 12, 3 }, /* WDT ITI */
+
+ { 32, 2, 0, 1 }, /* IRQ 0 */
+ { 33, 2, 4, 1 }, /* IRQ 1 */
+ { 34, 2, 8, 1 }, /* IRQ 2 APM */
+ { 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */
+
+ { 36, 3, 0, 1 }, /* IRQ 4 */
+ { 37, 3, 4, 1 }, /* IRQ 5 */
+
+ { 48, 4, 12, 7 }, /* DMA */
+ { 49, 4, 12, 7 }, /* DMA */
+ { 50, 4, 12, 7 }, /* DMA */
+ { 51, 4, 12, 7 }, /* DMA */
+
+ { 52, 4, 8, 3 }, /* IRDA */
+ { 53, 4, 8, 3 }, /* IRDA */
+ { 54, 4, 8, 3 }, /* IRDA */
+ { 55, 4, 8, 3 }, /* IRDA */
+
+ { 56, 4, 4, 3 }, /* SCIF */
+ { 57, 4, 4, 3 }, /* SCIF */
+ { 58, 4, 4, 3 }, /* SCIF */
+ { 59, 4, 4, 3 }, /* SCIF */
+};
+
+static unsigned long ipr_offsets[] = {
+ 0xfffffee2, /* 0: IPRA */
+ 0xfffffee4, /* 1: IPRB */
+ 0xa4000016, /* 2: IPRC */
+ 0xa4000018, /* 3: IPRD */
+ 0xa400001a, /* 4: IPRE */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7709",
+ },
};
-void __init init_IRQ_ipr()
+void __init init_IRQ_ipr(void)
{
- make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 51760a7e7f1c..f40e6dac337d 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -49,7 +49,7 @@ static int __init sh7710_devices_setup(void)
}
__initcall(sh7710_devices_setup);
-static struct ipr_data sh7710_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -78,26 +78,30 @@ static struct ipr_data sh7710_ipr_map[] = {
};
static unsigned long ipr_offsets[] = {
- 0xA414FEE2 /* 0: IPRA */
-, 0xA414FEE4 /* 1: IPRB */
-, 0xA4140016 /* 2: IPRC */
-, 0xA4140018 /* 3: IPRD */
-, 0xA414001A /* 4: IPRE */
-, 0xA4080000 /* 5: IPRF */
-, 0xA4080002 /* 6: IPRG */
-, 0xA4080004 /* 7: IPRH */
-, 0xA4080006 /* 8: IPRI */
+ 0xA414FEE2, /* 0: IPRA */
+ 0xA414FEE4, /* 1: IPRB */
+ 0xA4140016, /* 2: IPRC */
+ 0xA4140018, /* 3: IPRD */
+ 0xA414001A, /* 4: IPRE */
+ 0xA4080000, /* 5: IPRF */
+ 0xA4080002, /* 6: IPRG */
+ 0xA4080004, /* 7: IPRH */
+ 0xA4080006, /* 8: IPRI */
};
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
- if (idx >= ARRAY_SIZE(ipr_offsets))
- return 0;
- return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7710",
+ },
+};
-void __init init_IRQ_ipr()
+void __init init_IRQ_ipr(void)
{
- make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 8add10bd8268..dadd6bffc128 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -10,7 +10,11 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
# CPU subtype setup
obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7750S) += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7091) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index fab2eb07196b..66c3f75647b2 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -141,6 +141,14 @@ int __init detect_cpu_and_cache_system(void)
current_cpu_data.flags |= CPU_HAS_LLSC;
}
break;
+ case 0x4000: /* 1st cut */
+ case 0x4001: /* 2nd cut */
+ current_cpu_data.type = CPU_SHX3;
+ current_cpu_data.icache.ways = 4;
+ current_cpu_data.dcache.ways = 4;
+ current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+ CPU_HAS_LLSC;
+ break;
case 0x8000:
current_cpu_data.type = CPU_ST40RA;
current_cpu_data.flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 03b14cf78ddf..da153bcdfeb2 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -82,7 +82,7 @@ static int __init sh7750_devices_setup(void)
}
__initcall(sh7750_devices_setup);
-static struct ipr_data sh7750_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 12, 2 }, /* TMU1 TUNI */
@@ -106,8 +106,27 @@ static struct ipr_data sh7750_ipr_map[] = {
{ 38, 2, 8, 7 }, /* DMAC DMAE */
};
+static unsigned long ipr_offsets[] = {
+ 0xffd00004UL, /* 0: IPRA */
+ 0xffd00008UL, /* 1: IPRB */
+ 0xffd0000cUL, /* 2: IPRC */
+ 0xffd00010UL, /* 3: IPRD */
+};
+
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7750",
+ },
+};
+
#ifdef CONFIG_CPU_SUBTYPE_SH7751
-static struct ipr_data sh7751_ipr_map[] = {
+static struct ipr_data ipr_irq_table_sh7751[] = {
{ 44, 2, 8, 7 }, /* DMAC DMTE4 */
{ 45, 2, 8, 7 }, /* DMAC DMTE5 */
{ 46, 2, 8, 7 }, /* DMAC DMTE6 */
@@ -118,21 +137,26 @@ static struct ipr_data sh7751_ipr_map[] = {
/*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
/*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
};
-#endif
-static unsigned long ipr_offsets[] = {
- 0xffd00004UL, /* 0: IPRA */
- 0xffd00008UL, /* 1: IPRB */
- 0xffd0000cUL, /* 2: IPRC */
- 0xffd00010UL, /* 3: IPRD */
+static struct ipr_desc ipr_irq_desc_sh7751 = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table_sh7751,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table_sh7751),
+
+ .chip = {
+ .name = "IPR-sh7751",
+ },
};
+#endif
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
+void __init init_IRQ_ipr(void)
{
- if (idx >= ARRAY_SIZE(ipr_offsets))
- return 0;
- return ipr_offsets[idx];
+ register_ipr_controller(&ipr_irq_desc);
+#ifdef CONFIG_CPU_SUBTYPE_SH7751
+ register_ipr_controller(&ipr_irq_desc_sh7751);
+#endif
}
#define INTC_ICR 0xffd00000UL
@@ -143,11 +167,3 @@ void ipr_irq_enable_irlm(void)
{
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
}
-
-void __init init_IRQ_ipr()
-{
- make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
-#ifdef CONFIG_CPU_SUBTYPE_SH7751
- make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
-#endif
-}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index b7c702821e6f..3df169755673 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -96,7 +96,25 @@ static struct intc2_data intc2_irq_table[] = {
{109,12, 0, 4, 0, 3}, /* CMTI */
};
-static struct ipr_data sh7760_ipr_map[] = {
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+ .prio_base = 0xfe080000,
+ .msk_base = 0xfe080040,
+ .mskclr_base = 0xfe080060,
+
+ .intc2_data = intc2_irq_table,
+ .nr_irqs = ARRAY_SIZE(intc2_irq_table),
+
+ .chip = {
+ .name = "INTC2-sh7760",
+ },
+};
+
+void __init init_IRQ_intc2(void)
+{
+ register_intc2_controller(&intc2_irq_desc);
+}
+
+static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -133,20 +151,19 @@ static unsigned long ipr_offsets[] = {
0xffd00010UL, /* 3: IPRD */
};
-/* given the IPR index return the address of the IPR register */
-unsigned int map_ipridx_to_addr(int idx)
-{
- if (idx >= ARRAY_SIZE(ipr_offsets))
- return 0;
- return ipr_offsets[idx];
-}
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
-void __init init_IRQ_intc2(void)
-{
- make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
-}
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7760",
+ },
+};
-void __init init_IRQ_ipr(void)
+void __init init_IRQ_ipr(void)
{
- make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map));
+ register_ipr_controller(&ipr_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ab7422f8f820..400623286487 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o
obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
@@ -17,5 +18,6 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
obj-y += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
new file mode 100644
index 000000000000..c630b29e06a8
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
@@ -0,0 +1,135 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-shx3.c
+ *
+ * SH-X3 support for the clock framework
+ *
+ * Copyright (C) 2006-2007 Renesas Technology Corp.
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Copyright (C) 2006-2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 2, 4 ,6 };
+static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
+static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
+static int cfc_divisors[] = { 1, 1, 4, 6 };
+
+#define IFC_POS 28
+#define IFC_MSK 0x0003
+#define BFC_MSK 0x000f
+#define PFC_MSK 0x000f
+#define CFC_MSK 0x0003
+#define BFC_POS 16
+#define PFC_POS 0
+#define CFC_POS 20
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
+}
+
+static struct clk_ops shx3_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops shx3_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
+ clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops shx3_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops shx3_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *shx3_clk_ops[] = {
+ &shx3_master_clk_ops,
+ &shx3_module_clk_ops,
+ &shx3_bus_clk_ops,
+ &shx3_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(shx3_clk_ops))
+ *ops = shx3_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
+ clk->rate = clk->parent->rate / cfc_divisors[idx];
+}
+
+static struct clk_ops shx3_shyway_clk_ops = {
+ .recalc = shyway_clk_recalc,
+};
+
+static struct clk shx3_shyway_clk = {
+ .name = "shyway_clk",
+ .flags = CLK_ALWAYS_ENABLED,
+ .ops = &shx3_shyway_clk_ops,
+};
+
+/*
+ * Additional SHx3-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *shx3_onchip_clocks[] = {
+ &shx3_shyway_clk,
+};
+
+static int __init shx3_clk_init(void)
+{
+ struct clk *clk = clk_get(NULL, "master_clk");
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
+ struct clk *clkp = shx3_onchip_clocks[i];
+
+ clkp->parent = clk;
+ clk_register(clkp);
+ clk_enable(clkp);
+ }
+
+ /*
+ * Now that we have the rest of the clocks registered, we need to
+ * force the parent clock to propagate so that these clocks will
+ * automatically figure out their rate. We cheat by handing the
+ * parent clock its current rate and forcing child propagation.
+ */
+ clk_set_rate(clk, clk_get_rate(clk));
+
+ clk_put(clk);
+
+ return 0;
+}
+arch_initcall(shx3_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 1143fbf65faf..a3e159ef6dfe 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -1,7 +1,7 @@
/*
* SH7722 Setup
*
- * Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2006 - 2007 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
@@ -10,6 +10,8 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/mm.h>
+#include <asm/mmzone.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
@@ -42,7 +44,7 @@ static int __init sh7722_devices_setup(void)
}
__initcall(sh7722_devices_setup);
-static struct ipr_data sh7722_ipr_map[] = {
+static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, prio */
{ 16, 0, 12, 2 }, /* TMU0 */
{ 17, 0, 8, 2 }, /* TMU1 */
@@ -67,14 +69,25 @@ static unsigned long ipr_offsets[] = {
0xa408002c, /* 11: IPRL */
};
-unsigned int map_ipridx_to_addr(int idx)
+static struct ipr_desc ipr_irq_desc = {
+ .ipr_offsets = ipr_offsets,
+ .nr_offsets = ARRAY_SIZE(ipr_offsets),
+
+ .ipr_data = ipr_irq_table,
+ .nr_irqs = ARRAY_SIZE(ipr_irq_table),
+
+ .chip = {
+ .name = "IPR-sh7722",
+ },
+};
+
+void __init init_IRQ_ipr(void)
{
- if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
- return 0;
- return ipr_offsets[idx];
+ register_ipr_controller(&ipr_irq_desc);
}
-void __init init_IRQ_ipr(void)
+void __init plat_mem_setup(void)
{
- make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+ /* Register the URAM space as Node 1 */
+ setup_bootmem_node(1, 0x055f0000, 0x05610000);
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 9aeaa2ddaa28..b57c760bffde 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -102,7 +102,20 @@ static struct intc2_data intc2_irq_table[] = {
{ 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */
};
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+ .prio_base = 0xffd40000,
+ .msk_base = 0xffd40038,
+ .mskclr_base = 0xffd4003c,
+
+ .intc2_data = intc2_irq_table,
+ .nr_irqs = ARRAY_SIZE(intc2_irq_table),
+
+ .chip = {
+ .name = "INTC2-sh7780",
+ },
+};
+
void __init init_IRQ_intc2(void)
{
- make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+ register_intc2_controller(&intc2_irq_desc);
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 07b0de82cfe6..ce10ec5d6914 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -97,7 +97,21 @@ static struct intc2_data intc2_irq_table[] = {
{ 60, 12, 16, 0, 7, 3 }, /* SCIF5 ERI, RXI, BRI, TXI */
};
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+ .prio_base = 0xffd40000,
+ .msk_base = 0xffd40038,
+ .mskclr_base = 0xffd4003c,
+
+ .intc2_data = intc2_irq_table,
+ .nr_irqs = ARRAY_SIZE(intc2_irq_table),
+
+ .chip = {
+ .name = "INTC2-sh7785",
+ },
+};
+
void __init init_IRQ_intc2(void)
{
- make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
+ register_intc2_controller(&intc2_irq_desc);
}
+
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
new file mode 100644
index 000000000000..70683ea12b83
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -0,0 +1,85 @@
+/*
+ * SH-X3 Setup
+ *
+ * Copyright (C) 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/io.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffc30000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 40, 41, 43, 42 },
+ }, {
+ .mapbase = 0xffc40000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 44, 45, 47, 46 },
+ }, {
+ .mapbase = 0xffc50000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 48, 49, 51, 50 },
+ }, {
+ .mapbase = 0xffc60000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 52, 53, 55, 54 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *shx3_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init shx3_devices_setup(void)
+{
+ return platform_add_devices(shx3_devices,
+ ARRAY_SIZE(shx3_devices));
+}
+__initcall(shx3_devices_setup);
+
+static struct intc2_data intc2_irq_table[] = {
+ { 16, 0, 0, 0, 1, 2 }, /* TMU0 */
+ { 40, 4, 0, 0x20, 0, 3 }, /* SCIF0 ERI */
+ { 41, 4, 0, 0x20, 1, 3 }, /* SCIF0 RXI */
+ { 42, 4, 0, 0x20, 2, 3 }, /* SCIF0 BRI */
+ { 43, 4, 0, 0x20, 3, 3 }, /* SCIF0 TXI */
+};
+
+static struct intc2_desc intc2_irq_desc __read_mostly = {
+ .prio_base = 0xfe410000,
+ .msk_base = 0xfe410820,
+ .mskclr_base = 0xfe410850,
+
+ .intc2_data = intc2_irq_table,
+ .nr_irqs = ARRAY_SIZE(intc2_irq_table),
+
+ .chip = {
+ .name = "INTC2-SHX3",
+ },
+};
+
+void __init init_IRQ_intc2(void)
+{
+ register_intc2_controller(&intc2_irq_desc);
+}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 27b923c45b3d..27897798867a 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -158,15 +158,11 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
}
#ifdef CONFIG_4KSTACKS
-/*
- * These should really be __section__(".bss.page_aligned") as well, but
- * gcc's 3.0 and earlier don't handle that correctly.
- */
static char softirq_stack[NR_CPUS * THREAD_SIZE]
- __attribute__((__aligned__(THREAD_SIZE)));
+ __attribute__((__section__(".bss.page_aligned")));
static char hardirq_stack[NR_CPUS * THREAD_SIZE]
- __attribute__((__aligned__(THREAD_SIZE)));
+ __attribute__((__section__(".bss.page_aligned")));
/*
* allocate per-cpu stacks for hardirq and for softirq processing
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c
new file mode 100644
index 000000000000..23c5948f0124
--- /dev/null
+++ b/arch/sh/kernel/machvec.c
@@ -0,0 +1,130 @@
+/*
+ * arch/sh/kernel/machvec.c
+ *
+ * The SuperH machine vector setup handlers, yanked from setup.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002 - 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/machvec.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define MV_NAME_SIZE 32
+
+#define for_each_mv(mv) \
+ for ((mv) = (struct sh_machine_vector *)&__machvec_start; \
+ (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \
+ (mv)++)
+
+static struct sh_machine_vector * __init get_mv_byname(const char *name)
+{
+ struct sh_machine_vector *mv;
+
+ for_each_mv(mv)
+ if (strcasecmp(name, mv->mv_name) == 0)
+ return mv;
+
+ return NULL;
+}
+
+static unsigned int __initdata machvec_selected;
+
+static int __init early_parse_mv(char *from)
+{
+ char mv_name[MV_NAME_SIZE] = "";
+ char *mv_end;
+ char *mv_comma;
+ int mv_len;
+ struct sh_machine_vector *mvp;
+
+ mv_end = strchr(from, ' ');
+ if (mv_end == NULL)
+ mv_end = from + strlen(from);
+
+ mv_comma = strchr(from, ',');
+ mv_len = mv_end - from;
+ if (mv_len > (MV_NAME_SIZE-1))
+ mv_len = MV_NAME_SIZE-1;
+ memcpy(mv_name, from, mv_len);
+ mv_name[mv_len] = '\0';
+ from = mv_end;
+
+ machvec_selected = 1;
+
+ /* Boot with the generic vector */
+ if (strcmp(mv_name, "generic") == 0)
+ return 0;
+
+ mvp = get_mv_byname(mv_name);
+ if (unlikely(!mvp)) {
+ printk("Available vectors:\n\n\t'%s', ", sh_mv.mv_name);
+ for_each_mv(mvp)
+ printk("'%s', ", mvp->mv_name);
+ printk("\n\n");
+ panic("Failed to select machvec '%s' -- halting.\n",
+ mv_name);
+ } else
+ sh_mv = *mvp;
+
+ return 0;
+}
+early_param("sh_mv", early_parse_mv);
+
+void __init sh_mv_setup(void)
+{
+ /*
+ * Only overload the machvec if one hasn't been selected on
+ * the command line with sh_mv=
+ */
+ if (!machvec_selected) {
+ unsigned long machvec_size;
+
+ machvec_size = ((unsigned long)&__machvec_end -
+ (unsigned long)&__machvec_start);
+
+ /*
+ * If the machvec hasn't been preselected, use the first
+ * vector (usually the only one) from .machvec.init.
+ */
+ if (machvec_size >= sizeof(struct sh_machine_vector))
+ sh_mv = *(struct sh_machine_vector *)&__machvec_start;
+ }
+
+ printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type());
+
+ /*
+ * Manually walk the vec, fill in anything that the board hasn't yet
+ * by hand, wrapping to the generic implementation.
+ */
+#define mv_set(elem) do { \
+ if (!sh_mv.mv_##elem) \
+ sh_mv.mv_##elem = generic_##elem; \
+} while (0)
+
+ mv_set(inb); mv_set(inw); mv_set(inl);
+ mv_set(outb); mv_set(outw); mv_set(outl);
+
+ mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
+ mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
+
+ mv_set(insb); mv_set(insw); mv_set(insl);
+ mv_set(outsb); mv_set(outsw); mv_set(outsl);
+
+ mv_set(readb); mv_set(readw); mv_set(readl);
+ mv_set(writeb); mv_set(writew); mv_set(writel);
+
+ mv_set(ioport_map);
+ mv_set(ioport_unmap);
+ mv_set(irq_demux);
+
+ if (!sh_mv.mv_nr_irqs)
+ sh_mv.mv_nr_irqs = NR_IRQS;
+}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index a11e2aa73cbc..6334a4c54c7c 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -17,6 +17,7 @@
#include <linux/kexec.h>
#include <linux/kdebug.h>
#include <linux/tick.h>
+#include <linux/reboot.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
@@ -319,9 +320,7 @@ static void ubc_set_tracing(int asid, unsigned long pc)
ctrl_outl(pc, UBC_BARA);
#ifdef CONFIG_MMU
- /* We don't have any ASID settings for the SH-2! */
- if (current_cpu_data.type != CPU_SH7604)
- ctrl_outb(asid, UBC_BASRA);
+ ctrl_outb(asid, UBC_BASRA);
#endif
ctrl_outl(0, UBC_BAMRA);
@@ -405,8 +404,8 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
- struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
#ifdef CONFIG_MMU
+ struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
#else
/* fork almost works, enough to trick you into looking elsewhere :-( */
@@ -449,23 +448,20 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
/*
* sys_execve() executes a new program.
*/
-asmlinkage int sys_execve(char *ufilename, char **uargv,
- char **uenvp, unsigned long r7,
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+ char __user * __user *uenvp, unsigned long r7,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
int error;
char *filename;
- filename = getname((char __user *)ufilename);
+ filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
- error = do_execve(filename,
- (char __user * __user *)uargv,
- (char __user * __user *)uenvp,
- regs);
+ error = do_execve(filename, uargv, uenvp, regs);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 3fb5fc0b550d..891d1d46c902 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -91,17 +91,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long *) data);
- break;
- }
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -128,17 +119,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = !!tsk_used_math(child);
else
tmp = 0;
- ret = put_user(tmp, (unsigned long *)data);
+ ret = put_user(tmp, (unsigned long __user *)data);
break;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -196,7 +184,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long pc;
- struct pt_regs *dummy = NULL;
+ struct pt_regs *regs = NULL;
ret = -EIO;
if (!valid_signal(data))
@@ -207,7 +195,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
child->ptrace |= PT_DTRACE;
}
- pc = get_stack_long(child, (long)&dummy->pc);
+ pc = get_stack_long(child, (long)&regs->pc);
/* Next scheduling will set up UBC */
if (child->thread.ubc_pc == 0)
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index c27729135935..de8e6e2f2c87 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -23,6 +23,7 @@
#include <linux/kexec.h>
#include <asm/uaccess.h>
#include <asm/io.h>
+#include <asm/page.h>
#include <asm/sections.h>
#include <asm/irq.h>
#include <asm/setup.h>
@@ -41,20 +42,19 @@ extern void * __rd_start, * __rd_end;
* The bigger value means no problem.
*/
struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+
+/*
+ * The machine vector. First entry in .machvec.init, or clobbered by
+ * sh_mv= on the command line, prior to .machvec.init teardown.
+ */
+struct sh_machine_vector sh_mv = { .mv_name = "generic", };
+
#ifdef CONFIG_VT
struct screen_info screen_info;
#endif
-#if defined(CONFIG_SH_UNKNOWN)
-struct sh_machine_vector sh_mv;
-#endif
-
extern int root_mountflags;
-#define MV_NAME_SIZE 32
-
-static struct sh_machine_vector* __init get_mv_byname(const char* name);
-
/*
* This is set up by the setup-routine at boot-time
*/
@@ -80,131 +80,17 @@ static struct resource data_resource = { .name = "Kernel data", };
unsigned long memory_start, memory_end;
-static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
- struct sh_machine_vector** mvp,
- unsigned long *mv_io_base)
+static int __init early_parse_mem(char *p)
{
- char c = ' ', *to = command_line, *from = COMMAND_LINE;
- int len = 0;
-
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
+ unsigned long size;
memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
- memory_end = memory_start + __MEMORY_SIZE;
-
- for (;;) {
- /*
- * "mem=XXX[kKmM]" defines a size of memory.
- */
- if (c == ' ' && !memcmp(from, "mem=", 4)) {
- if (to != command_line)
- to--;
- {
- unsigned long mem_size;
-
- mem_size = memparse(from+4, &from);
- memory_end = memory_start + mem_size;
- }
- }
-
- if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
- char* mv_end;
- char* mv_comma;
- int mv_len;
- if (to != command_line)
- to--;
- from += 6;
- mv_end = strchr(from, ' ');
- if (mv_end == NULL)
- mv_end = from + strlen(from);
-
- mv_comma = strchr(from, ',');
- if ((mv_comma != NULL) && (mv_comma < mv_end)) {
- int ints[3];
- get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
- *mv_io_base = ints[1];
- mv_len = mv_comma - from;
- } else {
- mv_len = mv_end - from;
- }
- if (mv_len > (MV_NAME_SIZE-1))
- mv_len = MV_NAME_SIZE-1;
- memcpy(mv_name, from, mv_len);
- mv_name[mv_len] = '\0';
- from = mv_end;
-
- *mvp = get_mv_byname(mv_name);
- }
-
- c = *(from++);
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- *to = '\0';
- *cmdline_p = command_line;
-}
-
-static int __init sh_mv_setup(char **cmdline_p)
-{
-#ifdef CONFIG_SH_UNKNOWN
- extern struct sh_machine_vector mv_unknown;
-#endif
- struct sh_machine_vector *mv = NULL;
- char mv_name[MV_NAME_SIZE] = "";
- unsigned long mv_io_base = 0;
-
- parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
-
-#ifdef CONFIG_SH_UNKNOWN
- if (mv == NULL) {
- mv = &mv_unknown;
- if (*mv_name != '\0') {
- printk("Warning: Unsupported machine %s, using unknown\n",
- mv_name);
- }
- }
- sh_mv = *mv;
-#endif
-
- /*
- * Manually walk the vec, fill in anything that the board hasn't yet
- * by hand, wrapping to the generic implementation.
- */
-#define mv_set(elem) do { \
- if (!sh_mv.mv_##elem) \
- sh_mv.mv_##elem = generic_##elem; \
-} while (0)
-
- mv_set(inb); mv_set(inw); mv_set(inl);
- mv_set(outb); mv_set(outw); mv_set(outl);
-
- mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
- mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
-
- mv_set(insb); mv_set(insw); mv_set(insl);
- mv_set(outsb); mv_set(outsw); mv_set(outsl);
-
- mv_set(readb); mv_set(readw); mv_set(readl);
- mv_set(writeb); mv_set(writew); mv_set(writel);
-
- mv_set(ioport_map);
- mv_set(ioport_unmap);
- mv_set(irq_demux);
-
-#ifdef CONFIG_SH_UNKNOWN
- __set_io_port_base(mv_io_base);
-#endif
-
- if (!sh_mv.mv_nr_irqs)
- sh_mv.mv_nr_irqs = NR_IRQS;
+ size = memparse(p, &p);
+ memory_end = memory_start + size;
return 0;
}
+early_param("mem", early_parse_mem);
/*
* Register fully available low RAM pages with the bootmem allocator.
@@ -230,7 +116,7 @@ static void __init register_bootmem_low_pages(void)
free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
}
-void __init setup_bootmem_allocator(unsigned long start_pfn)
+void __init setup_bootmem_allocator(unsigned long free_pfn)
{
unsigned long bootmap_size;
@@ -239,9 +125,10 @@ void __init setup_bootmem_allocator(unsigned long start_pfn)
* bootstrap step all allocations (until the page allocator
* is intact) must be done via bootmem_alloc().
*/
- bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+ bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
min_low_pfn, max_low_pfn);
+ add_active_range(0, min_low_pfn, max_low_pfn);
register_bootmem_low_pages();
node_set_online(0);
@@ -254,7 +141,7 @@ void __init setup_bootmem_allocator(unsigned long start_pfn)
* an invalid RAM area.
*/
reserve_bootmem(__MEMORY_START+PAGE_SIZE,
- (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
+ (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -262,6 +149,8 @@ void __init setup_bootmem_allocator(unsigned long start_pfn)
*/
reserve_bootmem(__MEMORY_START, PAGE_SIZE);
+ sparse_memory_present_with_active_regions(0);
+
#ifdef CONFIG_BLK_DEV_INITRD
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
if (&__rd_start != &__rd_end) {
@@ -315,10 +204,6 @@ void __init setup_arch(char **cmdline_p)
{
enable_mmu();
-#ifdef CONFIG_CMDLINE_BOOL
- strcpy(COMMAND_LINE, CONFIG_CMDLINE);
-#endif
-
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
#ifdef CONFIG_BLK_DEV_RAM
@@ -339,9 +224,22 @@ void __init setup_arch(char **cmdline_p)
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;
+ memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
+ memory_end = memory_start + __MEMORY_SIZE;
+
+#ifdef CONFIG_CMDLINE_BOOL
+ strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
+#else
+ strlcpy(command_line, COMMAND_LINE, sizeof(command_line));
+#endif
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+
parse_early_param();
- sh_mv_setup(cmdline_p);
+ sh_mv_setup();
/*
* Find the highest page frame number we have available
@@ -355,8 +253,9 @@ void __init setup_arch(char **cmdline_p)
min_low_pfn = __MEMORY_START >> PAGE_SHIFT;
nodes_clear(node_online_map);
+
+ /* Setup bootmem with available RAM */
setup_memory();
- paging_init();
sparse_init();
#ifdef CONFIG_DUMMY_CONSOLE
@@ -366,46 +265,13 @@ void __init setup_arch(char **cmdline_p)
/* Perform the machine specific initialisation */
if (likely(sh_mv.mv_setup))
sh_mv.mv_setup(cmdline_p);
-}
-
-struct sh_machine_vector* __init get_mv_byname(const char* name)
-{
- extern long __machvec_start, __machvec_end;
- struct sh_machine_vector *all_vecs =
- (struct sh_machine_vector *)&__machvec_start;
-
- int i, n = ((unsigned long)&__machvec_end
- - (unsigned long)&__machvec_start)/
- sizeof(struct sh_machine_vector);
-
- for (i = 0; i < n; ++i) {
- struct sh_machine_vector *mv = &all_vecs[i];
- if (mv == NULL)
- continue;
- if (strcasecmp(name, get_system_type()) == 0) {
- return mv;
- }
- }
- return NULL;
-}
-
-static struct cpu cpu[NR_CPUS];
-
-static int __init topology_init(void)
-{
- int cpu_id;
- for_each_possible_cpu(cpu_id)
- register_cpu(&cpu[cpu_id], cpu_id);
-
- return 0;
+ paging_init();
}
-subsys_initcall(topology_init);
-
static const char *cpu_name[] = {
[CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
- [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300",
+ [CPU_SH7300] = "SH7300",
[CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
[CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
[CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710",
@@ -419,7 +285,7 @@ static const char *cpu_name[] = {
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
[CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722",
- [CPU_SH_NONE] = "Unknown"
+ [CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown"
};
const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index c1cfcb9f047c..c968dcf09eee 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -78,6 +78,16 @@ DECLARE_EXPORT(__movstr);
DECLARE_EXPORT(__movmem_i4_even);
DECLARE_EXPORT(__movmem_i4_odd);
DECLARE_EXPORT(__movmemSI12_i4);
+
+#if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__))
+/*
+ * GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST
+ * compiler which include backported patches.
+ */
+DECLARE_EXPORT(__sdivsi3_i4i);
+DECLARE_EXPORT(__udiv_qrnnd_16);
+DECLARE_EXPORT(__udivsi3_i4i);
+#endif
#else /* GCC 3.x */
DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index e323e299878b..706d81ccd101 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -23,6 +23,7 @@
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/freezer.h>
+#include <linux/io.h>
#include <asm/system.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
@@ -261,7 +262,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->regs[15]);
+ do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame);
return r0;
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 7db1c2dc5992..ff5656e60c05 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -308,9 +308,9 @@ ENTRY(sys_call_table)
.long sys_utimes
.long sys_fadvise64_64_wrapper
.long sys_ni_syscall /* Reserved for vserver */
- .long sys_ni_syscall /* Reserved for mbind */
- .long sys_ni_syscall /* 275 - get_mempolicy */
- .long sys_ni_syscall /* set_mempolicy */
+ .long sys_mbind
+ .long sys_get_mempolicy /* 275 */
+ .long sys_set_mempolicy
.long sys_mq_open
.long sys_mq_unlink
.long sys_mq_timedsend
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 2d997e2a5b6c..097ebd49f1bf 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -30,7 +30,7 @@
static int tmu_timer_start(void)
{
- ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+ ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR);
return 0;
}
@@ -52,7 +52,7 @@ static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
static int tmu_timer_stop(void)
{
- ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+ ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR);
return 0;
}
@@ -174,7 +174,8 @@ static int tmu_timer_init(void)
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
!defined(CONFIG_CPU_SUBTYPE_SH7760) && \
- !defined(CONFIG_CPU_SUBTYPE_SH7785)
+ !defined(CONFIG_CPU_SUBTYPE_SH7785) && \
+ !defined(CONFIG_CPU_SUBTYPE_SHX3)
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
#endif
diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c
new file mode 100644
index 000000000000..9b5844a1bdaa
--- /dev/null
+++ b/arch/sh/kernel/topology.c
@@ -0,0 +1,49 @@
+/*
+ * arch/sh/kernel/topology.c
+ *
+ * Copyright (C) 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+ int i, ret;
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+ for_each_online_node(i)
+ register_one_node(i);
+#endif
+
+ for_each_present_cpu(i) {
+ ret = register_cpu(&per_cpu(cpu_devices, i), i);
+ if (unlikely(ret))
+ printk(KERN_WARNING "%s: register_cpu %d failed (%d)\n",
+ __FUNCTION__, i, ret);
+ }
+
+#if defined(CONFIG_NUMA) && !defined(CONFIG_SMP)
+ /*
+ * In the UP case, make sure the CPU association is still
+ * registered under each node. Without this, sysfs fails
+ * to make the connection between nodes other than node0
+ * and cpu0.
+ */
+ for_each_online_node(i)
+ if (i != numa_node_id())
+ register_cpu_under_node(raw_smp_processor_id(), i);
+#endif
+
+ return 0;
+}
+subsys_initcall(topology_init);
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 8f18930d5bf8..502d43e4785c 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -103,6 +103,7 @@ void die(const char * str, struct pt_regs * regs, long err)
(unsigned long)task_stack_page(current));
bust_spinlocks(0);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (kexec_should_crash(current))
@@ -584,7 +585,7 @@ uspace_segv:
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = si_code;
- info.si_addr = (void *) address;
+ info.si_addr = (void __user *)address;
force_sig_info(SIGBUS, &info, current);
} else {
if (regs->pc & 1)
@@ -617,7 +618,7 @@ uspace_segv:
*/
int is_dsp_inst(struct pt_regs *regs)
{
- unsigned short inst;
+ unsigned short inst = 0;
/*
* Safe guard if DSP mode is already enabled or we're lacking
@@ -645,7 +646,6 @@ asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
- struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
siginfo_t info;
switch (r4) {
@@ -874,7 +874,7 @@ void __init trap_init(void)
void handle_BUG(struct pt_regs *regs)
{
enum bug_trap_type tt;
- tt = report_bug(regs->pc);
+ tt = report_bug(regs->pc, regs);
if (tt == BUG_TRAP_TYPE_WARN) {
regs->pc += 2;
return;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 4c5b57e9c3c1..0696402f446a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -97,18 +97,20 @@ SECTIONS
__initramfs_end = .;
#endif
+ . = ALIGN(4);
__machvec_start = .;
- .init.machvec : { *(.init.machvec) }
+ .machvec.init : { *(.machvec.init) }
__machvec_end = .;
- . = ALIGN(PAGE_SIZE);
- __init_end = .;
-
- . = ALIGN(4);
- __bss_start = .; /* BSS */
- .bss : { *(.bss) }
- . = ALIGN(4);
- _end = . ;
+ . = ALIGN(PAGE_SIZE);
+ .bss : {
+ __init_end = .;
+ __bss_start = .; /* BSS */
+ *(.bss.page_aligned)
+ *(.bss)
+ . = ALIGN(4);
+ _end = . ;
+ }
/* When something in the kernel is NOT compiled as a module, the
* module cleanup code and data are put into these segments. Both
diff --git a/arch/sh/lib/div64-generic.c b/arch/sh/lib/div64-generic.c
index c02473afd581..4bef3b5d964a 100644
--- a/arch/sh/lib/div64-generic.c
+++ b/arch/sh/lib/div64-generic.c
@@ -4,16 +4,15 @@
#include <linux/types.h>
-extern u64 __xdiv64_32(u64 n, u32 d);
+extern uint64_t __xdiv64_32(u64 n, u32 d);
-u64 __div64_32(u64 *xp, u32 y)
+uint32_t __div64_32(u64 *xp, u32 y)
{
- u64 rem;
- u64 q = __xdiv64_32(*xp, y);
+ uint32_t rem;
+ uint64_t q = __xdiv64_32(*xp, y);
rem = *xp - q * y;
*xp = q;
return rem;
}
-
diff --git a/arch/sh/lib/div64.S b/arch/sh/lib/div64.S
index eefc275d64a7..5ee7334ea64f 100644
--- a/arch/sh/lib/div64.S
+++ b/arch/sh/lib/div64.S
@@ -1,12 +1,12 @@
/*
- * unsigned long long __xdiv64_32(unsigned long long n, unsigned long d);
+ * unsigned long __xdiv64_32(unsigned long long n, unsigned long d);
*/
#include <linux/linkage.h>
.text
ENTRY(__xdiv64_32)
-#ifdef __LITTLE_ENDIAN__
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
mov r4, r0
mov r5, r1
#else
@@ -34,7 +34,7 @@ ENTRY(__xdiv64_32)
rotcl r0
div1 r6, r1
.endr
-#ifdef __LITTLE_ENDIAN__
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
mov r2, r1
rts
rotcl r0
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index a38e1eed9e77..ac2d7abd2567 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -507,6 +507,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
unsigned short insn = *(unsigned short *)regs->pc;
unsigned short finsn;
unsigned long nextpc;
+ siginfo_t info;
int nib[4] = {
(insn >> 12) & 0xf,
(insn >> 8) & 0xf,
@@ -559,9 +560,11 @@ static int ieee_fpe_handler(struct pt_regs *regs)
~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
set_tsk_thread_flag(tsk, TIF_USEDFPU);
} else {
- tsk->thread.trap_no = 11;
- tsk->thread.error_code = 0;
- force_sig(SIGFPE, tsk);
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = FPE_FLTINV;
+ info.si_addr = (void __user *)regs->pc;
+ force_sig_info(SIGFPE, &info, tsk);
}
regs->pc = nextpc;
@@ -576,14 +579,17 @@ asmlinkage void do_fpu_error(unsigned long r4, unsigned long r5,
struct pt_regs regs)
{
struct task_struct *tsk = current;
+ siginfo_t info;
if (ieee_fpe_handler (&regs))
return;
regs.pc += 2;
- tsk->thread.trap_no = 11;
- tsk->thread.error_code = 0;
- force_sig(SIGFPE, tsk);
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = FPE_FLTINV;
+ info.si_addr = (void __user *)regs.pc;
+ force_sig_info(SIGFPE, &info, tsk);
}
/**
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 253346d7b316..28d79a474cde 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -1,5 +1,3 @@
-menu "Processor selection"
-
#
# Processor families
#
@@ -38,27 +36,31 @@ config CPU_SUBTYPE_ST40
config CPU_SHX2
bool
+config CPU_SHX3
+ bool
+
+choice
+ prompt "Processor sub-type selection"
+
#
# Processor subtypes
#
-comment "SH-2 Processor Support"
-
-config CPU_SUBTYPE_SH7604
- bool "Support SH7604 processor"
- select CPU_SH2
+# SH-2 Processor Support
config CPU_SUBTYPE_SH7619
bool "Support SH7619 processor"
select CPU_SH2
+ select CPU_HAS_IPR_IRQ
-comment "SH-2A Processor Support"
+# SH-2A Processor Support
config CPU_SUBTYPE_SH7206
bool "Support SH7206 processor"
select CPU_SH2A
+ select CPU_HAS_IPR_IRQ
-comment "SH-3 Processor Support"
+# SH-3 Processor Support
config CPU_SUBTYPE_SH7300
bool "Support SH7300 processor"
@@ -113,7 +115,7 @@ config CPU_SUBTYPE_SH7712
help
Select SH7712 if you have a SH3-DSP SH7712 CPU.
-comment "SH-4 Processor Support"
+# SH-4 Processor Support
config CPU_SUBTYPE_SH7750
bool "Support SH7750 processor"
@@ -125,7 +127,7 @@ config CPU_SUBTYPE_SH7750
config CPU_SUBTYPE_SH7091
bool "Support SH7091 processor"
select CPU_SH4
- select CPU_SUBTYPE_SH7750
+ select CPU_HAS_IPR_IRQ
help
Select SH7091 if you have an SH-4 based Sega device (such as
the Dreamcast, Naomi, and Naomi 2).
@@ -133,13 +135,11 @@ config CPU_SUBTYPE_SH7091
config CPU_SUBTYPE_SH7750R
bool "Support SH7750R processor"
select CPU_SH4
- select CPU_SUBTYPE_SH7750
select CPU_HAS_IPR_IRQ
config CPU_SUBTYPE_SH7750S
bool "Support SH7750S processor"
select CPU_SH4
- select CPU_SUBTYPE_SH7750
select CPU_HAS_IPR_IRQ
config CPU_SUBTYPE_SH7751
@@ -153,7 +153,6 @@ config CPU_SUBTYPE_SH7751
config CPU_SUBTYPE_SH7751R
bool "Support SH7751R processor"
select CPU_SH4
- select CPU_SUBTYPE_SH7751
select CPU_HAS_IPR_IRQ
config CPU_SUBTYPE_SH7760
@@ -166,7 +165,7 @@ config CPU_SUBTYPE_SH4_202
bool "Support SH4-202 processor"
select CPU_SH4
-comment "ST40 Processor Support"
+# ST40 Processor Support
config CPU_SUBTYPE_ST40STB1
bool "Support ST40STB1/ST40RA processors"
@@ -181,7 +180,7 @@ config CPU_SUBTYPE_ST40GX1
help
Select ST40GX1 if you have a ST40GX1 CPU.
-comment "SH-4A Processor Support"
+# SH-4A Processor Support
config CPU_SUBTYPE_SH7770
bool "Support SH7770 processor"
@@ -198,7 +197,13 @@ config CPU_SUBTYPE_SH7785
select CPU_SHX2
select CPU_HAS_INTC2_IRQ
-comment "SH4AL-DSP Processor Support"
+config CPU_SUBTYPE_SHX3
+ bool "Support SH-X3 processor"
+ select CPU_SH4A
+ select CPU_SHX3
+ select CPU_HAS_INTC2_IRQ
+
+# SH4AL-DSP Processor Support
config CPU_SUBTYPE_SH73180
bool "Support SH73180 processor"
@@ -213,8 +218,10 @@ config CPU_SUBTYPE_SH7722
select CPU_SH4AL_DSP
select CPU_SHX2
select CPU_HAS_IPR_IRQ
+ select ARCH_SPARSEMEM_ENABLE
+ select SYS_SUPPORTS_NUMA
-endmenu
+endchoice
menu "Memory management options"
@@ -266,7 +273,7 @@ config MEMORY_SIZE
config 32BIT
bool "Support 32-bit physical addressing through PMB"
- depends on CPU_SH4A && MMU && (!X2TLB || BROKEN)
+ depends on MMU && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
default y
help
If you say Y here, physical addressing will be extended to
@@ -295,6 +302,17 @@ config VSYSCALL
For systems with an MMU that can afford to give up a page,
(the default value) say Y.
+config NUMA
+ bool "Non Uniform Memory Access (NUMA) Support"
+ depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL
+ default n
+ help
+ Some SH systems have many various memories scattered around
+ the address space, each with varying latencies. This enables
+ support for these blocks by binding them to nodes and allowing
+ memory policies to be used for prioritizing and controlling
+ allocation behaviour.
+
config NODES_SHIFT
int
default "1"
@@ -302,14 +320,34 @@ config NODES_SHIFT
config ARCH_FLATMEM_ENABLE
def_bool y
+ depends on !NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ select SPARSEMEM_STATIC
+
+config ARCH_SPARSEMEM_DEFAULT
+ def_bool y
config MAX_ACTIVE_REGIONS
int
+ default "2" if (CPU_SUBTYPE_SH7722 && SPARSEMEM)
default "1"
config ARCH_POPULATES_NODE_MAP
def_bool y
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
+config ARCH_ENABLE_MEMORY_HOTPLUG
+ def_bool y
+ depends on SPARSEMEM
+
+config ARCH_MEMORY_PROBE
+ def_bool y
+ depends on MEMORY_HOTPLUG
+
choice
prompt "Kernel page size"
default PAGE_SIZE_4KB
@@ -394,15 +432,4 @@ config SH_WRITETHROUGH
If unsure, say N.
-config SH_OCRAM
- bool "Operand Cache RAM (OCRAM) support"
- help
- Selecting this option will automatically tear down the number of
- sets in the dcache by half, which in turn exposes a memory range.
-
- The addresses for the OC RAM base will vary according to the
- processor version. Consult vendor documentation for specifics.
-
- If unsure, say N.
-
endmenu
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 3ffd7f68c0a2..d677d7f3afc1 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -8,9 +8,6 @@ obj-$(CONFIG_CPU_SH2) += cache-sh2.o
obj-$(CONFIG_CPU_SH3) += cache-sh3.o
obj-$(CONFIG_CPU_SH4) += cache-sh4.o
-obj-$(CONFIG_DMA_PAGE_OPS) += pg-dma.o
-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-
mmu-y := fault-nommu.o tlb-nommu.o pg-nommu.o
mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \
ioremap.o
@@ -27,5 +24,7 @@ obj-$(CONFIG_CPU_SH4) += tlb-sh4.o pg-sh4.o
obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
endif
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
obj-$(CONFIG_32BIT) += pmb.o
+obj-$(CONFIG_NUMA) += numa.o
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index c878faa4ae46..0b3eaf6fbb28 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -32,7 +32,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct * vma;
- unsigned long page;
int si_code;
siginfo_t info;
@@ -170,24 +169,38 @@ no_context:
* terminate things with extreme prejudice.
*
*/
- if (address < PAGE_SIZE)
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- else
- printk(KERN_ALERT "Unable to handle kernel paging request");
- printk(" at virtual address %08lx\n", address);
- printk(KERN_ALERT "pc = %08lx\n", regs->pc);
- page = (unsigned long)get_TTB();
- if (page) {
- page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
- printk(KERN_ALERT "*pde = %08lx\n", page);
- if (page & _PAGE_PRESENT) {
- page &= PAGE_MASK;
- address &= 0x003ff000;
- page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
- printk(KERN_ALERT "*pte = %08lx\n", page);
+
+ bust_spinlocks(1);
+
+ if (oops_may_print()) {
+ __typeof__(pte_val(__pte(0))) page;
+
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL "
+ "pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel paging "
+ "request");
+ printk(" at virtual address %08lx\n", address);
+ printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+ page = (unsigned long)get_TTB();
+ if (page) {
+ page = ((__typeof__(page) *) __va(page))[address >>
+ PGDIR_SHIFT];
+ printk(KERN_ALERT "*pde = %08lx\n", page);
+ if (page & _PAGE_PRESENT) {
+ page &= PAGE_MASK;
+ address &= 0x003ff000;
+ page = ((__typeof__(page) *)
+ __va(page))[address >>
+ PAGE_SHIFT];
+ printk(KERN_ALERT "*pte = %08lx\n", page);
+ }
}
}
+
die("Oops", regs, writeaccess);
+ bust_spinlocks(0);
do_exit(SIGKILL);
/*
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index e0e644ff3204..82b68c789a5f 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -18,6 +18,7 @@
#include <asm/mmu_context.h>
#include <asm/tlb.h>
#include <asm/cacheflush.h>
+#include <asm/sections.h>
#include <asm/cache.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -36,14 +37,11 @@ void show_mem(void)
show_free_areas();
for_each_online_pgdat(pgdat) {
- struct page *page, *end;
- unsigned long flags;
+ unsigned long flags, i;
pgdat_resize_lock(pgdat, &flags);
- page = pgdat->node_mem_map;
- end = page + pgdat->node_spanned_pages;
-
- do {
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat_page_nr(pgdat, i);
total++;
if (PageReserved(page))
reserved++;
@@ -55,9 +53,7 @@ void show_mem(void)
free++;
else
shared += page_count(page) - 1;
- page++;
- } while (page < end);
-
+ }
pgdat_resize_unlock(pgdat, &flags);
}
@@ -137,16 +133,12 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
}
#endif /* CONFIG_MMU */
-/* References to section boundaries */
-
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
-
/*
* paging_init() sets up the page tables
*/
void __init paging_init(void)
{
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
int nid;
/* We don't need to map the kernel through the TLB, as
@@ -158,43 +150,39 @@ void __init paging_init(void)
* check for a null value. */
set_TTB(swapper_pg_dir);
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+
for_each_online_node(nid) {
pg_data_t *pgdat = NODE_DATA(nid);
- unsigned long max_zone_pfns[MAX_NR_ZONES];
unsigned long low, start_pfn;
- memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-
start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
low = pgdat->bdata->node_low_pfn;
- max_zone_pfns[ZONE_NORMAL] = low;
- add_active_range(nid, start_pfn, low);
+ if (max_zone_pfns[ZONE_NORMAL] < low)
+ max_zone_pfns[ZONE_NORMAL] = low;
printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
nid, start_pfn, low);
-
- free_area_init_nodes(max_zone_pfns);
-
- printk("Node %u: mem_map starts at %p\n",
- pgdat->node_id, pgdat->node_mem_map);
}
+
+ free_area_init_nodes(max_zone_pfns);
}
static struct kcore_list kcore_mem, kcore_vmalloc;
void __init mem_init(void)
{
- int codesize, reservedpages, datasize, initsize;
+ int codesize, datasize, initsize;
int nid;
- reservedpages = 0;
+ num_physpages = 0;
+ high_memory = NULL;
for_each_online_node(nid) {
pg_data_t *pgdat = NODE_DATA(nid);
unsigned long node_pages = 0;
void *node_high_memory;
- int i;
num_physpages += pgdat->node_present_pages;
@@ -203,13 +191,9 @@ void __init mem_init(void)
totalram_pages += node_pages;
- for (i = 0; i < node_pages; i++)
- if (PageReserved(pgdat->node_mem_map + i))
- reservedpages++;
-
- node_high_memory = (void *)((pgdat->node_start_pfn +
- pgdat->node_spanned_pages) <<
- PAGE_SHIFT);
+ node_high_memory = (void *)__va((pgdat->node_start_pfn +
+ pgdat->node_spanned_pages) <<
+ PAGE_SHIFT);
if (node_high_memory > high_memory)
high_memory = node_high_memory;
}
@@ -239,11 +223,10 @@ void __init mem_init(void)
VMALLOC_END - VMALLOC_START);
printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
- "%dk reserved, %dk data, %dk init)\n",
+ "%dk data, %dk init)\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
- totalram_pages << (PAGE_SHIFT-10),
+ num_physpages << (PAGE_SHIFT-10),
codesize >> 10,
- reservedpages << (PAGE_SHIFT-10),
datasize >> 10,
initsize >> 10);
@@ -264,7 +247,9 @@ void free_initmem(void)
free_page(addr);
totalram_pages++;
}
- printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+ printk("Freeing unused kernel memory: %ldk freed\n",
+ ((unsigned long)&__init_end -
+ (unsigned long)&__init_begin) >> 10);
}
#ifdef CONFIG_BLK_DEV_INITRD
@@ -277,6 +262,50 @@ void free_initrd_mem(unsigned long start, unsigned long end)
free_page(p);
totalram_pages++;
}
- printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ printk("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+}
+#endif
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void online_page(struct page *page)
+{
+ ClearPageReserved(page);
+ init_page_count(page);
+ __free_page(page);
+ totalram_pages++;
+ num_physpages++;
}
+
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+ pg_data_t *pgdat;
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ int ret;
+
+ pgdat = NODE_DATA(nid);
+
+ /* We only have ZONE_NORMAL, so this is easy.. */
+ ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
+ if (unlikely(ret))
+ printk("%s: Failed, __add_pages() == %d\n", __FUNCTION__, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(arch_add_memory);
+
+int remove_memory(u64 start, u64 size)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
+
+#ifdef CONFIG_NUMA
+int memory_add_physaddr_to_nid(u64 addr)
+{
+ /* Node 0 for now.. */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
#endif
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
new file mode 100644
index 000000000000..8aff065dd307
--- /dev/null
+++ b/arch/sh/mm/numa.c
@@ -0,0 +1,92 @@
+/*
+ * arch/sh/mm/numa.c - Multiple node support for SH machines
+ *
+ * Copyright (C) 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/numa.h>
+#include <linux/pfn.h>
+#include <asm/sections.h>
+
+static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL_GPL(node_data);
+
+/*
+ * On SH machines the conventional approach is to stash system RAM
+ * in node 0, and other memory blocks in to node 1 and up, ordered by
+ * latency. Each node's pgdat is node-local at the beginning of the node,
+ * immediately followed by the node mem map.
+ */
+void __init setup_memory(void)
+{
+ unsigned long free_pfn = PFN_UP(__pa(_end));
+
+ /*
+ * Node 0 sets up its pgdat at the first available pfn,
+ * and bumps it up before setting up the bootmem allocator.
+ */
+ NODE_DATA(0) = pfn_to_kaddr(free_pfn);
+ memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
+ free_pfn += PFN_UP(sizeof(struct pglist_data));
+ NODE_DATA(0)->bdata = &plat_node_bdata[0];
+
+ /* Set up node 0 */
+ setup_bootmem_allocator(free_pfn);
+
+ /* Give the platforms a chance to hook up their nodes */
+ plat_mem_setup();
+}
+
+void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
+{
+ unsigned long bootmap_pages, bootmap_start, bootmap_size;
+ unsigned long start_pfn, free_pfn, end_pfn;
+
+ /* Don't allow bogus node assignment */
+ BUG_ON(nid > MAX_NUMNODES || nid == 0);
+
+ /*
+ * The free pfn starts at the beginning of the range, and is
+ * advanced as necessary for pgdat and node map allocations.
+ */
+ free_pfn = start_pfn = start >> PAGE_SHIFT;
+ end_pfn = end >> PAGE_SHIFT;
+
+ add_active_range(nid, start_pfn, end_pfn);
+
+ /* Node-local pgdat */
+ NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
+ free_pfn += PFN_UP(sizeof(struct pglist_data));
+ memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+
+ NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+ NODE_DATA(nid)->node_start_pfn = start_pfn;
+ NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
+
+ /* Node-local bootmap */
+ bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+ bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
+ bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
+ end_pfn);
+
+ free_bootmem_with_active_regions(nid, end_pfn);
+
+ /* Reserve the pgdat and bootmap space with the bootmem allocator */
+ reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
+ sizeof(struct pglist_data));
+ reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
+ bootmap_pages << PAGE_SHIFT);
+
+ /* It's up */
+ node_set_online(nid);
+
+ /* Kick sparsemem */
+ sparse_memory_present_with_active_regions(nid);
+}
diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c
deleted file mode 100644
index bb23679369d6..000000000000
--- a/arch/sh/mm/pg-dma.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * arch/sh/mm/pg-dma.c
- *
- * Fast clear_page()/copy_page() implementation using the SH DMAC
- *
- * 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.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/semaphore.h>
-#include <asm/mmu_context.h>
-#include <asm/addrspace.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-
-/* Channel to use for page ops, must be dual-address mode capable. */
-static int dma_channel = CONFIG_DMA_PAGE_OPS_CHANNEL;
-
-static void copy_page_dma(void *to, void *from)
-{
- /*
- * This doesn't seem to get triggered until further along in the
- * boot process, at which point the DMAC is already initialized.
- * Fix this in the same fashion as clear_page_dma() in the event
- * that this crashes due to the DMAC not being initialized.
- */
-
- flush_icache_range((unsigned long)from, PAGE_SIZE);
- dma_write_page(dma_channel, (unsigned long)from, (unsigned long)to);
- dma_wait_for_completion(dma_channel);
-}
-
-static void clear_page_dma(void *to)
-{
- /*
- * We get invoked quite early on, if the DMAC hasn't been initialized
- * yet, fall back on the slow manual implementation.
- */
- if (dma_info[dma_channel].chan != dma_channel) {
- clear_page_slow(to);
- return;
- }
-
- dma_write_page(dma_channel, (unsigned long)empty_zero_page,
- (unsigned long)to);
-
- /*
- * FIXME: Something is a bit racy here, if we poll the counter right
- * away, we seem to lock. flushing the page from the dcache doesn't
- * seem to make a difference one way or the other, though either a full
- * icache or dcache flush does.
- *
- * The location of this is important as well, and must happen prior to
- * the completion loop but after the transfer was initiated.
- *
- * Oddly enough, this doesn't appear to be an issue for copy_page()..
- */
- flush_icache_range((unsigned long)to, PAGE_SIZE);
-
- dma_wait_for_completion(dma_channel);
-}
-
-static int __init pg_dma_init(void)
-{
- int ret;
-
- ret = request_dma(dma_channel, "page ops");
- if (ret != 0)
- return ret;
-
- copy_page = copy_page_dma;
- clear_page = clear_page_dma;
-
- return ret;
-}
-
-static void __exit pg_dma_exit(void)
-{
- free_dma(dma_channel);
-}
-
-module_init(pg_dma_init);
-module_exit(pg_dma_exit);
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
-MODULE_DESCRIPTION("Optimized page copy/clear routines using a dual-address mode capable DMAC channel");
-MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile
index 3c370a113291..567516b58acc 100644
--- a/arch/sh/tools/Makefile
+++ b/arch/sh/tools/Makefile
@@ -12,4 +12,5 @@
include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
@echo ' Generating $@'
+ $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index fb40f188aff9..4b5e9305092e 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -18,7 +18,6 @@ SE SH_SOLUTION_ENGINE
HP6XX SH_HP6XX
HD64461 HD64461
HD64465 HD64465
-SATURN SH_SATURN
DREAMCAST SH_DREAMCAST
MPC1211 SH_MPC1211
SNAPGEAR SH_SECUREEDGE5410
@@ -34,3 +33,4 @@ R7785RP SH_R7785RP
TITAN SH_TITAN
SHMIN SH_SHMIN
7710VOIPGW SH_7710VOIPGW
+LBOXRE2 SH_LBOX_RE2
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 4e95e18b46d9..df06c6477468 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -129,17 +129,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long *) data);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -166,10 +158,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR:
diff --git a/arch/sh64/lib/c-checksum.c b/arch/sh64/lib/c-checksum.c
index 4b2676380deb..bd5501760240 100644
--- a/arch/sh64/lib/c-checksum.c
+++ b/arch/sh64/lib/c-checksum.c
@@ -213,3 +213,4 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
return (__wsum)result;
}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 8567cc901942..73df7115325b 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -217,6 +217,9 @@ source "drivers/pci/Kconfig"
endif
+config NO_DMA
+ def_bool !PCI
+
config SUN_OPENPROMFS
tristate "Openprom tree appears in /proc/openprom"
help
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index dc9ffea2a4f7..3bc3bff51e08 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -101,6 +101,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
show_regs(regs);
+ add_taint(TAINT_DIE);
__SAVE; __SAVE; __SAVE; __SAVE;
__SAVE; __SAVE; __SAVE; __SAVE;
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index e5eaa8072ae0..ca26232da7ab 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -160,9 +160,6 @@ static inline int srmmu_pte_none(pte_t pte)
static inline int srmmu_pte_present(pte_t pte)
{ return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); }
-static inline int srmmu_pte_read(pte_t pte)
-{ return !(pte_val(pte) & SRMMU_NOREAD); }
-
static inline void srmmu_pte_clear(pte_t *ptep)
{ srmmu_set_pte(ptep, __pte(0)); }
@@ -2181,7 +2178,6 @@ void __init ld_mmu_srmmu(void)
BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0);
- BTFIXUPSET_CALL(pte_read, srmmu_pte_read, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_bad, srmmu_pmd_bad, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_present, srmmu_pmd_present, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 436021ceb2e7..bdd835fba02e 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1748,11 +1748,6 @@ static int sun4c_pte_present(pte_t pte)
}
static void sun4c_pte_clear(pte_t *ptep) { *ptep = __pte(0); }
-static int sun4c_pte_read(pte_t pte)
-{
- return (pte_val(pte) & _SUN4C_PAGE_READ);
-}
-
static int sun4c_pmd_bad(pmd_t pmd)
{
return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) ||
@@ -2212,7 +2207,6 @@ void __init ld_mmu_sun4c(void)
BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0);
- BTFIXUPSET_CALL(pte_read, sun4c_pte_read, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_bad, sun4c_pmd_bad, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_present, sun4c_pmd_present, BTFIXUPCALL_NORM);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 6566d13db04f..b84b6af1241e 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -108,6 +108,15 @@ config SECCOMP
source kernel/Kconfig.hz
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs"
+ depends on SMP
+ select HOTPLUG
+ ---help---
+ Say Y here to experiment with turning CPUs off and on. CPUs
+ can be controlled through /sys/devices/system/cpu/cpu#.
+ Say N if you want to disable CPU hotplug.
+
source "init/Kconfig"
config SYSVIPC_COMPAT
@@ -305,6 +314,12 @@ config SUN_IO
bool
default y
+config SUN_LDOMS
+ bool "Sun Logical Domains support"
+ help
+ Say Y here is you want to support virtual devices via
+ Logical Domains.
+
config PCI
bool "PCI support"
select ARCH_SUPPORTS_MSI
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 65840a62bb9c..45ebf91a280c 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc1
-# Mon May 14 04:17:48 2007
+# Linux kernel version: 2.6.22
+# Tue Jul 17 01:19:52 2007
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -42,12 +42,11 @@ CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=18
@@ -82,22 +81,15 @@ CONFIG_SLUB=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
-
-#
-# Block layer
-#
CONFIG_BLOCK=y
CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_BLK_DEV_BSG=y
#
# IO Schedulers
@@ -156,12 +148,15 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
+# CONFIG_SUN_LDOMS is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
@@ -246,10 +241,6 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m
CONFIG_IP_DCCP_ACKVEC=y
@@ -269,15 +260,7 @@ CONFIG_IP_DCCP_CCID3_RTO=100
#
# CONFIG_IP_DCCP_DEBUG is not set
# CONFIG_NET_DCCPPROBE is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -314,6 +297,7 @@ CONFIG_NET_TCPPROBE=m
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -328,26 +312,10 @@ CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
CONFIG_CONNECTOR=m
# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
@@ -364,18 +332,11 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_CDROM_PKTCDVD_WCACHE=y
CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -440,6 +401,7 @@ CONFIG_BLK_DEV_IDEDMA=y
#
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
@@ -505,7 +467,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
# CONFIG_SCSI_SUNESP is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_ATA is not set
@@ -545,30 +506,16 @@ CONFIG_DM_ZERO=m
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
# CONFIG_I2O is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
# CONFIG_SUNLANCE is not set
@@ -578,10 +525,6 @@ CONFIG_MII=m
# CONFIG_SUNGEM is not set
CONFIG_CASSINI=m
# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
@@ -617,7 +560,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
CONFIG_BNX2=m
@@ -631,11 +573,6 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
# CONFIG_TR is not set
#
@@ -665,6 +602,7 @@ CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
CONFIG_SLHC=m
# CONFIG_NET_FC is not set
@@ -677,10 +615,6 @@ CONFIG_SLHC=m
# ISDN subsystem
#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
@@ -688,6 +622,7 @@ CONFIG_SLHC=m
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -733,7 +668,6 @@ CONFIG_INPUT_SPARCSPKR=y
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
# CONFIG_INPUT_UINPUT is not set
-# CONFIG_INPUT_POLLDEV is not set
#
# Hardware I/O ports
@@ -773,10 +707,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
@@ -785,10 +715,6 @@ CONFIG_RTC=y
# CONFIG_APPLICOM is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
CONFIG_I2C=y
@@ -822,6 +748,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
@@ -833,11 +760,13 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -848,11 +777,8 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
@@ -949,6 +875,8 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_SBUS is not set
+# CONFIG_FB_XVR500 is not set
+# CONFIG_FB_XVR2500 is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
@@ -970,9 +898,6 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
-# CONFIG_FB_XVR500 is not set
-# CONFIG_FB_XVR2500 is not set
-# CONFIG_FB_PCI is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -1118,10 +1043,7 @@ CONFIG_SND_SUN_CS4231=m
#
# CONFIG_SOUND_PRIME is not set
CONFIG_AC97_BUS=m
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
@@ -1132,10 +1054,7 @@ CONFIG_USB_HID=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
CONFIG_USB_HIDDEV=y
-
-#
-# USB support
-#
+CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
@@ -1157,7 +1076,6 @@ CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
@@ -1165,6 +1083,7 @@ CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
#
# USB Device Class drivers
@@ -1256,17 +1175,9 @@ CONFIG_USB_STORAGE=m
#
# LED Triggers
#
-
-#
-# InfiniBand support
-#
# CONFIG_INFINIBAND is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
# Real Time Clock
#
# CONFIG_RTC_CLASS is not set
@@ -1387,7 +1298,6 @@ CONFIG_RAMFS=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
@@ -1465,8 +1375,10 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -1496,10 +1408,10 @@ CONFIG_FORCED_INLINING=y
CONFIG_KEYS=y
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -1539,10 +1451,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_TEST=m
-
-#
-# Hardware crypto devices
-#
+CONFIG_CRYPTO_HW=y
#
# Library routines
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index f964bf28d21a..b66876bf410c 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
pci_psycho.o pci_sabre.o pci_schizo.o \
pci_sun4v.o pci_sun4v_asm.o pci_fire.o
-obj-$(CONFIG_SMP) += smp.o trampoline.o
+obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o
obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
@@ -26,6 +26,7 @@ obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
obj-$(CONFIG_AUDIT) += audit.o
obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o
obj-y += $(obj-yy)
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
new file mode 100644
index 000000000000..ba01533f4e03
--- /dev/null
+++ b/arch/sparc64/kernel/ds.c
@@ -0,0 +1,1168 @@
+/* ds.c: Domain Services driver for Logical Domains
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
+
+#include <asm/ldc.h>
+#include <asm/vio.h>
+#include <asm/power.h>
+#include <asm/mdesc.h>
+#include <asm/head.h>
+#include <asm/irq.h>
+
+#define DRV_MODULE_NAME "ds"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "Jul 11, 2007"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM domain services driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+struct ds_msg_tag {
+ __u32 type;
+#define DS_INIT_REQ 0x00
+#define DS_INIT_ACK 0x01
+#define DS_INIT_NACK 0x02
+#define DS_REG_REQ 0x03
+#define DS_REG_ACK 0x04
+#define DS_REG_NACK 0x05
+#define DS_UNREG_REQ 0x06
+#define DS_UNREG_ACK 0x07
+#define DS_UNREG_NACK 0x08
+#define DS_DATA 0x09
+#define DS_NACK 0x0a
+
+ __u32 len;
+};
+
+/* Result codes */
+#define DS_OK 0x00
+#define DS_REG_VER_NACK 0x01
+#define DS_REG_DUP 0x02
+#define DS_INV_HDL 0x03
+#define DS_TYPE_UNKNOWN 0x04
+
+struct ds_version {
+ __u16 major;
+ __u16 minor;
+};
+
+struct ds_ver_req {
+ struct ds_msg_tag tag;
+ struct ds_version ver;
+};
+
+struct ds_ver_ack {
+ struct ds_msg_tag tag;
+ __u16 minor;
+};
+
+struct ds_ver_nack {
+ struct ds_msg_tag tag;
+ __u16 major;
+};
+
+struct ds_reg_req {
+ struct ds_msg_tag tag;
+ __u64 handle;
+ __u16 major;
+ __u16 minor;
+ char svc_id[0];
+};
+
+struct ds_reg_ack {
+ struct ds_msg_tag tag;
+ __u64 handle;
+ __u16 minor;
+};
+
+struct ds_reg_nack {
+ struct ds_msg_tag tag;
+ __u64 handle;
+ __u16 major;
+};
+
+struct ds_unreg_req {
+ struct ds_msg_tag tag;
+ __u64 handle;
+};
+
+struct ds_unreg_ack {
+ struct ds_msg_tag tag;
+ __u64 handle;
+};
+
+struct ds_unreg_nack {
+ struct ds_msg_tag tag;
+ __u64 handle;
+};
+
+struct ds_data {
+ struct ds_msg_tag tag;
+ __u64 handle;
+};
+
+struct ds_data_nack {
+ struct ds_msg_tag tag;
+ __u64 handle;
+ __u64 result;
+};
+
+struct ds_cap_state {
+ __u64 handle;
+
+ void (*data)(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len);
+
+ const char *service_id;
+
+ u8 state;
+#define CAP_STATE_UNKNOWN 0x00
+#define CAP_STATE_REG_SENT 0x01
+#define CAP_STATE_REGISTERED 0x02
+};
+
+static void md_update_data(struct ldc_channel *lp, struct ds_cap_state *cp,
+ void *buf, int len);
+static void domain_shutdown_data(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len);
+static void domain_panic_data(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len);
+#ifdef CONFIG_HOTPLUG_CPU
+static void dr_cpu_data(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len);
+#endif
+static void ds_pri_data(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len);
+static void ds_var_data(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len);
+
+struct ds_cap_state ds_states[] = {
+ {
+ .service_id = "md-update",
+ .data = md_update_data,
+ },
+ {
+ .service_id = "domain-shutdown",
+ .data = domain_shutdown_data,
+ },
+ {
+ .service_id = "domain-panic",
+ .data = domain_panic_data,
+ },
+#ifdef CONFIG_HOTPLUG_CPU
+ {
+ .service_id = "dr-cpu",
+ .data = dr_cpu_data,
+ },
+#endif
+ {
+ .service_id = "pri",
+ .data = ds_pri_data,
+ },
+ {
+ .service_id = "var-config",
+ .data = ds_var_data,
+ },
+ {
+ .service_id = "var-config-backup",
+ .data = ds_var_data,
+ },
+};
+
+static DEFINE_SPINLOCK(ds_lock);
+
+struct ds_info {
+ struct ldc_channel *lp;
+ u8 hs_state;
+#define DS_HS_START 0x01
+#define DS_HS_DONE 0x02
+
+ void *rcv_buf;
+ int rcv_buf_len;
+};
+
+static struct ds_info *ds_info;
+
+static struct ds_cap_state *find_cap(u64 handle)
+{
+ unsigned int index = handle >> 32;
+
+ if (index >= ARRAY_SIZE(ds_states))
+ return NULL;
+ return &ds_states[index];
+}
+
+static struct ds_cap_state *find_cap_by_string(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
+ if (strcmp(ds_states[i].service_id, name))
+ continue;
+
+ return &ds_states[i];
+ }
+ return NULL;
+}
+
+static int __ds_send(struct ldc_channel *lp, void *data, int len)
+{
+ int err, limit = 1000;
+
+ err = -EINVAL;
+ while (limit-- > 0) {
+ err = ldc_write(lp, data, len);
+ if (!err || (err != -EAGAIN))
+ break;
+ udelay(1);
+ }
+
+ return err;
+}
+
+static int ds_send(struct ldc_channel *lp, void *data, int len)
+{
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&ds_lock, flags);
+ err = __ds_send(lp, data, len);
+ spin_unlock_irqrestore(&ds_lock, flags);
+
+ return err;
+}
+
+struct ds_md_update_req {
+ __u64 req_num;
+};
+
+struct ds_md_update_res {
+ __u64 req_num;
+ __u32 result;
+};
+
+static void md_update_data(struct ldc_channel *lp,
+ struct ds_cap_state *dp,
+ void *buf, int len)
+{
+ struct ds_data *dpkt = buf;
+ struct ds_md_update_req *rp;
+ struct {
+ struct ds_data data;
+ struct ds_md_update_res res;
+ } pkt;
+
+ rp = (struct ds_md_update_req *) (dpkt + 1);
+
+ printk(KERN_INFO PFX "Machine description update.\n");
+
+ mdesc_update();
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.data.tag.type = DS_DATA;
+ pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+ pkt.data.handle = dp->handle;
+ pkt.res.req_num = rp->req_num;
+ pkt.res.result = DS_OK;
+
+ ds_send(lp, &pkt, sizeof(pkt));
+}
+
+struct ds_shutdown_req {
+ __u64 req_num;
+ __u32 ms_delay;
+};
+
+struct ds_shutdown_res {
+ __u64 req_num;
+ __u32 result;
+ char reason[1];
+};
+
+static void domain_shutdown_data(struct ldc_channel *lp,
+ struct ds_cap_state *dp,
+ void *buf, int len)
+{
+ struct ds_data *dpkt = buf;
+ struct ds_shutdown_req *rp;
+ struct {
+ struct ds_data data;
+ struct ds_shutdown_res res;
+ } pkt;
+
+ rp = (struct ds_shutdown_req *) (dpkt + 1);
+
+ printk(KERN_ALERT PFX "Shutdown request from "
+ "LDOM manager received.\n");
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.data.tag.type = DS_DATA;
+ pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+ pkt.data.handle = dp->handle;
+ pkt.res.req_num = rp->req_num;
+ pkt.res.result = DS_OK;
+ pkt.res.reason[0] = 0;
+
+ ds_send(lp, &pkt, sizeof(pkt));
+
+ wake_up_powerd();
+}
+
+struct ds_panic_req {
+ __u64 req_num;
+};
+
+struct ds_panic_res {
+ __u64 req_num;
+ __u32 result;
+ char reason[1];
+};
+
+static void domain_panic_data(struct ldc_channel *lp,
+ struct ds_cap_state *dp,
+ void *buf, int len)
+{
+ struct ds_data *dpkt = buf;
+ struct ds_panic_req *rp;
+ struct {
+ struct ds_data data;
+ struct ds_panic_res res;
+ } pkt;
+
+ rp = (struct ds_panic_req *) (dpkt + 1);
+
+ printk(KERN_ALERT PFX "Panic request from "
+ "LDOM manager received.\n");
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.data.tag.type = DS_DATA;
+ pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
+ pkt.data.handle = dp->handle;
+ pkt.res.req_num = rp->req_num;
+ pkt.res.result = DS_OK;
+ pkt.res.reason[0] = 0;
+
+ ds_send(lp, &pkt, sizeof(pkt));
+
+ panic("PANIC requested by LDOM manager.");
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+struct dr_cpu_tag {
+ __u64 req_num;
+ __u32 type;
+#define DR_CPU_CONFIGURE 0x43
+#define DR_CPU_UNCONFIGURE 0x55
+#define DR_CPU_FORCE_UNCONFIGURE 0x46
+#define DR_CPU_STATUS 0x53
+
+/* Responses */
+#define DR_CPU_OK 0x6f
+#define DR_CPU_ERROR 0x65
+
+ __u32 num_records;
+};
+
+struct dr_cpu_resp_entry {
+ __u32 cpu;
+ __u32 result;
+#define DR_CPU_RES_OK 0x00
+#define DR_CPU_RES_FAILURE 0x01
+#define DR_CPU_RES_BLOCKED 0x02
+#define DR_CPU_RES_CPU_NOT_RESPONDING 0x03
+#define DR_CPU_RES_NOT_IN_MD 0x04
+
+ __u32 stat;
+#define DR_CPU_STAT_NOT_PRESENT 0x00
+#define DR_CPU_STAT_UNCONFIGURED 0x01
+#define DR_CPU_STAT_CONFIGURED 0x02
+
+ __u32 str_off;
+};
+
+static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data)
+{
+ struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
+ struct ds_info *dp = ds_info;
+ struct {
+ struct ds_data data;
+ struct dr_cpu_tag tag;
+ } pkt;
+ int msg_len;
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.data.tag.type = DS_DATA;
+ pkt.data.handle = cp->handle;
+ pkt.tag.req_num = tag->req_num;
+ pkt.tag.type = DR_CPU_ERROR;
+ pkt.tag.num_records = 0;
+
+ msg_len = (sizeof(struct ds_data) +
+ sizeof(struct dr_cpu_tag));
+
+ pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
+
+ __ds_send(dp->lp, &pkt, msg_len);
+}
+
+static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ds_lock, flags);
+ __dr_cpu_send_error(cp, data);
+ spin_unlock_irqrestore(&ds_lock, flags);
+}
+
+#define CPU_SENTINEL 0xffffffff
+
+static void purge_dups(u32 *list, u32 num_ents)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_ents; i++) {
+ u32 cpu = list[i];
+ unsigned int j;
+
+ if (cpu == CPU_SENTINEL)
+ continue;
+
+ for (j = i + 1; j < num_ents; j++) {
+ if (list[j] == cpu)
+ list[j] = CPU_SENTINEL;
+ }
+ }
+}
+
+static int dr_cpu_size_response(int ncpus)
+{
+ return (sizeof(struct ds_data) +
+ sizeof(struct dr_cpu_tag) +
+ (sizeof(struct dr_cpu_resp_entry) * ncpus));
+}
+
+static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
+ u64 handle, int resp_len, int ncpus,
+ cpumask_t *mask, u32 default_stat)
+{
+ struct dr_cpu_resp_entry *ent;
+ struct dr_cpu_tag *tag;
+ int i, cpu;
+
+ tag = (struct dr_cpu_tag *) (resp + 1);
+ ent = (struct dr_cpu_resp_entry *) (tag + 1);
+
+ resp->tag.type = DS_DATA;
+ resp->tag.len = resp_len - sizeof(struct ds_msg_tag);
+ resp->handle = handle;
+ tag->req_num = req_num;
+ tag->type = DR_CPU_OK;
+ tag->num_records = ncpus;
+
+ i = 0;
+ for_each_cpu_mask(cpu, *mask) {
+ ent[i].cpu = cpu;
+ ent[i].result = DR_CPU_RES_OK;
+ ent[i].stat = default_stat;
+ i++;
+ }
+ BUG_ON(i != ncpus);
+}
+
+static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus,
+ u32 res, u32 stat)
+{
+ struct dr_cpu_resp_entry *ent;
+ struct dr_cpu_tag *tag;
+ int i;
+
+ tag = (struct dr_cpu_tag *) (resp + 1);
+ ent = (struct dr_cpu_resp_entry *) (tag + 1);
+
+ for (i = 0; i < ncpus; i++) {
+ if (ent[i].cpu != cpu)
+ continue;
+ ent[i].result = res;
+ ent[i].stat = stat;
+ break;
+ }
+}
+
+static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num,
+ cpumask_t *mask)
+{
+ struct ds_data *resp;
+ int resp_len, ncpus, cpu;
+ unsigned long flags;
+
+ ncpus = cpus_weight(*mask);
+ resp_len = dr_cpu_size_response(ncpus);
+ resp = kzalloc(resp_len, GFP_KERNEL);
+ if (!resp)
+ return -ENOMEM;
+
+ dr_cpu_init_response(resp, req_num, cp->handle,
+ resp_len, ncpus, mask,
+ DR_CPU_STAT_CONFIGURED);
+
+ mdesc_fill_in_cpu_data(*mask);
+
+ for_each_cpu_mask(cpu, *mask) {
+ int err;
+
+ printk(KERN_INFO PFX "Starting cpu %d...\n", cpu);
+ err = cpu_up(cpu);
+ if (err) {
+ __u32 res = DR_CPU_RES_FAILURE;
+ __u32 stat = DR_CPU_STAT_UNCONFIGURED;
+
+ if (!cpu_present(cpu)) {
+ /* CPU not present in MD */
+ res = DR_CPU_RES_NOT_IN_MD;
+ stat = DR_CPU_STAT_NOT_PRESENT;
+ } else if (err == -ENODEV) {
+ /* CPU did not call in successfully */
+ res = DR_CPU_RES_CPU_NOT_RESPONDING;
+ }
+
+ printk(KERN_INFO PFX "CPU startup failed err=%d\n",
+ err);
+ dr_cpu_mark(resp, cpu, ncpus, res, stat);
+ }
+ }
+
+ spin_lock_irqsave(&ds_lock, flags);
+ __ds_send(ds_info->lp, resp, resp_len);
+ spin_unlock_irqrestore(&ds_lock, flags);
+
+ kfree(resp);
+
+ /* Redistribute IRQs, taking into account the new cpus. */
+ fixup_irqs();
+
+ return 0;
+}
+
+static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num,
+ cpumask_t *mask)
+{
+ struct ds_data *resp;
+ int resp_len, ncpus, cpu;
+ unsigned long flags;
+
+ ncpus = cpus_weight(*mask);
+ resp_len = dr_cpu_size_response(ncpus);
+ resp = kzalloc(resp_len, GFP_KERNEL);
+ if (!resp)
+ return -ENOMEM;
+
+ dr_cpu_init_response(resp, req_num, cp->handle,
+ resp_len, ncpus, mask,
+ DR_CPU_STAT_UNCONFIGURED);
+
+ for_each_cpu_mask(cpu, *mask) {
+ int err;
+
+ printk(KERN_INFO PFX "CPU[%d]: Shutting down cpu %d...\n",
+ smp_processor_id(), cpu);
+ err = cpu_down(cpu);
+ if (err)
+ dr_cpu_mark(resp, cpu, ncpus,
+ DR_CPU_RES_FAILURE,
+ DR_CPU_STAT_CONFIGURED);
+ }
+
+ spin_lock_irqsave(&ds_lock, flags);
+ __ds_send(ds_info->lp, resp, resp_len);
+ spin_unlock_irqrestore(&ds_lock, flags);
+
+ kfree(resp);
+
+ return 0;
+}
+
+static void dr_cpu_data(struct ldc_channel *lp,
+ struct ds_cap_state *cp,
+ void *buf, int len)
+{
+ struct ds_data *data = buf;
+ struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
+ u32 *cpu_list = (u32 *) (tag + 1);
+ u64 req_num = tag->req_num;
+ cpumask_t mask;
+ unsigned int i;
+ int err;
+
+ switch (tag->type) {
+ case DR_CPU_CONFIGURE:
+ case DR_CPU_UNCONFIGURE:
+ case DR_CPU_FORCE_UNCONFIGURE:
+ break;
+
+ default:
+ dr_cpu_send_error(cp, data);
+ return;
+ }
+
+ purge_dups(cpu_list, tag->num_records);
+
+ cpus_clear(mask);
+ for (i = 0; i < tag->num_records; i++) {
+ if (cpu_list[i] == CPU_SENTINEL)
+ continue;
+
+ if (cpu_list[i] < NR_CPUS)
+ cpu_set(cpu_list[i], mask);
+ }
+
+ if (tag->type == DR_CPU_CONFIGURE)
+ err = dr_cpu_configure(cp, req_num, &mask);
+ else
+ err = dr_cpu_unconfigure(cp, req_num, &mask);
+
+ if (err)
+ dr_cpu_send_error(cp, data);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+struct ds_pri_msg {
+ __u64 req_num;
+ __u64 type;
+#define DS_PRI_REQUEST 0x00
+#define DS_PRI_DATA 0x01
+#define DS_PRI_UPDATE 0x02
+};
+
+static void ds_pri_data(struct ldc_channel *lp,
+ struct ds_cap_state *dp,
+ void *buf, int len)
+{
+ struct ds_data *dpkt = buf;
+ struct ds_pri_msg *rp;
+
+ rp = (struct ds_pri_msg *) (dpkt + 1);
+
+ printk(KERN_INFO PFX "PRI REQ [%lx:%lx], len=%d\n",
+ rp->req_num, rp->type, len);
+}
+
+struct ds_var_hdr {
+ __u32 type;
+#define DS_VAR_SET_REQ 0x00
+#define DS_VAR_DELETE_REQ 0x01
+#define DS_VAR_SET_RESP 0x02
+#define DS_VAR_DELETE_RESP 0x03
+};
+
+struct ds_var_set_msg {
+ struct ds_var_hdr hdr;
+ char name_and_value[0];
+};
+
+struct ds_var_delete_msg {
+ struct ds_var_hdr hdr;
+ char name[0];
+};
+
+struct ds_var_resp {
+ struct ds_var_hdr hdr;
+ __u32 result;
+#define DS_VAR_SUCCESS 0x00
+#define DS_VAR_NO_SPACE 0x01
+#define DS_VAR_INVALID_VAR 0x02
+#define DS_VAR_INVALID_VAL 0x03
+#define DS_VAR_NOT_PRESENT 0x04
+};
+
+static DEFINE_MUTEX(ds_var_mutex);
+static int ds_var_doorbell;
+static int ds_var_response;
+
+static void ds_var_data(struct ldc_channel *lp,
+ struct ds_cap_state *dp,
+ void *buf, int len)
+{
+ struct ds_data *dpkt = buf;
+ struct ds_var_resp *rp;
+
+ rp = (struct ds_var_resp *) (dpkt + 1);
+
+ if (rp->hdr.type != DS_VAR_SET_RESP &&
+ rp->hdr.type != DS_VAR_DELETE_RESP)
+ return;
+
+ ds_var_response = rp->result;
+ wmb();
+ ds_var_doorbell = 1;
+}
+
+void ldom_set_var(const char *var, const char *value)
+{
+ struct ds_info *dp = ds_info;
+ struct ds_cap_state *cp;
+
+ cp = find_cap_by_string("var-config");
+ if (cp->state != CAP_STATE_REGISTERED)
+ cp = find_cap_by_string("var-config-backup");
+
+ if (cp->state == CAP_STATE_REGISTERED) {
+ union {
+ struct {
+ struct ds_data data;
+ struct ds_var_set_msg msg;
+ } header;
+ char all[512];
+ } pkt;
+ unsigned long flags;
+ char *base, *p;
+ int msg_len, loops;
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.header.data.tag.type = DS_DATA;
+ pkt.header.data.handle = cp->handle;
+ pkt.header.msg.hdr.type = DS_VAR_SET_REQ;
+ base = p = &pkt.header.msg.name_and_value[0];
+ strcpy(p, var);
+ p += strlen(var) + 1;
+ strcpy(p, value);
+ p += strlen(value) + 1;
+
+ msg_len = (sizeof(struct ds_data) +
+ sizeof(struct ds_var_set_msg) +
+ (p - base));
+ msg_len = (msg_len + 3) & ~3;
+ pkt.header.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
+
+ mutex_lock(&ds_var_mutex);
+
+ spin_lock_irqsave(&ds_lock, flags);
+ ds_var_doorbell = 0;
+ ds_var_response = -1;
+
+ __ds_send(dp->lp, &pkt, msg_len);
+ spin_unlock_irqrestore(&ds_lock, flags);
+
+ loops = 1000;
+ while (ds_var_doorbell == 0) {
+ if (loops-- < 0)
+ break;
+ barrier();
+ udelay(100);
+ }
+
+ mutex_unlock(&ds_var_mutex);
+
+ if (ds_var_doorbell == 0 ||
+ ds_var_response != DS_VAR_SUCCESS)
+ printk(KERN_ERR PFX "var-config [%s:%s] "
+ "failed, response(%d).\n",
+ var, value,
+ ds_var_response);
+ } else {
+ printk(KERN_ERR PFX "var-config not registered so "
+ "could not set (%s) variable to (%s).\n",
+ var, value);
+ }
+}
+
+void ldom_reboot(const char *boot_command)
+{
+ /* Don't bother with any of this if the boot_command
+ * is empty.
+ */
+ if (boot_command && strlen(boot_command)) {
+ char full_boot_str[256];
+
+ strcpy(full_boot_str, "boot ");
+ strcpy(full_boot_str + strlen("boot "), boot_command);
+
+ ldom_set_var("reboot-command", full_boot_str);
+ }
+ sun4v_mach_sir();
+}
+
+void ldom_power_off(void)
+{
+ sun4v_mach_exit(0);
+}
+
+static void ds_conn_reset(struct ds_info *dp)
+{
+ printk(KERN_ERR PFX "ds_conn_reset() from %p\n",
+ __builtin_return_address(0));
+}
+
+static int register_services(struct ds_info *dp)
+{
+ struct ldc_channel *lp = dp->lp;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
+ struct {
+ struct ds_reg_req req;
+ u8 id_buf[256];
+ } pbuf;
+ struct ds_cap_state *cp = &ds_states[i];
+ int err, msg_len;
+ u64 new_count;
+
+ if (cp->state == CAP_STATE_REGISTERED)
+ continue;
+
+ new_count = sched_clock() & 0xffffffff;
+ cp->handle = ((u64) i << 32) | new_count;
+
+ msg_len = (sizeof(struct ds_reg_req) +
+ strlen(cp->service_id));
+
+ memset(&pbuf, 0, sizeof(pbuf));
+ pbuf.req.tag.type = DS_REG_REQ;
+ pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
+ pbuf.req.handle = cp->handle;
+ pbuf.req.major = 1;
+ pbuf.req.minor = 0;
+ strcpy(pbuf.req.svc_id, cp->service_id);
+
+ err = __ds_send(lp, &pbuf, msg_len);
+ if (err > 0)
+ cp->state = CAP_STATE_REG_SENT;
+ }
+ return 0;
+}
+
+static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
+{
+
+ if (dp->hs_state == DS_HS_START) {
+ if (pkt->type != DS_INIT_ACK)
+ goto conn_reset;
+
+ dp->hs_state = DS_HS_DONE;
+
+ return register_services(dp);
+ }
+
+ if (dp->hs_state != DS_HS_DONE)
+ goto conn_reset;
+
+ if (pkt->type == DS_REG_ACK) {
+ struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
+ struct ds_cap_state *cp = find_cap(ap->handle);
+
+ if (!cp) {
+ printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n",
+ ap->handle);
+ return 0;
+ }
+ printk(KERN_INFO PFX "Registered %s service.\n",
+ cp->service_id);
+ cp->state = CAP_STATE_REGISTERED;
+ } else if (pkt->type == DS_REG_NACK) {
+ struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
+ struct ds_cap_state *cp = find_cap(np->handle);
+
+ if (!cp) {
+ printk(KERN_ERR PFX "REG NACK for "
+ "unknown handle %lx\n",
+ np->handle);
+ return 0;
+ }
+ printk(KERN_INFO PFX "Could not register %s service\n",
+ cp->service_id);
+ cp->state = CAP_STATE_UNKNOWN;
+ }
+
+ return 0;
+
+conn_reset:
+ ds_conn_reset(dp);
+ return -ECONNRESET;
+}
+
+static void __send_ds_nack(struct ds_info *dp, u64 handle)
+{
+ struct ds_data_nack nack = {
+ .tag = {
+ .type = DS_NACK,
+ .len = (sizeof(struct ds_data_nack) -
+ sizeof(struct ds_msg_tag)),
+ },
+ .handle = handle,
+ .result = DS_INV_HDL,
+ };
+
+ __ds_send(dp->lp, &nack, sizeof(nack));
+}
+
+static LIST_HEAD(ds_work_list);
+static DECLARE_WAIT_QUEUE_HEAD(ds_wait);
+
+struct ds_queue_entry {
+ struct list_head list;
+ int req_len;
+ int __pad;
+ u64 req[0];
+};
+
+static void process_ds_work(void)
+{
+ struct ds_queue_entry *qp, *tmp;
+ static struct ds_info *dp;
+ unsigned long flags;
+ LIST_HEAD(todo);
+
+ spin_lock_irqsave(&ds_lock, flags);
+ list_splice(&ds_work_list, &todo);
+ INIT_LIST_HEAD(&ds_work_list);
+ spin_unlock_irqrestore(&ds_lock, flags);
+
+ dp = ds_info;
+
+ list_for_each_entry_safe(qp, tmp, &todo, list) {
+ struct ds_data *dpkt = (struct ds_data *) qp->req;
+ struct ds_cap_state *cp = find_cap(dpkt->handle);
+ int req_len = qp->req_len;
+
+ if (!cp) {
+ printk(KERN_ERR PFX "Data for unknown handle %lu\n",
+ dpkt->handle);
+
+ spin_lock_irqsave(&ds_lock, flags);
+ __send_ds_nack(dp, dpkt->handle);
+ spin_unlock_irqrestore(&ds_lock, flags);
+ } else {
+ cp->data(dp->lp, cp, dpkt, req_len);
+ }
+
+ list_del(&qp->list);
+ kfree(qp);
+ }
+}
+
+static int ds_thread(void *__unused)
+{
+ DEFINE_WAIT(wait);
+
+ while (1) {
+ prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE);
+ if (list_empty(&ds_work_list))
+ schedule();
+ finish_wait(&ds_wait, &wait);
+
+ if (kthread_should_stop())
+ break;
+
+ process_ds_work();
+ }
+
+ return 0;
+}
+
+static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
+{
+ struct ds_data *dpkt = (struct ds_data *) pkt;
+ struct ds_queue_entry *qp;
+
+ qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC);
+ if (!qp) {
+ __send_ds_nack(dp, dpkt->handle);
+ } else {
+ memcpy(&qp->req, pkt, len);
+ list_add_tail(&qp->list, &ds_work_list);
+ wake_up(&ds_wait);
+ }
+ return 0;
+}
+
+static void ds_up(struct ds_info *dp)
+{
+ struct ldc_channel *lp = dp->lp;
+ struct ds_ver_req req;
+ int err;
+
+ req.tag.type = DS_INIT_REQ;
+ req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
+ req.ver.major = 1;
+ req.ver.minor = 0;
+
+ err = __ds_send(lp, &req, sizeof(req));
+ if (err > 0)
+ dp->hs_state = DS_HS_START;
+}
+
+static void ds_event(void *arg, int event)
+{
+ struct ds_info *dp = arg;
+ struct ldc_channel *lp = dp->lp;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&ds_lock, flags);
+
+ if (event == LDC_EVENT_UP) {
+ ds_up(dp);
+ spin_unlock_irqrestore(&ds_lock, flags);
+ return;
+ }
+
+ if (event != LDC_EVENT_DATA_READY) {
+ printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+ spin_unlock_irqrestore(&ds_lock, flags);
+ return;
+ }
+
+ err = 0;
+ while (1) {
+ struct ds_msg_tag *tag;
+
+ err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
+
+ if (unlikely(err < 0)) {
+ if (err == -ECONNRESET)
+ ds_conn_reset(dp);
+ break;
+ }
+ if (err == 0)
+ break;
+
+ tag = dp->rcv_buf;
+ err = ldc_read(lp, tag + 1, tag->len);
+
+ if (unlikely(err < 0)) {
+ if (err == -ECONNRESET)
+ ds_conn_reset(dp);
+ break;
+ }
+ if (err < tag->len)
+ break;
+
+ if (tag->type < DS_DATA)
+ err = ds_handshake(dp, dp->rcv_buf);
+ else
+ err = ds_data(dp, dp->rcv_buf,
+ sizeof(*tag) + err);
+ if (err == -ECONNRESET)
+ break;
+ }
+
+ spin_unlock_irqrestore(&ds_lock, flags);
+}
+
+static int __devinit ds_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ static int ds_version_printed;
+ struct ldc_channel_config ds_cfg = {
+ .event = ds_event,
+ .mtu = 4096,
+ .mode = LDC_MODE_STREAM,
+ };
+ struct ldc_channel *lp;
+ struct ds_info *dp;
+ int err;
+
+ if (ds_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ dp = kzalloc(sizeof(*dp), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!dp)
+ goto out_err;
+
+ dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
+ if (!dp->rcv_buf)
+ goto out_free_dp;
+
+ dp->rcv_buf_len = 4096;
+
+ ds_cfg.tx_irq = vdev->tx_irq;
+ ds_cfg.rx_irq = vdev->rx_irq;
+
+ lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
+ if (IS_ERR(lp)) {
+ err = PTR_ERR(lp);
+ goto out_free_rcv_buf;
+ }
+ dp->lp = lp;
+
+ err = ldc_bind(lp, "DS");
+ if (err)
+ goto out_free_ldc;
+
+ ds_info = dp;
+
+ start_powerd();
+
+ return err;
+
+out_free_ldc:
+ ldc_free(dp->lp);
+
+out_free_rcv_buf:
+ kfree(dp->rcv_buf);
+
+out_free_dp:
+ kfree(dp);
+
+out_err:
+ return err;
+}
+
+static int ds_remove(struct vio_dev *vdev)
+{
+ return 0;
+}
+
+static struct vio_device_id ds_match[] = {
+ {
+ .type = "domain-services-port",
+ },
+ {},
+};
+
+static struct vio_driver ds_driver = {
+ .id_table = ds_match,
+ .probe = ds_probe,
+ .remove = ds_remove,
+ .driver = {
+ .name = "ds",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init ds_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ds_states); i++)
+ ds_states[i].handle = ((u64)i << 32);
+
+ kthread_run(ds_thread, NULL, "kldomd");
+
+ return vio_register_driver(&ds_driver);
+}
+
+subsys_initcall(ds_init);
diff --git a/arch/sparc64/kernel/hvtramp.S b/arch/sparc64/kernel/hvtramp.S
new file mode 100644
index 000000000000..a55c252e18cc
--- /dev/null
+++ b/arch/sparc64/kernel/hvtramp.S
@@ -0,0 +1,140 @@
+/* hvtramp.S: Hypervisor start-cpu trampoline code.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <asm/thread_info.h>
+#include <asm/hypervisor.h>
+#include <asm/scratchpad.h>
+#include <asm/spitfire.h>
+#include <asm/hvtramp.h>
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+#include <asm/asi.h>
+
+ .text
+ .align 8
+ .globl hv_cpu_startup, hv_cpu_startup_end
+
+ /* This code executes directly out of the hypervisor
+ * with physical addressing (va==pa). %o0 contains
+ * our client argument which for Linux points to
+ * a descriptor data structure which defines the
+ * MMU entries we need to load up.
+ *
+ * After we set things up we enable the MMU and call
+ * into the kernel.
+ *
+ * First setup basic privileged cpu state.
+ */
+hv_cpu_startup:
+ SET_GL(0)
+ wrpr %g0, 15, %pil
+ wrpr %g0, 0, %canrestore
+ wrpr %g0, 0, %otherwin
+ wrpr %g0, 6, %cansave
+ wrpr %g0, 6, %cleanwin
+ wrpr %g0, 0, %cwp
+ wrpr %g0, 0, %wstate
+ wrpr %g0, 0, %tl
+
+ sethi %hi(sparc64_ttable_tl0), %g1
+ wrpr %g1, %tba
+
+ mov %o0, %l0
+
+ lduw [%l0 + HVTRAMP_DESCR_CPU], %g1
+ mov SCRATCHPAD_CPUID, %g2
+ stxa %g1, [%g2] ASI_SCRATCHPAD
+
+ ldx [%l0 + HVTRAMP_DESCR_FAULT_INFO_VA], %g2
+ stxa %g2, [%g0] ASI_SCRATCHPAD
+
+ mov 0, %l1
+ lduw [%l0 + HVTRAMP_DESCR_NUM_MAPPINGS], %l2
+ add %l0, HVTRAMP_DESCR_MAPS, %l3
+
+1: ldx [%l3 + HVTRAMP_MAPPING_VADDR], %o0
+ clr %o1
+ ldx [%l3 + HVTRAMP_MAPPING_TTE], %o2
+ mov HV_MMU_IMMU | HV_MMU_DMMU, %o3
+ mov HV_FAST_MMU_MAP_PERM_ADDR, %o5
+ ta HV_FAST_TRAP
+
+ brnz,pn %o0, 80f
+ nop
+
+ add %l1, 1, %l1
+ cmp %l1, %l2
+ blt,a,pt %xcc, 1b
+ add %l3, HVTRAMP_MAPPING_SIZE, %l3
+
+ ldx [%l0 + HVTRAMP_DESCR_FAULT_INFO_PA], %o0
+ mov HV_FAST_MMU_FAULT_AREA_CONF, %o5
+ ta HV_FAST_TRAP
+
+ brnz,pn %o0, 80f
+ nop
+
+ wrpr %g0, (PSTATE_PRIV | PSTATE_PEF), %pstate
+
+ ldx [%l0 + HVTRAMP_DESCR_THREAD_REG], %l6
+
+ mov 1, %o0
+ set 1f, %o1
+ mov HV_FAST_MMU_ENABLE, %o5
+ ta HV_FAST_TRAP
+
+ ba,pt %xcc, 80f
+ nop
+
+1:
+ wr %g0, 0, %fprs
+ wr %g0, ASI_P, %asi
+
+ mov PRIMARY_CONTEXT, %g7
+ stxa %g0, [%g7] ASI_MMU
+ membar #Sync
+
+ mov SECONDARY_CONTEXT, %g7
+ stxa %g0, [%g7] ASI_MMU
+ membar #Sync
+
+ mov %l6, %g6
+ ldx [%g6 + TI_TASK], %g4
+
+ mov 1, %g5
+ sllx %g5, THREAD_SHIFT, %g5
+ sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5
+ add %g6, %g5, %sp
+ mov 0, %fp
+
+ call init_irqwork_curcpu
+ nop
+ call hard_smp_processor_id
+ nop
+
+ mov %o0, %o1
+ mov 0, %o0
+ mov 0, %o2
+ call sun4v_init_mondo_queues
+ mov 1, %o3
+
+ call init_cur_cpu_trap
+ mov %g6, %o0
+
+ wrpr %g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate
+
+ call smp_callin
+ nop
+ call cpu_idle
+ mov 0, %o0
+ call cpu_panic
+ nop
+
+80: ba,pt %xcc, 80b
+ nop
+
+ .align 8
+hv_cpu_startup_end:
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 6b6165d36fd8..8cb3358674f5 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -293,6 +293,11 @@ static void sun4u_irq_enable(unsigned int virt_irq)
}
}
+static void sun4u_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+ sun4u_irq_enable(virt_irq);
+}
+
static void sun4u_irq_disable(unsigned int virt_irq)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
@@ -309,6 +314,10 @@ static void sun4u_irq_disable(unsigned int virt_irq)
static void sun4u_irq_end(unsigned int virt_irq)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+ struct irq_desc *desc = irq_desc + virt_irq;
+
+ if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ return;
if (likely(data))
upa_writeq(ICLR_IDLE, data->iclr);
@@ -340,6 +349,24 @@ static void sun4v_irq_enable(unsigned int virt_irq)
}
}
+static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+ struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+ unsigned int ino = bucket - &ivector_table[0];
+
+ if (likely(bucket)) {
+ unsigned long cpuid;
+ int err;
+
+ cpuid = irq_choose_cpu(virt_irq);
+
+ err = sun4v_intr_settarget(ino, cpuid);
+ if (err != HV_EOK)
+ printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
+ ino, cpuid, err);
+ }
+}
+
static void sun4v_irq_disable(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -373,6 +400,10 @@ static void sun4v_irq_end(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
unsigned int ino = bucket - &ivector_table[0];
+ struct irq_desc *desc = irq_desc + virt_irq;
+
+ if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ return;
if (likely(bucket)) {
int err;
@@ -418,6 +449,28 @@ static void sun4v_virq_enable(unsigned int virt_irq)
}
}
+static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
+{
+ struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+ unsigned int ino = bucket - &ivector_table[0];
+
+ if (likely(bucket)) {
+ unsigned long cpuid, dev_handle, dev_ino;
+ int err;
+
+ cpuid = irq_choose_cpu(virt_irq);
+
+ dev_handle = ino & IMAP_IGN;
+ dev_ino = ino & IMAP_INO;
+
+ err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
+ if (err != HV_EOK)
+ printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
+ "err(%d)\n",
+ dev_handle, dev_ino, cpuid, err);
+ }
+}
+
static void sun4v_virq_disable(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -443,6 +496,10 @@ static void sun4v_virq_end(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
unsigned int ino = bucket - &ivector_table[0];
+ struct irq_desc *desc = irq_desc + virt_irq;
+
+ if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ return;
if (likely(bucket)) {
unsigned long dev_handle, dev_ino;
@@ -477,6 +534,7 @@ static struct irq_chip sun4u_irq = {
.enable = sun4u_irq_enable,
.disable = sun4u_irq_disable,
.end = sun4u_irq_end,
+ .set_affinity = sun4u_set_affinity,
};
static struct irq_chip sun4u_irq_ack = {
@@ -485,6 +543,7 @@ static struct irq_chip sun4u_irq_ack = {
.disable = sun4u_irq_disable,
.ack = run_pre_handler,
.end = sun4u_irq_end,
+ .set_affinity = sun4u_set_affinity,
};
static struct irq_chip sun4v_irq = {
@@ -492,6 +551,7 @@ static struct irq_chip sun4v_irq = {
.enable = sun4v_irq_enable,
.disable = sun4v_irq_disable,
.end = sun4v_irq_end,
+ .set_affinity = sun4v_set_affinity,
};
static struct irq_chip sun4v_irq_ack = {
@@ -500,6 +560,7 @@ static struct irq_chip sun4v_irq_ack = {
.disable = sun4v_irq_disable,
.ack = run_pre_handler,
.end = sun4v_irq_end,
+ .set_affinity = sun4v_set_affinity,
};
#ifdef CONFIG_PCI_MSI
@@ -511,6 +572,7 @@ static struct irq_chip sun4v_msi = {
.disable = sun4v_msi_disable,
.ack = run_pre_handler,
.end = sun4v_irq_end,
+ .set_affinity = sun4v_set_affinity,
};
#endif
@@ -519,6 +581,7 @@ static struct irq_chip sun4v_virq = {
.enable = sun4v_virq_enable,
.disable = sun4v_virq_disable,
.end = sun4v_virq_end,
+ .set_affinity = sun4v_virt_set_affinity,
};
static struct irq_chip sun4v_virq_ack = {
@@ -527,6 +590,7 @@ static struct irq_chip sun4v_virq_ack = {
.disable = sun4v_virq_disable,
.ack = run_pre_handler,
.end = sun4v_virq_end,
+ .set_affinity = sun4v_virt_set_affinity,
};
void irq_install_pre_handler(int virt_irq,
@@ -739,6 +803,26 @@ void handler_irq(int irq, struct pt_regs *regs)
set_irq_regs(old_regs);
}
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(void)
+{
+ unsigned int irq;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&irq_desc[irq].lock, flags);
+ if (irq_desc[irq].action &&
+ !(irq_desc[irq].status & IRQ_PER_CPU)) {
+ if (irq_desc[irq].chip->set_affinity)
+ irq_desc[irq].chip->set_affinity(irq,
+ irq_desc[irq].affinity);
+ }
+ spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+ }
+}
+#endif
+
struct sun5_timer {
u64 count0;
u64 limit0;
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
new file mode 100644
index 000000000000..85a2be0b0962
--- /dev/null
+++ b/arch/sparc64/kernel/ldc.c
@@ -0,0 +1,2373 @@
+/* ldc.c: Logical Domain Channel link-layer protocol driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/iommu.h>
+#include <asm/page.h>
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+#define DRV_MODULE_NAME "ldc"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "June 25, 2007"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+#define LDC_PACKET_SIZE 64
+
+/* Packet header layout for unreliable and reliable mode frames.
+ * When in RAW mode, packets are simply straight 64-byte payloads
+ * with no headers.
+ */
+struct ldc_packet {
+ u8 type;
+#define LDC_CTRL 0x01
+#define LDC_DATA 0x02
+#define LDC_ERR 0x10
+
+ u8 stype;
+#define LDC_INFO 0x01
+#define LDC_ACK 0x02
+#define LDC_NACK 0x04
+
+ u8 ctrl;
+#define LDC_VERS 0x01 /* Link Version */
+#define LDC_RTS 0x02 /* Request To Send */
+#define LDC_RTR 0x03 /* Ready To Receive */
+#define LDC_RDX 0x04 /* Ready for Data eXchange */
+#define LDC_CTRL_MSK 0x0f
+
+ u8 env;
+#define LDC_LEN 0x3f
+#define LDC_FRAG_MASK 0xc0
+#define LDC_START 0x40
+#define LDC_STOP 0x80
+
+ u32 seqid;
+
+ union {
+ u8 u_data[LDC_PACKET_SIZE - 8];
+ struct {
+ u32 pad;
+ u32 ackid;
+ u8 r_data[LDC_PACKET_SIZE - 8 - 8];
+ } r;
+ } u;
+};
+
+struct ldc_version {
+ u16 major;
+ u16 minor;
+};
+
+/* Ordered from largest major to lowest. */
+static struct ldc_version ver_arr[] = {
+ { .major = 1, .minor = 0 },
+};
+
+#define LDC_DEFAULT_MTU (4 * LDC_PACKET_SIZE)
+#define LDC_DEFAULT_NUM_ENTRIES (PAGE_SIZE / LDC_PACKET_SIZE)
+
+struct ldc_channel;
+
+struct ldc_mode_ops {
+ int (*write)(struct ldc_channel *, const void *, unsigned int);
+ int (*read)(struct ldc_channel *, void *, unsigned int);
+};
+
+static const struct ldc_mode_ops raw_ops;
+static const struct ldc_mode_ops nonraw_ops;
+static const struct ldc_mode_ops stream_ops;
+
+int ldom_domaining_enabled;
+
+struct ldc_iommu {
+ /* Protects arena alloc/free. */
+ spinlock_t lock;
+ struct iommu_arena arena;
+ struct ldc_mtable_entry *page_table;
+};
+
+struct ldc_channel {
+ /* Protects all operations that depend upon channel state. */
+ spinlock_t lock;
+
+ unsigned long id;
+
+ u8 *mssbuf;
+ u32 mssbuf_len;
+ u32 mssbuf_off;
+
+ struct ldc_packet *tx_base;
+ unsigned long tx_head;
+ unsigned long tx_tail;
+ unsigned long tx_num_entries;
+ unsigned long tx_ra;
+
+ unsigned long tx_acked;
+
+ struct ldc_packet *rx_base;
+ unsigned long rx_head;
+ unsigned long rx_tail;
+ unsigned long rx_num_entries;
+ unsigned long rx_ra;
+
+ u32 rcv_nxt;
+ u32 snd_nxt;
+
+ unsigned long chan_state;
+
+ struct ldc_channel_config cfg;
+ void *event_arg;
+
+ const struct ldc_mode_ops *mops;
+
+ struct ldc_iommu iommu;
+
+ struct ldc_version ver;
+
+ u8 hs_state;
+#define LDC_HS_CLOSED 0x00
+#define LDC_HS_OPEN 0x01
+#define LDC_HS_GOTVERS 0x02
+#define LDC_HS_SENTRTR 0x03
+#define LDC_HS_GOTRTR 0x04
+#define LDC_HS_COMPLETE 0x10
+
+ u8 flags;
+#define LDC_FLAG_ALLOCED_QUEUES 0x01
+#define LDC_FLAG_REGISTERED_QUEUES 0x02
+#define LDC_FLAG_REGISTERED_IRQS 0x04
+#define LDC_FLAG_RESET 0x10
+
+ u8 mss;
+ u8 state;
+
+#define LDC_IRQ_NAME_MAX 32
+ char rx_irq_name[LDC_IRQ_NAME_MAX];
+ char tx_irq_name[LDC_IRQ_NAME_MAX];
+
+ struct hlist_head mh_list;
+
+ struct hlist_node list;
+};
+
+#define ldcdbg(TYPE, f, a...) \
+do { if (lp->cfg.debug & LDC_DEBUG_##TYPE) \
+ printk(KERN_INFO PFX "ID[%lu] " f, lp->id, ## a); \
+} while (0)
+
+static const char *state_to_str(u8 state)
+{
+ switch (state) {
+ case LDC_STATE_INVALID:
+ return "INVALID";
+ case LDC_STATE_INIT:
+ return "INIT";
+ case LDC_STATE_BOUND:
+ return "BOUND";
+ case LDC_STATE_READY:
+ return "READY";
+ case LDC_STATE_CONNECTED:
+ return "CONNECTED";
+ default:
+ return "<UNKNOWN>";
+ }
+}
+
+static void ldc_set_state(struct ldc_channel *lp, u8 state)
+{
+ ldcdbg(STATE, "STATE (%s) --> (%s)\n",
+ state_to_str(lp->state),
+ state_to_str(state));
+
+ lp->state = state;
+}
+
+static unsigned long __advance(unsigned long off, unsigned long num_entries)
+{
+ off += LDC_PACKET_SIZE;
+ if (off == (num_entries * LDC_PACKET_SIZE))
+ off = 0;
+
+ return off;
+}
+
+static unsigned long rx_advance(struct ldc_channel *lp, unsigned long off)
+{
+ return __advance(off, lp->rx_num_entries);
+}
+
+static unsigned long tx_advance(struct ldc_channel *lp, unsigned long off)
+{
+ return __advance(off, lp->tx_num_entries);
+}
+
+static struct ldc_packet *handshake_get_tx_packet(struct ldc_channel *lp,
+ unsigned long *new_tail)
+{
+ struct ldc_packet *p;
+ unsigned long t;
+
+ t = tx_advance(lp, lp->tx_tail);
+ if (t == lp->tx_head)
+ return NULL;
+
+ *new_tail = t;
+
+ p = lp->tx_base;
+ return p + (lp->tx_tail / LDC_PACKET_SIZE);
+}
+
+/* When we are in reliable or stream mode, have to track the next packet
+ * we haven't gotten an ACK for in the TX queue using tx_acked. We have
+ * to be careful not to stomp over the queue past that point. During
+ * the handshake, we don't have TX data packets pending in the queue
+ * and that's why handshake_get_tx_packet() need not be mindful of
+ * lp->tx_acked.
+ */
+static unsigned long head_for_data(struct ldc_channel *lp)
+{
+ if (lp->cfg.mode == LDC_MODE_STREAM)
+ return lp->tx_acked;
+ return lp->tx_head;
+}
+
+static int tx_has_space_for(struct ldc_channel *lp, unsigned int size)
+{
+ unsigned long limit, tail, new_tail, diff;
+ unsigned int mss;
+
+ limit = head_for_data(lp);
+ tail = lp->tx_tail;
+ new_tail = tx_advance(lp, tail);
+ if (new_tail == limit)
+ return 0;
+
+ if (limit > new_tail)
+ diff = limit - new_tail;
+ else
+ diff = (limit +
+ ((lp->tx_num_entries * LDC_PACKET_SIZE) - new_tail));
+ diff /= LDC_PACKET_SIZE;
+ mss = lp->mss;
+
+ if (diff * mss < size)
+ return 0;
+
+ return 1;
+}
+
+static struct ldc_packet *data_get_tx_packet(struct ldc_channel *lp,
+ unsigned long *new_tail)
+{
+ struct ldc_packet *p;
+ unsigned long h, t;
+
+ h = head_for_data(lp);
+ t = tx_advance(lp, lp->tx_tail);
+ if (t == h)
+ return NULL;
+
+ *new_tail = t;
+
+ p = lp->tx_base;
+ return p + (lp->tx_tail / LDC_PACKET_SIZE);
+}
+
+static int set_tx_tail(struct ldc_channel *lp, unsigned long tail)
+{
+ unsigned long orig_tail = lp->tx_tail;
+ int limit = 1000;
+
+ lp->tx_tail = tail;
+ while (limit-- > 0) {
+ unsigned long err;
+
+ err = sun4v_ldc_tx_set_qtail(lp->id, tail);
+ if (!err)
+ return 0;
+
+ if (err != HV_EWOULDBLOCK) {
+ lp->tx_tail = orig_tail;
+ return -EINVAL;
+ }
+ udelay(1);
+ }
+
+ lp->tx_tail = orig_tail;
+ return -EBUSY;
+}
+
+/* This just updates the head value in the hypervisor using
+ * a polling loop with a timeout. The caller takes care of
+ * upating software state representing the head change, if any.
+ */
+static int __set_rx_head(struct ldc_channel *lp, unsigned long head)
+{
+ int limit = 1000;
+
+ while (limit-- > 0) {
+ unsigned long err;
+
+ err = sun4v_ldc_rx_set_qhead(lp->id, head);
+ if (!err)
+ return 0;
+
+ if (err != HV_EWOULDBLOCK)
+ return -EINVAL;
+
+ udelay(1);
+ }
+
+ return -EBUSY;
+}
+
+static int send_tx_packet(struct ldc_channel *lp,
+ struct ldc_packet *p,
+ unsigned long new_tail)
+{
+ BUG_ON(p != (lp->tx_base + (lp->tx_tail / LDC_PACKET_SIZE)));
+
+ return set_tx_tail(lp, new_tail);
+}
+
+static struct ldc_packet *handshake_compose_ctrl(struct ldc_channel *lp,
+ u8 stype, u8 ctrl,
+ void *data, int dlen,
+ unsigned long *new_tail)
+{
+ struct ldc_packet *p = handshake_get_tx_packet(lp, new_tail);
+
+ if (p) {
+ memset(p, 0, sizeof(*p));
+ p->type = LDC_CTRL;
+ p->stype = stype;
+ p->ctrl = ctrl;
+ if (data)
+ memcpy(p->u.u_data, data, dlen);
+ }
+ return p;
+}
+
+static int start_handshake(struct ldc_channel *lp)
+{
+ struct ldc_packet *p;
+ struct ldc_version *ver;
+ unsigned long new_tail;
+
+ ver = &ver_arr[0];
+
+ ldcdbg(HS, "SEND VER INFO maj[%u] min[%u]\n",
+ ver->major, ver->minor);
+
+ p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+ ver, sizeof(*ver), &new_tail);
+ if (p) {
+ int err = send_tx_packet(lp, p, new_tail);
+ if (!err)
+ lp->flags &= ~LDC_FLAG_RESET;
+ return err;
+ }
+ return -EBUSY;
+}
+
+static int send_version_nack(struct ldc_channel *lp,
+ u16 major, u16 minor)
+{
+ struct ldc_packet *p;
+ struct ldc_version ver;
+ unsigned long new_tail;
+
+ ver.major = major;
+ ver.minor = minor;
+
+ p = handshake_compose_ctrl(lp, LDC_NACK, LDC_VERS,
+ &ver, sizeof(ver), &new_tail);
+ if (p) {
+ ldcdbg(HS, "SEND VER NACK maj[%u] min[%u]\n",
+ ver.major, ver.minor);
+
+ return send_tx_packet(lp, p, new_tail);
+ }
+ return -EBUSY;
+}
+
+static int send_version_ack(struct ldc_channel *lp,
+ struct ldc_version *vp)
+{
+ struct ldc_packet *p;
+ unsigned long new_tail;
+
+ p = handshake_compose_ctrl(lp, LDC_ACK, LDC_VERS,
+ vp, sizeof(*vp), &new_tail);
+ if (p) {
+ ldcdbg(HS, "SEND VER ACK maj[%u] min[%u]\n",
+ vp->major, vp->minor);
+
+ return send_tx_packet(lp, p, new_tail);
+ }
+ return -EBUSY;
+}
+
+static int send_rts(struct ldc_channel *lp)
+{
+ struct ldc_packet *p;
+ unsigned long new_tail;
+
+ p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RTS, NULL, 0,
+ &new_tail);
+ if (p) {
+ p->env = lp->cfg.mode;
+ p->seqid = 0;
+ lp->rcv_nxt = 0;
+
+ ldcdbg(HS, "SEND RTS env[0x%x] seqid[0x%x]\n",
+ p->env, p->seqid);
+
+ return send_tx_packet(lp, p, new_tail);
+ }
+ return -EBUSY;
+}
+
+static int send_rtr(struct ldc_channel *lp)
+{
+ struct ldc_packet *p;
+ unsigned long new_tail;
+
+ p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RTR, NULL, 0,
+ &new_tail);
+ if (p) {
+ p->env = lp->cfg.mode;
+ p->seqid = 0;
+
+ ldcdbg(HS, "SEND RTR env[0x%x] seqid[0x%x]\n",
+ p->env, p->seqid);
+
+ return send_tx_packet(lp, p, new_tail);
+ }
+ return -EBUSY;
+}
+
+static int send_rdx(struct ldc_channel *lp)
+{
+ struct ldc_packet *p;
+ unsigned long new_tail;
+
+ p = handshake_compose_ctrl(lp, LDC_INFO, LDC_RDX, NULL, 0,
+ &new_tail);
+ if (p) {
+ p->env = 0;
+ p->seqid = ++lp->snd_nxt;
+ p->u.r.ackid = lp->rcv_nxt;
+
+ ldcdbg(HS, "SEND RDX env[0x%x] seqid[0x%x] ackid[0x%x]\n",
+ p->env, p->seqid, p->u.r.ackid);
+
+ return send_tx_packet(lp, p, new_tail);
+ }
+ return -EBUSY;
+}
+
+static int send_data_nack(struct ldc_channel *lp, struct ldc_packet *data_pkt)
+{
+ struct ldc_packet *p;
+ unsigned long new_tail;
+ int err;
+
+ p = data_get_tx_packet(lp, &new_tail);
+ if (!p)
+ return -EBUSY;
+ memset(p, 0, sizeof(*p));
+ p->type = data_pkt->type;
+ p->stype = LDC_NACK;
+ p->ctrl = data_pkt->ctrl & LDC_CTRL_MSK;
+ p->seqid = lp->snd_nxt + 1;
+ p->u.r.ackid = lp->rcv_nxt;
+
+ ldcdbg(HS, "SEND DATA NACK type[0x%x] ctl[0x%x] seq[0x%x] ack[0x%x]\n",
+ p->type, p->ctrl, p->seqid, p->u.r.ackid);
+
+ err = send_tx_packet(lp, p, new_tail);
+ if (!err)
+ lp->snd_nxt++;
+
+ return err;
+}
+
+static int ldc_abort(struct ldc_channel *lp)
+{
+ unsigned long hv_err;
+
+ ldcdbg(STATE, "ABORT\n");
+
+ /* We report but do not act upon the hypervisor errors because
+ * there really isn't much we can do if they fail at this point.
+ */
+ hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+ if (hv_err)
+ printk(KERN_ERR PFX "ldc_abort: "
+ "sun4v_ldc_tx_qconf(%lx,%lx,%lx) failed, err=%lu\n",
+ lp->id, lp->tx_ra, lp->tx_num_entries, hv_err);
+
+ hv_err = sun4v_ldc_tx_get_state(lp->id,
+ &lp->tx_head,
+ &lp->tx_tail,
+ &lp->chan_state);
+ if (hv_err)
+ printk(KERN_ERR PFX "ldc_abort: "
+ "sun4v_ldc_tx_get_state(%lx,...) failed, err=%lu\n",
+ lp->id, hv_err);
+
+ hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+ if (hv_err)
+ printk(KERN_ERR PFX "ldc_abort: "
+ "sun4v_ldc_rx_qconf(%lx,%lx,%lx) failed, err=%lu\n",
+ lp->id, lp->rx_ra, lp->rx_num_entries, hv_err);
+
+ /* Refetch the RX queue state as well, because we could be invoked
+ * here in the queue processing context.
+ */
+ hv_err = sun4v_ldc_rx_get_state(lp->id,
+ &lp->rx_head,
+ &lp->rx_tail,
+ &lp->chan_state);
+ if (hv_err)
+ printk(KERN_ERR PFX "ldc_abort: "
+ "sun4v_ldc_rx_get_state(%lx,...) failed, err=%lu\n",
+ lp->id, hv_err);
+
+ return -ECONNRESET;
+}
+
+static struct ldc_version *find_by_major(u16 major)
+{
+ struct ldc_version *ret = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ver_arr); i++) {
+ struct ldc_version *v = &ver_arr[i];
+ if (v->major <= major) {
+ ret = v;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int process_ver_info(struct ldc_channel *lp, struct ldc_version *vp)
+{
+ struct ldc_version *vap;
+ int err;
+
+ ldcdbg(HS, "GOT VERSION INFO major[%x] minor[%x]\n",
+ vp->major, vp->minor);
+
+ if (lp->hs_state == LDC_HS_GOTVERS) {
+ lp->hs_state = LDC_HS_OPEN;
+ memset(&lp->ver, 0, sizeof(lp->ver));
+ }
+
+ vap = find_by_major(vp->major);
+ if (!vap) {
+ err = send_version_nack(lp, 0, 0);
+ } else if (vap->major != vp->major) {
+ err = send_version_nack(lp, vap->major, vap->minor);
+ } else {
+ struct ldc_version ver = *vp;
+ if (ver.minor > vap->minor)
+ ver.minor = vap->minor;
+ err = send_version_ack(lp, &ver);
+ if (!err) {
+ lp->ver = ver;
+ lp->hs_state = LDC_HS_GOTVERS;
+ }
+ }
+ if (err)
+ return ldc_abort(lp);
+
+ return 0;
+}
+
+static int process_ver_ack(struct ldc_channel *lp, struct ldc_version *vp)
+{
+ ldcdbg(HS, "GOT VERSION ACK major[%x] minor[%x]\n",
+ vp->major, vp->minor);
+
+ if (lp->hs_state == LDC_HS_GOTVERS) {
+ if (lp->ver.major != vp->major ||
+ lp->ver.minor != vp->minor)
+ return ldc_abort(lp);
+ } else {
+ lp->ver = *vp;
+ lp->hs_state = LDC_HS_GOTVERS;
+ }
+ if (send_rts(lp))
+ return ldc_abort(lp);
+ return 0;
+}
+
+static int process_ver_nack(struct ldc_channel *lp, struct ldc_version *vp)
+{
+ struct ldc_version *vap;
+
+ if ((vp->major == 0 && vp->minor == 0) ||
+ !(vap = find_by_major(vp->major))) {
+ return ldc_abort(lp);
+ } else {
+ struct ldc_packet *p;
+ unsigned long new_tail;
+
+ p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+ vap, sizeof(*vap),
+ &new_tail);
+ if (p)
+ return send_tx_packet(lp, p, new_tail);
+ else
+ return ldc_abort(lp);
+ }
+}
+
+static int process_version(struct ldc_channel *lp,
+ struct ldc_packet *p)
+{
+ struct ldc_version *vp;
+
+ vp = (struct ldc_version *) p->u.u_data;
+
+ switch (p->stype) {
+ case LDC_INFO:
+ return process_ver_info(lp, vp);
+
+ case LDC_ACK:
+ return process_ver_ack(lp, vp);
+
+ case LDC_NACK:
+ return process_ver_nack(lp, vp);
+
+ default:
+ return ldc_abort(lp);
+ }
+}
+
+static int process_rts(struct ldc_channel *lp,
+ struct ldc_packet *p)
+{
+ ldcdbg(HS, "GOT RTS stype[%x] seqid[%x] env[%x]\n",
+ p->stype, p->seqid, p->env);
+
+ if (p->stype != LDC_INFO ||
+ lp->hs_state != LDC_HS_GOTVERS ||
+ p->env != lp->cfg.mode)
+ return ldc_abort(lp);
+
+ lp->snd_nxt = p->seqid;
+ lp->rcv_nxt = p->seqid;
+ lp->hs_state = LDC_HS_SENTRTR;
+ if (send_rtr(lp))
+ return ldc_abort(lp);
+
+ return 0;
+}
+
+static int process_rtr(struct ldc_channel *lp,
+ struct ldc_packet *p)
+{
+ ldcdbg(HS, "GOT RTR stype[%x] seqid[%x] env[%x]\n",
+ p->stype, p->seqid, p->env);
+
+ if (p->stype != LDC_INFO ||
+ p->env != lp->cfg.mode)
+ return ldc_abort(lp);
+
+ lp->snd_nxt = p->seqid;
+ lp->hs_state = LDC_HS_COMPLETE;
+ ldc_set_state(lp, LDC_STATE_CONNECTED);
+ send_rdx(lp);
+
+ return LDC_EVENT_UP;
+}
+
+static int rx_seq_ok(struct ldc_channel *lp, u32 seqid)
+{
+ return lp->rcv_nxt + 1 == seqid;
+}
+
+static int process_rdx(struct ldc_channel *lp,
+ struct ldc_packet *p)
+{
+ ldcdbg(HS, "GOT RDX stype[%x] seqid[%x] env[%x] ackid[%x]\n",
+ p->stype, p->seqid, p->env, p->u.r.ackid);
+
+ if (p->stype != LDC_INFO ||
+ !(rx_seq_ok(lp, p->seqid)))
+ return ldc_abort(lp);
+
+ lp->rcv_nxt = p->seqid;
+
+ lp->hs_state = LDC_HS_COMPLETE;
+ ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+ return LDC_EVENT_UP;
+}
+
+static int process_control_frame(struct ldc_channel *lp,
+ struct ldc_packet *p)
+{
+ switch (p->ctrl) {
+ case LDC_VERS:
+ return process_version(lp, p);
+
+ case LDC_RTS:
+ return process_rts(lp, p);
+
+ case LDC_RTR:
+ return process_rtr(lp, p);
+
+ case LDC_RDX:
+ return process_rdx(lp, p);
+
+ default:
+ return ldc_abort(lp);
+ }
+}
+
+static int process_error_frame(struct ldc_channel *lp,
+ struct ldc_packet *p)
+{
+ return ldc_abort(lp);
+}
+
+static int process_data_ack(struct ldc_channel *lp,
+ struct ldc_packet *ack)
+{
+ unsigned long head = lp->tx_acked;
+ u32 ackid = ack->u.r.ackid;
+
+ while (1) {
+ struct ldc_packet *p = lp->tx_base + (head / LDC_PACKET_SIZE);
+
+ head = tx_advance(lp, head);
+
+ if (p->seqid == ackid) {
+ lp->tx_acked = head;
+ return 0;
+ }
+ if (head == lp->tx_tail)
+ return ldc_abort(lp);
+ }
+
+ return 0;
+}
+
+static void send_events(struct ldc_channel *lp, unsigned int event_mask)
+{
+ if (event_mask & LDC_EVENT_RESET)
+ lp->cfg.event(lp->event_arg, LDC_EVENT_RESET);
+ if (event_mask & LDC_EVENT_UP)
+ lp->cfg.event(lp->event_arg, LDC_EVENT_UP);
+ if (event_mask & LDC_EVENT_DATA_READY)
+ lp->cfg.event(lp->event_arg, LDC_EVENT_DATA_READY);
+}
+
+static irqreturn_t ldc_rx(int irq, void *dev_id)
+{
+ struct ldc_channel *lp = dev_id;
+ unsigned long orig_state, hv_err, flags;
+ unsigned int event_mask;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ orig_state = lp->chan_state;
+ hv_err = sun4v_ldc_rx_get_state(lp->id,
+ &lp->rx_head,
+ &lp->rx_tail,
+ &lp->chan_state);
+
+ ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
+ orig_state, lp->chan_state, lp->rx_head, lp->rx_tail);
+
+ event_mask = 0;
+
+ if (lp->cfg.mode == LDC_MODE_RAW &&
+ lp->chan_state == LDC_CHANNEL_UP) {
+ lp->hs_state = LDC_HS_COMPLETE;
+ ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+ event_mask |= LDC_EVENT_UP;
+
+ orig_state = lp->chan_state;
+ }
+
+ /* If we are in reset state, flush the RX queue and ignore
+ * everything.
+ */
+ if (lp->flags & LDC_FLAG_RESET) {
+ (void) __set_rx_head(lp, lp->rx_tail);
+ goto out;
+ }
+
+ /* Once we finish the handshake, we let the ldc_read()
+ * paths do all of the control frame and state management.
+ * Just trigger the callback.
+ */
+ if (lp->hs_state == LDC_HS_COMPLETE) {
+handshake_complete:
+ if (lp->chan_state != orig_state) {
+ unsigned int event = LDC_EVENT_RESET;
+
+ if (lp->chan_state == LDC_CHANNEL_UP)
+ event = LDC_EVENT_UP;
+
+ event_mask |= event;
+ }
+ if (lp->rx_head != lp->rx_tail)
+ event_mask |= LDC_EVENT_DATA_READY;
+
+ goto out;
+ }
+
+ if (lp->chan_state != orig_state)
+ goto out;
+
+ while (lp->rx_head != lp->rx_tail) {
+ struct ldc_packet *p;
+ unsigned long new;
+ int err;
+
+ p = lp->rx_base + (lp->rx_head / LDC_PACKET_SIZE);
+
+ switch (p->type) {
+ case LDC_CTRL:
+ err = process_control_frame(lp, p);
+ if (err > 0)
+ event_mask |= err;
+ break;
+
+ case LDC_DATA:
+ event_mask |= LDC_EVENT_DATA_READY;
+ err = 0;
+ break;
+
+ case LDC_ERR:
+ err = process_error_frame(lp, p);
+ break;
+
+ default:
+ err = ldc_abort(lp);
+ break;
+ }
+
+ if (err < 0)
+ break;
+
+ new = lp->rx_head;
+ new += LDC_PACKET_SIZE;
+ if (new == (lp->rx_num_entries * LDC_PACKET_SIZE))
+ new = 0;
+ lp->rx_head = new;
+
+ err = __set_rx_head(lp, new);
+ if (err < 0) {
+ (void) ldc_abort(lp);
+ break;
+ }
+ if (lp->hs_state == LDC_HS_COMPLETE)
+ goto handshake_complete;
+ }
+
+out:
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ send_events(lp, event_mask);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ldc_tx(int irq, void *dev_id)
+{
+ struct ldc_channel *lp = dev_id;
+ unsigned long flags, hv_err, orig_state;
+ unsigned int event_mask = 0;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ orig_state = lp->chan_state;
+ hv_err = sun4v_ldc_tx_get_state(lp->id,
+ &lp->tx_head,
+ &lp->tx_tail,
+ &lp->chan_state);
+
+ ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
+ orig_state, lp->chan_state, lp->tx_head, lp->tx_tail);
+
+ if (lp->cfg.mode == LDC_MODE_RAW &&
+ lp->chan_state == LDC_CHANNEL_UP) {
+ lp->hs_state = LDC_HS_COMPLETE;
+ ldc_set_state(lp, LDC_STATE_CONNECTED);
+
+ event_mask |= LDC_EVENT_UP;
+ }
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ send_events(lp, event_mask);
+
+ return IRQ_HANDLED;
+}
+
+/* XXX ldc_alloc() and ldc_free() needs to run under a mutex so
+ * XXX that addition and removal from the ldc_channel_list has
+ * XXX atomicity, otherwise the __ldc_channel_exists() check is
+ * XXX totally pointless as another thread can slip into ldc_alloc()
+ * XXX and add a channel with the same ID. There also needs to be
+ * XXX a spinlock for ldc_channel_list.
+ */
+static HLIST_HEAD(ldc_channel_list);
+
+static int __ldc_channel_exists(unsigned long id)
+{
+ struct ldc_channel *lp;
+ struct hlist_node *n;
+
+ hlist_for_each_entry(lp, n, &ldc_channel_list, list) {
+ if (lp->id == id)
+ return 1;
+ }
+ return 0;
+}
+
+static int alloc_queue(const char *name, unsigned long num_entries,
+ struct ldc_packet **base, unsigned long *ra)
+{
+ unsigned long size, order;
+ void *q;
+
+ size = num_entries * LDC_PACKET_SIZE;
+ order = get_order(size);
+
+ q = (void *) __get_free_pages(GFP_KERNEL, order);
+ if (!q) {
+ printk(KERN_ERR PFX "Alloc of %s queue failed with "
+ "size=%lu order=%lu\n", name, size, order);
+ return -ENOMEM;
+ }
+
+ memset(q, 0, PAGE_SIZE << order);
+
+ *base = q;
+ *ra = __pa(q);
+
+ return 0;
+}
+
+static void free_queue(unsigned long num_entries, struct ldc_packet *q)
+{
+ unsigned long size, order;
+
+ if (!q)
+ return;
+
+ size = num_entries * LDC_PACKET_SIZE;
+ order = get_order(size);
+
+ free_pages((unsigned long)q, order);
+}
+
+/* XXX Make this configurable... XXX */
+#define LDC_IOTABLE_SIZE (8 * 1024)
+
+static int ldc_iommu_init(struct ldc_channel *lp)
+{
+ unsigned long sz, num_tsb_entries, tsbsize, order;
+ struct ldc_iommu *iommu = &lp->iommu;
+ struct ldc_mtable_entry *table;
+ unsigned long hv_err;
+ int err;
+
+ num_tsb_entries = LDC_IOTABLE_SIZE;
+ tsbsize = num_tsb_entries * sizeof(struct ldc_mtable_entry);
+
+ spin_lock_init(&iommu->lock);
+
+ sz = num_tsb_entries / 8;
+ sz = (sz + 7UL) & ~7UL;
+ iommu->arena.map = kzalloc(sz, GFP_KERNEL);
+ if (!iommu->arena.map) {
+ printk(KERN_ERR PFX "Alloc of arena map failed, sz=%lu\n", sz);
+ return -ENOMEM;
+ }
+
+ iommu->arena.limit = num_tsb_entries;
+
+ order = get_order(tsbsize);
+
+ table = (struct ldc_mtable_entry *)
+ __get_free_pages(GFP_KERNEL, order);
+ err = -ENOMEM;
+ if (!table) {
+ printk(KERN_ERR PFX "Alloc of MTE table failed, "
+ "size=%lu order=%lu\n", tsbsize, order);
+ goto out_free_map;
+ }
+
+ memset(table, 0, PAGE_SIZE << order);
+
+ iommu->page_table = table;
+
+ hv_err = sun4v_ldc_set_map_table(lp->id, __pa(table),
+ num_tsb_entries);
+ err = -EINVAL;
+ if (hv_err)
+ goto out_free_table;
+
+ return 0;
+
+out_free_table:
+ free_pages((unsigned long) table, order);
+ iommu->page_table = NULL;
+
+out_free_map:
+ kfree(iommu->arena.map);
+ iommu->arena.map = NULL;
+
+ return err;
+}
+
+static void ldc_iommu_release(struct ldc_channel *lp)
+{
+ struct ldc_iommu *iommu = &lp->iommu;
+ unsigned long num_tsb_entries, tsbsize, order;
+
+ (void) sun4v_ldc_set_map_table(lp->id, 0, 0);
+
+ num_tsb_entries = iommu->arena.limit;
+ tsbsize = num_tsb_entries * sizeof(struct ldc_mtable_entry);
+ order = get_order(tsbsize);
+
+ free_pages((unsigned long) iommu->page_table, order);
+ iommu->page_table = NULL;
+
+ kfree(iommu->arena.map);
+ iommu->arena.map = NULL;
+}
+
+struct ldc_channel *ldc_alloc(unsigned long id,
+ const struct ldc_channel_config *cfgp,
+ void *event_arg)
+{
+ struct ldc_channel *lp;
+ const struct ldc_mode_ops *mops;
+ unsigned long dummy1, dummy2, hv_err;
+ u8 mss, *mssbuf;
+ int err;
+
+ err = -ENODEV;
+ if (!ldom_domaining_enabled)
+ goto out_err;
+
+ err = -EINVAL;
+ if (!cfgp)
+ goto out_err;
+
+ switch (cfgp->mode) {
+ case LDC_MODE_RAW:
+ mops = &raw_ops;
+ mss = LDC_PACKET_SIZE;
+ break;
+
+ case LDC_MODE_UNRELIABLE:
+ mops = &nonraw_ops;
+ mss = LDC_PACKET_SIZE - 8;
+ break;
+
+ case LDC_MODE_STREAM:
+ mops = &stream_ops;
+ mss = LDC_PACKET_SIZE - 8 - 8;
+ break;
+
+ default:
+ goto out_err;
+ }
+
+ if (!cfgp->event || !event_arg || !cfgp->rx_irq || !cfgp->tx_irq)
+ goto out_err;
+
+ hv_err = sun4v_ldc_tx_qinfo(id, &dummy1, &dummy2);
+ err = -ENODEV;
+ if (hv_err == HV_ECHANNEL)
+ goto out_err;
+
+ err = -EEXIST;
+ if (__ldc_channel_exists(id))
+ goto out_err;
+
+ mssbuf = NULL;
+
+ lp = kzalloc(sizeof(*lp), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!lp)
+ goto out_err;
+
+ spin_lock_init(&lp->lock);
+
+ lp->id = id;
+
+ err = ldc_iommu_init(lp);
+ if (err)
+ goto out_free_ldc;
+
+ lp->mops = mops;
+ lp->mss = mss;
+
+ lp->cfg = *cfgp;
+ if (!lp->cfg.mtu)
+ lp->cfg.mtu = LDC_DEFAULT_MTU;
+
+ if (lp->cfg.mode == LDC_MODE_STREAM) {
+ mssbuf = kzalloc(lp->cfg.mtu, GFP_KERNEL);
+ if (!mssbuf) {
+ err = -ENOMEM;
+ goto out_free_iommu;
+ }
+ lp->mssbuf = mssbuf;
+ }
+
+ lp->event_arg = event_arg;
+
+ /* XXX allow setting via ldc_channel_config to override defaults
+ * XXX or use some formula based upon mtu
+ */
+ lp->tx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+ lp->rx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+
+ err = alloc_queue("TX", lp->tx_num_entries,
+ &lp->tx_base, &lp->tx_ra);
+ if (err)
+ goto out_free_mssbuf;
+
+ err = alloc_queue("RX", lp->rx_num_entries,
+ &lp->rx_base, &lp->rx_ra);
+ if (err)
+ goto out_free_txq;
+
+ lp->flags |= LDC_FLAG_ALLOCED_QUEUES;
+
+ lp->hs_state = LDC_HS_CLOSED;
+ ldc_set_state(lp, LDC_STATE_INIT);
+
+ INIT_HLIST_NODE(&lp->list);
+ hlist_add_head(&lp->list, &ldc_channel_list);
+
+ INIT_HLIST_HEAD(&lp->mh_list);
+
+ return lp;
+
+out_free_txq:
+ free_queue(lp->tx_num_entries, lp->tx_base);
+
+out_free_mssbuf:
+ if (mssbuf)
+ kfree(mssbuf);
+
+out_free_iommu:
+ ldc_iommu_release(lp);
+
+out_free_ldc:
+ kfree(lp);
+
+out_err:
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(ldc_alloc);
+
+void ldc_free(struct ldc_channel *lp)
+{
+ if (lp->flags & LDC_FLAG_REGISTERED_IRQS) {
+ free_irq(lp->cfg.rx_irq, lp);
+ free_irq(lp->cfg.tx_irq, lp);
+ }
+
+ if (lp->flags & LDC_FLAG_REGISTERED_QUEUES) {
+ sun4v_ldc_tx_qconf(lp->id, 0, 0);
+ sun4v_ldc_rx_qconf(lp->id, 0, 0);
+ lp->flags &= ~LDC_FLAG_REGISTERED_QUEUES;
+ }
+ if (lp->flags & LDC_FLAG_ALLOCED_QUEUES) {
+ free_queue(lp->tx_num_entries, lp->tx_base);
+ free_queue(lp->rx_num_entries, lp->rx_base);
+ lp->flags &= ~LDC_FLAG_ALLOCED_QUEUES;
+ }
+
+ hlist_del(&lp->list);
+
+ if (lp->mssbuf)
+ kfree(lp->mssbuf);
+
+ ldc_iommu_release(lp);
+
+ kfree(lp);
+}
+EXPORT_SYMBOL(ldc_free);
+
+/* Bind the channel. This registers the LDC queues with
+ * the hypervisor and puts the channel into a pseudo-listening
+ * state. This does not initiate a handshake, ldc_connect() does
+ * that.
+ */
+int ldc_bind(struct ldc_channel *lp, const char *name)
+{
+ unsigned long hv_err, flags;
+ int err = -EINVAL;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ if (!name)
+ goto out_err;
+
+ if (lp->state != LDC_STATE_INIT)
+ goto out_err;
+
+ snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
+ snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
+
+ err = request_irq(lp->cfg.rx_irq, ldc_rx,
+ IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+ lp->rx_irq_name, lp);
+ if (err)
+ goto out_err;
+
+ err = request_irq(lp->cfg.tx_irq, ldc_tx,
+ IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+ lp->tx_irq_name, lp);
+ if (err)
+ goto out_free_rx_irq;
+
+
+ lp->flags |= LDC_FLAG_REGISTERED_IRQS;
+
+ err = -ENODEV;
+ hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+ if (hv_err)
+ goto out_free_tx_irq;
+
+ hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+ if (hv_err)
+ goto out_free_tx_irq;
+
+ hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+ if (hv_err)
+ goto out_unmap_tx;
+
+ hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+ if (hv_err)
+ goto out_unmap_tx;
+
+ lp->flags |= LDC_FLAG_REGISTERED_QUEUES;
+
+ hv_err = sun4v_ldc_tx_get_state(lp->id,
+ &lp->tx_head,
+ &lp->tx_tail,
+ &lp->chan_state);
+ err = -EBUSY;
+ if (hv_err)
+ goto out_unmap_rx;
+
+ lp->tx_acked = lp->tx_head;
+
+ lp->hs_state = LDC_HS_OPEN;
+ ldc_set_state(lp, LDC_STATE_BOUND);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return 0;
+
+out_unmap_rx:
+ lp->flags &= ~LDC_FLAG_REGISTERED_QUEUES;
+ sun4v_ldc_rx_qconf(lp->id, 0, 0);
+
+out_unmap_tx:
+ sun4v_ldc_tx_qconf(lp->id, 0, 0);
+
+out_free_tx_irq:
+ lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
+ free_irq(lp->cfg.tx_irq, lp);
+
+out_free_rx_irq:
+ free_irq(lp->cfg.rx_irq, lp);
+
+out_err:
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL(ldc_bind);
+
+int ldc_connect(struct ldc_channel *lp)
+{
+ unsigned long flags;
+ int err;
+
+ if (lp->cfg.mode == LDC_MODE_RAW)
+ return -EINVAL;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
+ !(lp->flags & LDC_FLAG_REGISTERED_QUEUES) ||
+ lp->hs_state != LDC_HS_OPEN)
+ err = -EINVAL;
+ else
+ err = start_handshake(lp);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL(ldc_connect);
+
+int ldc_disconnect(struct ldc_channel *lp)
+{
+ unsigned long hv_err, flags;
+ int err;
+
+ if (lp->cfg.mode == LDC_MODE_RAW)
+ return -EINVAL;
+
+ if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
+ !(lp->flags & LDC_FLAG_REGISTERED_QUEUES))
+ return -EINVAL;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ err = -ENODEV;
+ hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
+ if (hv_err)
+ goto out_err;
+
+ hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
+ if (hv_err)
+ goto out_err;
+
+ hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
+ if (hv_err)
+ goto out_err;
+
+ hv_err = sun4v_ldc_rx_qconf(lp->id, lp->rx_ra, lp->rx_num_entries);
+ if (hv_err)
+ goto out_err;
+
+ ldc_set_state(lp, LDC_STATE_BOUND);
+ lp->hs_state = LDC_HS_OPEN;
+ lp->flags |= LDC_FLAG_RESET;
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return 0;
+
+out_err:
+ sun4v_ldc_tx_qconf(lp->id, 0, 0);
+ sun4v_ldc_rx_qconf(lp->id, 0, 0);
+ free_irq(lp->cfg.tx_irq, lp);
+ free_irq(lp->cfg.rx_irq, lp);
+ lp->flags &= ~(LDC_FLAG_REGISTERED_IRQS |
+ LDC_FLAG_REGISTERED_QUEUES);
+ ldc_set_state(lp, LDC_STATE_INIT);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL(ldc_disconnect);
+
+int ldc_state(struct ldc_channel *lp)
+{
+ return lp->state;
+}
+EXPORT_SYMBOL(ldc_state);
+
+static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size)
+{
+ struct ldc_packet *p;
+ unsigned long new_tail;
+ int err;
+
+ if (size > LDC_PACKET_SIZE)
+ return -EMSGSIZE;
+
+ p = data_get_tx_packet(lp, &new_tail);
+ if (!p)
+ return -EAGAIN;
+
+ memcpy(p, buf, size);
+
+ err = send_tx_packet(lp, p, new_tail);
+ if (!err)
+ err = size;
+
+ return err;
+}
+
+static int read_raw(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+ struct ldc_packet *p;
+ unsigned long hv_err, new;
+ int err;
+
+ if (size < LDC_PACKET_SIZE)
+ return -EINVAL;
+
+ hv_err = sun4v_ldc_rx_get_state(lp->id,
+ &lp->rx_head,
+ &lp->rx_tail,
+ &lp->chan_state);
+ if (hv_err)
+ return ldc_abort(lp);
+
+ if (lp->chan_state == LDC_CHANNEL_DOWN ||
+ lp->chan_state == LDC_CHANNEL_RESETTING)
+ return -ECONNRESET;
+
+ if (lp->rx_head == lp->rx_tail)
+ return 0;
+
+ p = lp->rx_base + (lp->rx_head / LDC_PACKET_SIZE);
+ memcpy(buf, p, LDC_PACKET_SIZE);
+
+ new = rx_advance(lp, lp->rx_head);
+ lp->rx_head = new;
+
+ err = __set_rx_head(lp, new);
+ if (err < 0)
+ err = -ECONNRESET;
+ else
+ err = LDC_PACKET_SIZE;
+
+ return err;
+}
+
+static const struct ldc_mode_ops raw_ops = {
+ .write = write_raw,
+ .read = read_raw,
+};
+
+static int write_nonraw(struct ldc_channel *lp, const void *buf,
+ unsigned int size)
+{
+ unsigned long hv_err, tail;
+ unsigned int copied;
+ u32 seq;
+ int err;
+
+ hv_err = sun4v_ldc_tx_get_state(lp->id, &lp->tx_head, &lp->tx_tail,
+ &lp->chan_state);
+ if (unlikely(hv_err))
+ return -EBUSY;
+
+ if (unlikely(lp->chan_state != LDC_CHANNEL_UP))
+ return ldc_abort(lp);
+
+ if (!tx_has_space_for(lp, size))
+ return -EAGAIN;
+
+ seq = lp->snd_nxt;
+ copied = 0;
+ tail = lp->tx_tail;
+ while (copied < size) {
+ struct ldc_packet *p = lp->tx_base + (tail / LDC_PACKET_SIZE);
+ u8 *data = ((lp->cfg.mode == LDC_MODE_UNRELIABLE) ?
+ p->u.u_data :
+ p->u.r.r_data);
+ int data_len;
+
+ p->type = LDC_DATA;
+ p->stype = LDC_INFO;
+ p->ctrl = 0;
+
+ data_len = size - copied;
+ if (data_len > lp->mss)
+ data_len = lp->mss;
+
+ BUG_ON(data_len > LDC_LEN);
+
+ p->env = (data_len |
+ (copied == 0 ? LDC_START : 0) |
+ (data_len == size - copied ? LDC_STOP : 0));
+
+ p->seqid = ++seq;
+
+ ldcdbg(DATA, "SENT DATA [%02x:%02x:%02x:%02x:%08x]\n",
+ p->type,
+ p->stype,
+ p->ctrl,
+ p->env,
+ p->seqid);
+
+ memcpy(data, buf, data_len);
+ buf += data_len;
+ copied += data_len;
+
+ tail = tx_advance(lp, tail);
+ }
+
+ err = set_tx_tail(lp, tail);
+ if (!err) {
+ lp->snd_nxt = seq;
+ err = size;
+ }
+
+ return err;
+}
+
+static int rx_bad_seq(struct ldc_channel *lp, struct ldc_packet *p,
+ struct ldc_packet *first_frag)
+{
+ int err;
+
+ if (first_frag)
+ lp->rcv_nxt = first_frag->seqid - 1;
+
+ err = send_data_nack(lp, p);
+ if (err)
+ return err;
+
+ err = __set_rx_head(lp, lp->rx_tail);
+ if (err < 0)
+ return ldc_abort(lp);
+
+ return 0;
+}
+
+static int data_ack_nack(struct ldc_channel *lp, struct ldc_packet *p)
+{
+ if (p->stype & LDC_ACK) {
+ int err = process_data_ack(lp, p);
+ if (err)
+ return err;
+ }
+ if (p->stype & LDC_NACK)
+ return ldc_abort(lp);
+
+ return 0;
+}
+
+static int rx_data_wait(struct ldc_channel *lp, unsigned long cur_head)
+{
+ unsigned long dummy;
+ int limit = 1000;
+
+ ldcdbg(DATA, "DATA WAIT cur_head[%lx] rx_head[%lx] rx_tail[%lx]\n",
+ cur_head, lp->rx_head, lp->rx_tail);
+ while (limit-- > 0) {
+ unsigned long hv_err;
+
+ hv_err = sun4v_ldc_rx_get_state(lp->id,
+ &dummy,
+ &lp->rx_tail,
+ &lp->chan_state);
+ if (hv_err)
+ return ldc_abort(lp);
+
+ if (lp->chan_state == LDC_CHANNEL_DOWN ||
+ lp->chan_state == LDC_CHANNEL_RESETTING)
+ return -ECONNRESET;
+
+ if (cur_head != lp->rx_tail) {
+ ldcdbg(DATA, "DATA WAIT DONE "
+ "head[%lx] tail[%lx] chan_state[%lx]\n",
+ dummy, lp->rx_tail, lp->chan_state);
+ return 0;
+ }
+
+ udelay(1);
+ }
+ return -EAGAIN;
+}
+
+static int rx_set_head(struct ldc_channel *lp, unsigned long head)
+{
+ int err = __set_rx_head(lp, head);
+
+ if (err < 0)
+ return ldc_abort(lp);
+
+ lp->rx_head = head;
+ return 0;
+}
+
+static void send_data_ack(struct ldc_channel *lp)
+{
+ unsigned long new_tail;
+ struct ldc_packet *p;
+
+ p = data_get_tx_packet(lp, &new_tail);
+ if (likely(p)) {
+ int err;
+
+ memset(p, 0, sizeof(*p));
+ p->type = LDC_DATA;
+ p->stype = LDC_ACK;
+ p->ctrl = 0;
+ p->seqid = lp->snd_nxt + 1;
+ p->u.r.ackid = lp->rcv_nxt;
+
+ err = send_tx_packet(lp, p, new_tail);
+ if (!err)
+ lp->snd_nxt++;
+ }
+}
+
+static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+ struct ldc_packet *first_frag;
+ unsigned long hv_err, new;
+ int err, copied;
+
+ hv_err = sun4v_ldc_rx_get_state(lp->id,
+ &lp->rx_head,
+ &lp->rx_tail,
+ &lp->chan_state);
+ if (hv_err)
+ return ldc_abort(lp);
+
+ if (lp->chan_state == LDC_CHANNEL_DOWN ||
+ lp->chan_state == LDC_CHANNEL_RESETTING)
+ return -ECONNRESET;
+
+ if (lp->rx_head == lp->rx_tail)
+ return 0;
+
+ first_frag = NULL;
+ copied = err = 0;
+ new = lp->rx_head;
+ while (1) {
+ struct ldc_packet *p;
+ int pkt_len;
+
+ BUG_ON(new == lp->rx_tail);
+ p = lp->rx_base + (new / LDC_PACKET_SIZE);
+
+ ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x:%08x] "
+ "rcv_nxt[%08x]\n",
+ p->type,
+ p->stype,
+ p->ctrl,
+ p->env,
+ p->seqid,
+ p->u.r.ackid,
+ lp->rcv_nxt);
+
+ if (unlikely(!rx_seq_ok(lp, p->seqid))) {
+ err = rx_bad_seq(lp, p, first_frag);
+ copied = 0;
+ break;
+ }
+
+ if (p->type & LDC_CTRL) {
+ err = process_control_frame(lp, p);
+ if (err < 0)
+ break;
+ err = 0;
+ }
+
+ lp->rcv_nxt = p->seqid;
+
+ if (!(p->type & LDC_DATA)) {
+ new = rx_advance(lp, new);
+ goto no_data;
+ }
+ if (p->stype & (LDC_ACK | LDC_NACK)) {
+ err = data_ack_nack(lp, p);
+ if (err)
+ break;
+ }
+ if (!(p->stype & LDC_INFO)) {
+ new = rx_advance(lp, new);
+ err = rx_set_head(lp, new);
+ if (err)
+ break;
+ goto no_data;
+ }
+
+ pkt_len = p->env & LDC_LEN;
+
+ /* Every initial packet starts with the START bit set.
+ *
+ * Singleton packets will have both START+STOP set.
+ *
+ * Fragments will have START set in the first frame, STOP
+ * set in the last frame, and neither bit set in middle
+ * frames of the packet.
+ *
+ * Therefore if we are at the beginning of a packet and
+ * we don't see START, or we are in the middle of a fragmented
+ * packet and do see START, we are unsynchronized and should
+ * flush the RX queue.
+ */
+ if ((first_frag == NULL && !(p->env & LDC_START)) ||
+ (first_frag != NULL && (p->env & LDC_START))) {
+ if (!first_frag)
+ new = rx_advance(lp, new);
+
+ err = rx_set_head(lp, new);
+ if (err)
+ break;
+
+ if (!first_frag)
+ goto no_data;
+ }
+ if (!first_frag)
+ first_frag = p;
+
+ if (pkt_len > size - copied) {
+ /* User didn't give us a big enough buffer,
+ * what to do? This is a pretty serious error.
+ *
+ * Since we haven't updated the RX ring head to
+ * consume any of the packets, signal the error
+ * to the user and just leave the RX ring alone.
+ *
+ * This seems the best behavior because this allows
+ * a user of the LDC layer to start with a small
+ * RX buffer for ldc_read() calls and use -EMSGSIZE
+ * as a cue to enlarge it's read buffer.
+ */
+ err = -EMSGSIZE;
+ break;
+ }
+
+ /* Ok, we are gonna eat this one. */
+ new = rx_advance(lp, new);
+
+ memcpy(buf,
+ (lp->cfg.mode == LDC_MODE_UNRELIABLE ?
+ p->u.u_data : p->u.r.r_data), pkt_len);
+ buf += pkt_len;
+ copied += pkt_len;
+
+ if (p->env & LDC_STOP)
+ break;
+
+no_data:
+ if (new == lp->rx_tail) {
+ err = rx_data_wait(lp, new);
+ if (err)
+ break;
+ }
+ }
+
+ if (!err)
+ err = rx_set_head(lp, new);
+
+ if (err && first_frag)
+ lp->rcv_nxt = first_frag->seqid - 1;
+
+ if (!err) {
+ err = copied;
+ if (err > 0 && lp->cfg.mode != LDC_MODE_UNRELIABLE)
+ send_data_ack(lp);
+ }
+
+ return err;
+}
+
+static const struct ldc_mode_ops nonraw_ops = {
+ .write = write_nonraw,
+ .read = read_nonraw,
+};
+
+static int write_stream(struct ldc_channel *lp, const void *buf,
+ unsigned int size)
+{
+ if (size > lp->cfg.mtu)
+ size = lp->cfg.mtu;
+ return write_nonraw(lp, buf, size);
+}
+
+static int read_stream(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+ if (!lp->mssbuf_len) {
+ int err = read_nonraw(lp, lp->mssbuf, lp->cfg.mtu);
+ if (err < 0)
+ return err;
+
+ lp->mssbuf_len = err;
+ lp->mssbuf_off = 0;
+ }
+
+ if (size > lp->mssbuf_len)
+ size = lp->mssbuf_len;
+ memcpy(buf, lp->mssbuf + lp->mssbuf_off, size);
+
+ lp->mssbuf_off += size;
+ lp->mssbuf_len -= size;
+
+ return size;
+}
+
+static const struct ldc_mode_ops stream_ops = {
+ .write = write_stream,
+ .read = read_stream,
+};
+
+int ldc_write(struct ldc_channel *lp, const void *buf, unsigned int size)
+{
+ unsigned long flags;
+ int err;
+
+ if (!buf)
+ return -EINVAL;
+
+ if (!size)
+ return 0;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ if (lp->hs_state != LDC_HS_COMPLETE)
+ err = -ENOTCONN;
+ else
+ err = lp->mops->write(lp, buf, size);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL(ldc_write);
+
+int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size)
+{
+ unsigned long flags;
+ int err;
+
+ if (!buf)
+ return -EINVAL;
+
+ if (!size)
+ return 0;
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ if (lp->hs_state != LDC_HS_COMPLETE)
+ err = -ENOTCONN;
+ else
+ err = lp->mops->read(lp, buf, size);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return err;
+}
+EXPORT_SYMBOL(ldc_read);
+
+static long arena_alloc(struct ldc_iommu *iommu, unsigned long npages)
+{
+ struct iommu_arena *arena = &iommu->arena;
+ unsigned long n, i, start, end, limit;
+ int pass;
+
+ limit = arena->limit;
+ start = arena->hint;
+ pass = 0;
+
+again:
+ n = find_next_zero_bit(arena->map, limit, start);
+ end = n + npages;
+ if (unlikely(end >= limit)) {
+ if (likely(pass < 1)) {
+ limit = start;
+ start = 0;
+ pass++;
+ goto again;
+ } else {
+ /* Scanned the whole thing, give up. */
+ return -1;
+ }
+ }
+
+ for (i = n; i < end; i++) {
+ if (test_bit(i, arena->map)) {
+ start = i + 1;
+ goto again;
+ }
+ }
+
+ for (i = n; i < end; i++)
+ __set_bit(i, arena->map);
+
+ arena->hint = end;
+
+ return n;
+}
+
+#define COOKIE_PGSZ_CODE 0xf000000000000000ULL
+#define COOKIE_PGSZ_CODE_SHIFT 60ULL
+
+static u64 pagesize_code(void)
+{
+ switch (PAGE_SIZE) {
+ default:
+ case (8ULL * 1024ULL):
+ return 0;
+ case (64ULL * 1024ULL):
+ return 1;
+ case (512ULL * 1024ULL):
+ return 2;
+ case (4ULL * 1024ULL * 1024ULL):
+ return 3;
+ case (32ULL * 1024ULL * 1024ULL):
+ return 4;
+ case (256ULL * 1024ULL * 1024ULL):
+ return 5;
+ }
+}
+
+static u64 make_cookie(u64 index, u64 pgsz_code, u64 page_offset)
+{
+ return ((pgsz_code << COOKIE_PGSZ_CODE_SHIFT) |
+ (index << PAGE_SHIFT) |
+ page_offset);
+}
+
+static u64 cookie_to_index(u64 cookie, unsigned long *shift)
+{
+ u64 szcode = cookie >> COOKIE_PGSZ_CODE_SHIFT;
+
+ cookie &= ~COOKIE_PGSZ_CODE;
+
+ *shift = szcode * 3;
+
+ return (cookie >> (13ULL + (szcode * 3ULL)));
+}
+
+static struct ldc_mtable_entry *alloc_npages(struct ldc_iommu *iommu,
+ unsigned long npages)
+{
+ long entry;
+
+ entry = arena_alloc(iommu, npages);
+ if (unlikely(entry < 0))
+ return NULL;
+
+ return iommu->page_table + entry;
+}
+
+static u64 perm_to_mte(unsigned int map_perm)
+{
+ u64 mte_base;
+
+ mte_base = pagesize_code();
+
+ if (map_perm & LDC_MAP_SHADOW) {
+ if (map_perm & LDC_MAP_R)
+ mte_base |= LDC_MTE_COPY_R;
+ if (map_perm & LDC_MAP_W)
+ mte_base |= LDC_MTE_COPY_W;
+ }
+ if (map_perm & LDC_MAP_DIRECT) {
+ if (map_perm & LDC_MAP_R)
+ mte_base |= LDC_MTE_READ;
+ if (map_perm & LDC_MAP_W)
+ mte_base |= LDC_MTE_WRITE;
+ if (map_perm & LDC_MAP_X)
+ mte_base |= LDC_MTE_EXEC;
+ }
+ if (map_perm & LDC_MAP_IO) {
+ if (map_perm & LDC_MAP_R)
+ mte_base |= LDC_MTE_IOMMU_R;
+ if (map_perm & LDC_MAP_W)
+ mte_base |= LDC_MTE_IOMMU_W;
+ }
+
+ return mte_base;
+}
+
+static int pages_in_region(unsigned long base, long len)
+{
+ int count = 0;
+
+ do {
+ unsigned long new = (base + PAGE_SIZE) & PAGE_MASK;
+
+ len -= (new - base);
+ base = new;
+ count++;
+ } while (len > 0);
+
+ return count;
+}
+
+struct cookie_state {
+ struct ldc_mtable_entry *page_table;
+ struct ldc_trans_cookie *cookies;
+ u64 mte_base;
+ u64 prev_cookie;
+ u32 pte_idx;
+ u32 nc;
+};
+
+static void fill_cookies(struct cookie_state *sp, unsigned long pa,
+ unsigned long off, unsigned long len)
+{
+ do {
+ unsigned long tlen, new = pa + PAGE_SIZE;
+ u64 this_cookie;
+
+ sp->page_table[sp->pte_idx].mte = sp->mte_base | pa;
+
+ tlen = PAGE_SIZE;
+ if (off)
+ tlen = PAGE_SIZE - off;
+ if (tlen > len)
+ tlen = len;
+
+ this_cookie = make_cookie(sp->pte_idx,
+ pagesize_code(), off);
+
+ off = 0;
+
+ if (this_cookie == sp->prev_cookie) {
+ sp->cookies[sp->nc - 1].cookie_size += tlen;
+ } else {
+ sp->cookies[sp->nc].cookie_addr = this_cookie;
+ sp->cookies[sp->nc].cookie_size = tlen;
+ sp->nc++;
+ }
+ sp->prev_cookie = this_cookie + tlen;
+
+ sp->pte_idx++;
+
+ len -= tlen;
+ pa = new;
+ } while (len > 0);
+}
+
+static int sg_count_one(struct scatterlist *sg)
+{
+ unsigned long base = page_to_pfn(sg->page) << PAGE_SHIFT;
+ long len = sg->length;
+
+ if ((sg->offset | len) & (8UL - 1))
+ return -EFAULT;
+
+ return pages_in_region(base + sg->offset, len);
+}
+
+static int sg_count_pages(struct scatterlist *sg, int num_sg)
+{
+ int count;
+ int i;
+
+ count = 0;
+ for (i = 0; i < num_sg; i++) {
+ int err = sg_count_one(sg + i);
+ if (err < 0)
+ return err;
+ count += err;
+ }
+
+ return count;
+}
+
+int ldc_map_sg(struct ldc_channel *lp,
+ struct scatterlist *sg, int num_sg,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm)
+{
+ unsigned long i, npages, flags;
+ struct ldc_mtable_entry *base;
+ struct cookie_state state;
+ struct ldc_iommu *iommu;
+ int err;
+
+ if (map_perm & ~LDC_MAP_ALL)
+ return -EINVAL;
+
+ err = sg_count_pages(sg, num_sg);
+ if (err < 0)
+ return err;
+
+ npages = err;
+ if (err > ncookies)
+ return -EMSGSIZE;
+
+ iommu = &lp->iommu;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ base = alloc_npages(iommu, npages);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+ if (!base)
+ return -ENOMEM;
+
+ state.page_table = iommu->page_table;
+ state.cookies = cookies;
+ state.mte_base = perm_to_mte(map_perm);
+ state.prev_cookie = ~(u64)0;
+ state.pte_idx = (base - iommu->page_table);
+ state.nc = 0;
+
+ for (i = 0; i < num_sg; i++)
+ fill_cookies(&state, page_to_pfn(sg[i].page) << PAGE_SHIFT,
+ sg[i].offset, sg[i].length);
+
+ return state.nc;
+}
+EXPORT_SYMBOL(ldc_map_sg);
+
+int ldc_map_single(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm)
+{
+ unsigned long npages, pa, flags;
+ struct ldc_mtable_entry *base;
+ struct cookie_state state;
+ struct ldc_iommu *iommu;
+
+ if ((map_perm & ~LDC_MAP_ALL) || (ncookies < 1))
+ return -EINVAL;
+
+ pa = __pa(buf);
+ if ((pa | len) & (8UL - 1))
+ return -EFAULT;
+
+ npages = pages_in_region(pa, len);
+
+ iommu = &lp->iommu;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ base = alloc_npages(iommu, npages);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+ if (!base)
+ return -ENOMEM;
+
+ state.page_table = iommu->page_table;
+ state.cookies = cookies;
+ state.mte_base = perm_to_mte(map_perm);
+ state.prev_cookie = ~(u64)0;
+ state.pte_idx = (base - iommu->page_table);
+ state.nc = 0;
+ fill_cookies(&state, (pa & PAGE_MASK), (pa & ~PAGE_MASK), len);
+ BUG_ON(state.nc != 1);
+
+ return state.nc;
+}
+EXPORT_SYMBOL(ldc_map_single);
+
+static void free_npages(unsigned long id, struct ldc_iommu *iommu,
+ u64 cookie, u64 size)
+{
+ struct iommu_arena *arena = &iommu->arena;
+ unsigned long i, shift, index, npages;
+ struct ldc_mtable_entry *base;
+
+ npages = PAGE_ALIGN(((cookie & ~PAGE_MASK) + size)) >> PAGE_SHIFT;
+ index = cookie_to_index(cookie, &shift);
+ base = iommu->page_table + index;
+
+ BUG_ON(index > arena->limit ||
+ (index + npages) > arena->limit);
+
+ for (i = 0; i < npages; i++) {
+ if (base->cookie)
+ sun4v_ldc_revoke(id, cookie + (i << shift),
+ base->cookie);
+ base->mte = 0;
+ __clear_bit(index + i, arena->map);
+ }
+}
+
+void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ struct ldc_iommu *iommu = &lp->iommu;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ for (i = 0; i < ncookies; i++) {
+ u64 addr = cookies[i].cookie_addr;
+ u64 size = cookies[i].cookie_size;
+
+ free_npages(lp->id, iommu, addr, size);
+ }
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+EXPORT_SYMBOL(ldc_unmap);
+
+int ldc_copy(struct ldc_channel *lp, int copy_dir,
+ void *buf, unsigned int len, unsigned long offset,
+ struct ldc_trans_cookie *cookies, int ncookies)
+{
+ unsigned int orig_len;
+ unsigned long ra;
+ int i;
+
+ if (copy_dir != LDC_COPY_IN && copy_dir != LDC_COPY_OUT) {
+ printk(KERN_ERR PFX "ldc_copy: ID[%lu] Bad copy_dir[%d]\n",
+ lp->id, copy_dir);
+ return -EINVAL;
+ }
+
+ ra = __pa(buf);
+ if ((ra | len | offset) & (8UL - 1)) {
+ printk(KERN_ERR PFX "ldc_copy: ID[%lu] Unaligned buffer "
+ "ra[%lx] len[%x] offset[%lx]\n",
+ lp->id, ra, len, offset);
+ return -EFAULT;
+ }
+
+ if (lp->hs_state != LDC_HS_COMPLETE ||
+ (lp->flags & LDC_FLAG_RESET)) {
+ printk(KERN_ERR PFX "ldc_copy: ID[%lu] Link down hs_state[%x] "
+ "flags[%x]\n", lp->id, lp->hs_state, lp->flags);
+ return -ECONNRESET;
+ }
+
+ orig_len = len;
+ for (i = 0; i < ncookies; i++) {
+ unsigned long cookie_raddr = cookies[i].cookie_addr;
+ unsigned long this_len = cookies[i].cookie_size;
+ unsigned long actual_len;
+
+ if (unlikely(offset)) {
+ unsigned long this_off = offset;
+
+ if (this_off > this_len)
+ this_off = this_len;
+
+ offset -= this_off;
+ this_len -= this_off;
+ if (!this_len)
+ continue;
+ cookie_raddr += this_off;
+ }
+
+ if (this_len > len)
+ this_len = len;
+
+ while (1) {
+ unsigned long hv_err;
+
+ hv_err = sun4v_ldc_copy(lp->id, copy_dir,
+ cookie_raddr, ra,
+ this_len, &actual_len);
+ if (unlikely(hv_err)) {
+ printk(KERN_ERR PFX "ldc_copy: ID[%lu] "
+ "HV error %lu\n",
+ lp->id, hv_err);
+ if (lp->hs_state != LDC_HS_COMPLETE ||
+ (lp->flags & LDC_FLAG_RESET))
+ return -ECONNRESET;
+ else
+ return -EFAULT;
+ }
+
+ cookie_raddr += actual_len;
+ ra += actual_len;
+ len -= actual_len;
+ if (actual_len == this_len)
+ break;
+
+ this_len -= actual_len;
+ }
+
+ if (!len)
+ break;
+ }
+
+ /* It is caller policy what to do about short copies.
+ * For example, a networking driver can declare the
+ * packet a runt and drop it.
+ */
+
+ return orig_len - len;
+}
+EXPORT_SYMBOL(ldc_copy);
+
+void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+ struct ldc_trans_cookie *cookies, int *ncookies,
+ unsigned int map_perm)
+{
+ void *buf;
+ int err;
+
+ if (len & (8UL - 1))
+ return ERR_PTR(-EINVAL);
+
+ buf = kzalloc(len, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ err = ldc_map_single(lp, buf, len, cookies, *ncookies, map_perm);
+ if (err < 0) {
+ kfree(buf);
+ return ERR_PTR(err);
+ }
+ *ncookies = err;
+
+ return buf;
+}
+EXPORT_SYMBOL(ldc_alloc_exp_dring);
+
+void ldc_free_exp_dring(struct ldc_channel *lp, void *buf, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies)
+{
+ ldc_unmap(lp, cookies, ncookies);
+ kfree(buf);
+}
+EXPORT_SYMBOL(ldc_free_exp_dring);
+
+static int __init ldc_init(void)
+{
+ unsigned long major, minor;
+ struct mdesc_handle *hp;
+ const u64 *v;
+ u64 mp;
+
+ hp = mdesc_grab();
+ if (!hp)
+ return -ENODEV;
+
+ mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
+ if (mp == MDESC_NODE_NULL)
+ return -ENODEV;
+
+ v = mdesc_get_property(hp, mp, "domaining-enabled", NULL);
+ if (!v)
+ return -ENODEV;
+
+ major = 1;
+ minor = 0;
+ if (sun4v_hvapi_register(HV_GRP_LDOM, major, &minor)) {
+ printk(KERN_INFO PFX "Could not register LDOM hvapi.\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "%s", version);
+
+ if (!*v) {
+ printk(KERN_INFO PFX "Domaining disabled.\n");
+ return -ENODEV;
+ }
+ ldom_domaining_enabled = 1;
+
+ return 0;
+}
+
+core_initcall(ldc_init);
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index f0e16045fb16..de5310ffdb48 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -6,6 +6,9 @@
#include <linux/types.h>
#include <linux/bootmem.h>
#include <linux/log2.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
#include <asm/hypervisor.h>
#include <asm/mdesc.h>
@@ -29,7 +32,7 @@ struct mdesc_hdr {
u32 node_sz; /* node block size */
u32 name_sz; /* name block size */
u32 data_sz; /* data block size */
-};
+} __attribute__((aligned(16)));
struct mdesc_elem {
u8 tag;
@@ -53,306 +56,396 @@ struct mdesc_elem {
} d;
};
-static struct mdesc_hdr *main_mdesc;
-static struct mdesc_node *allnodes;
-
-static struct mdesc_node *allnodes_tail;
-static unsigned int unique_id;
+struct mdesc_mem_ops {
+ struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
+ void (*free)(struct mdesc_handle *handle);
+};
-static struct mdesc_node **mdesc_hash;
-static unsigned int mdesc_hash_size;
+struct mdesc_handle {
+ struct list_head list;
+ struct mdesc_mem_ops *mops;
+ void *self_base;
+ atomic_t refcnt;
+ unsigned int handle_size;
+ struct mdesc_hdr mdesc;
+};
-static inline unsigned int node_hashfn(u64 node)
+static void mdesc_handle_init(struct mdesc_handle *hp,
+ unsigned int handle_size,
+ void *base)
{
- return ((unsigned int) (node ^ (node >> 8) ^ (node >> 16)))
- & (mdesc_hash_size - 1);
+ BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
+
+ memset(hp, 0, handle_size);
+ INIT_LIST_HEAD(&hp->list);
+ hp->self_base = base;
+ atomic_set(&hp->refcnt, 1);
+ hp->handle_size = handle_size;
}
-static inline void hash_node(struct mdesc_node *mp)
+static struct mdesc_handle *mdesc_bootmem_alloc(unsigned int mdesc_size)
{
- struct mdesc_node **head = &mdesc_hash[node_hashfn(mp->node)];
+ struct mdesc_handle *hp;
+ unsigned int handle_size, alloc_size;
- mp->hash_next = *head;
- *head = mp;
+ handle_size = (sizeof(struct mdesc_handle) -
+ sizeof(struct mdesc_hdr) +
+ mdesc_size);
+ alloc_size = PAGE_ALIGN(handle_size);
- if (allnodes_tail) {
- allnodes_tail->allnodes_next = mp;
- allnodes_tail = mp;
- } else {
- allnodes = allnodes_tail = mp;
- }
+ hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
+ if (hp)
+ mdesc_handle_init(hp, handle_size, hp);
+
+ return hp;
}
-static struct mdesc_node *find_node(u64 node)
+static void mdesc_bootmem_free(struct mdesc_handle *hp)
{
- struct mdesc_node *mp = mdesc_hash[node_hashfn(node)];
+ unsigned int alloc_size, handle_size = hp->handle_size;
+ unsigned long start, end;
- while (mp) {
- if (mp->node == node)
- return mp;
+ BUG_ON(atomic_read(&hp->refcnt) != 0);
+ BUG_ON(!list_empty(&hp->list));
- mp = mp->hash_next;
+ alloc_size = PAGE_ALIGN(handle_size);
+
+ start = (unsigned long) hp;
+ end = start + alloc_size;
+
+ while (start < end) {
+ struct page *p;
+
+ p = virt_to_page(start);
+ ClearPageReserved(p);
+ __free_page(p);
+ start += PAGE_SIZE;
}
- return NULL;
}
-struct property *md_find_property(const struct mdesc_node *mp,
- const char *name,
- int *lenp)
+static struct mdesc_mem_ops bootmem_mdesc_memops = {
+ .alloc = mdesc_bootmem_alloc,
+ .free = mdesc_bootmem_free,
+};
+
+static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
{
- struct property *pp;
+ unsigned int handle_size;
+ void *base;
- for (pp = mp->properties; pp != 0; pp = pp->next) {
- if (strcasecmp(pp->name, name) == 0) {
- if (lenp)
- *lenp = pp->length;
- break;
- }
+ handle_size = (sizeof(struct mdesc_handle) -
+ sizeof(struct mdesc_hdr) +
+ mdesc_size);
+
+ base = kmalloc(handle_size + 15, GFP_KERNEL);
+ if (base) {
+ struct mdesc_handle *hp;
+ unsigned long addr;
+
+ addr = (unsigned long)base;
+ addr = (addr + 15UL) & ~15UL;
+ hp = (struct mdesc_handle *) addr;
+
+ mdesc_handle_init(hp, handle_size, base);
+ return hp;
}
- return pp;
+
+ return NULL;
}
-EXPORT_SYMBOL(md_find_property);
-/*
- * Find a property with a given name for a given node
- * and return the value.
- */
-const void *md_get_property(const struct mdesc_node *mp, const char *name,
- int *lenp)
+static void mdesc_kfree(struct mdesc_handle *hp)
{
- struct property *pp = md_find_property(mp, name, lenp);
- return pp ? pp->value : NULL;
+ BUG_ON(atomic_read(&hp->refcnt) != 0);
+ BUG_ON(!list_empty(&hp->list));
+
+ kfree(hp->self_base);
}
-EXPORT_SYMBOL(md_get_property);
-struct mdesc_node *md_find_node_by_name(struct mdesc_node *from,
- const char *name)
+static struct mdesc_mem_ops kmalloc_mdesc_memops = {
+ .alloc = mdesc_kmalloc,
+ .free = mdesc_kfree,
+};
+
+static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
+ struct mdesc_mem_ops *mops)
{
- struct mdesc_node *mp;
+ struct mdesc_handle *hp = mops->alloc(mdesc_size);
- mp = from ? from->allnodes_next : allnodes;
- for (; mp != NULL; mp = mp->allnodes_next) {
- if (strcmp(mp->name, name) == 0)
- break;
- }
- return mp;
-}
-EXPORT_SYMBOL(md_find_node_by_name);
+ if (hp)
+ hp->mops = mops;
-static unsigned int mdesc_early_allocated;
+ return hp;
+}
-static void * __init mdesc_early_alloc(unsigned long size)
+static void mdesc_free(struct mdesc_handle *hp)
{
- void *ret;
+ hp->mops->free(hp);
+}
- ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
- if (ret == NULL) {
- prom_printf("MDESC: alloc of %lu bytes failed.\n", size);
- prom_halt();
- }
+static struct mdesc_handle *cur_mdesc;
+static LIST_HEAD(mdesc_zombie_list);
+static DEFINE_SPINLOCK(mdesc_lock);
- memset(ret, 0, size);
+struct mdesc_handle *mdesc_grab(void)
+{
+ struct mdesc_handle *hp;
+ unsigned long flags;
- mdesc_early_allocated += size;
+ spin_lock_irqsave(&mdesc_lock, flags);
+ hp = cur_mdesc;
+ if (hp)
+ atomic_inc(&hp->refcnt);
+ spin_unlock_irqrestore(&mdesc_lock, flags);
- return ret;
+ return hp;
}
+EXPORT_SYMBOL(mdesc_grab);
-static unsigned int __init count_arcs(struct mdesc_elem *ep)
+void mdesc_release(struct mdesc_handle *hp)
{
- unsigned int ret = 0;
+ unsigned long flags;
- ep++;
- while (ep->tag != MD_NODE_END) {
- if (ep->tag == MD_PROP_ARC)
- ret++;
- ep++;
+ spin_lock_irqsave(&mdesc_lock, flags);
+ if (atomic_dec_and_test(&hp->refcnt)) {
+ list_del_init(&hp->list);
+ hp->mops->free(hp);
}
- return ret;
+ spin_unlock_irqrestore(&mdesc_lock, flags);
}
+EXPORT_SYMBOL(mdesc_release);
-static void __init mdesc_node_alloc(u64 node, struct mdesc_elem *ep, const char *names)
+void mdesc_update(void)
{
- unsigned int num_arcs = count_arcs(ep);
- struct mdesc_node *mp;
+ unsigned long len, real_len, status;
+ struct mdesc_handle *hp, *orig_hp;
+ unsigned long flags;
+
+ (void) sun4v_mach_desc(0UL, 0UL, &len);
+
+ hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
+ if (!hp) {
+ printk(KERN_ERR "MD: mdesc alloc fails\n");
+ return;
+ }
+
+ status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
+ if (status != HV_EOK || real_len > len) {
+ printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
+ status);
+ atomic_dec(&hp->refcnt);
+ mdesc_free(hp);
+ return;
+ }
- mp = mdesc_early_alloc(sizeof(*mp) +
- (num_arcs * sizeof(struct mdesc_arc)));
- mp->name = names + ep->name_offset;
- mp->node = node;
- mp->unique_id = unique_id++;
- mp->num_arcs = num_arcs;
+ spin_lock_irqsave(&mdesc_lock, flags);
+ orig_hp = cur_mdesc;
+ cur_mdesc = hp;
- hash_node(mp);
+ if (atomic_dec_and_test(&orig_hp->refcnt))
+ mdesc_free(orig_hp);
+ else
+ list_add(&orig_hp->list, &mdesc_zombie_list);
+ spin_unlock_irqrestore(&mdesc_lock, flags);
}
-static inline struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
+static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
{
return (struct mdesc_elem *) (mdesc + 1);
}
-static inline void *name_block(struct mdesc_hdr *mdesc)
+static void *name_block(struct mdesc_hdr *mdesc)
{
return ((void *) node_block(mdesc)) + mdesc->node_sz;
}
-static inline void *data_block(struct mdesc_hdr *mdesc)
+static void *data_block(struct mdesc_hdr *mdesc)
{
return ((void *) name_block(mdesc)) + mdesc->name_sz;
}
-/* In order to avoid recursion (the graph can be very deep) we use a
- * two pass algorithm. First we allocate all the nodes and hash them.
- * Then we iterate over each node, filling in the arcs and properties.
- */
-static void __init build_all_nodes(struct mdesc_hdr *mdesc)
+u64 mdesc_node_by_name(struct mdesc_handle *hp,
+ u64 from_node, const char *name)
{
- struct mdesc_elem *start, *ep;
- struct mdesc_node *mp;
- const char *names;
- void *data;
- u64 last_node;
+ struct mdesc_elem *ep = node_block(&hp->mdesc);
+ const char *names = name_block(&hp->mdesc);
+ u64 last_node = hp->mdesc.node_sz / 16;
+ u64 ret;
+
+ if (from_node == MDESC_NODE_NULL) {
+ ret = from_node = 0;
+ } else if (from_node >= last_node) {
+ return MDESC_NODE_NULL;
+ } else {
+ ret = ep[from_node].d.val;
+ }
- start = ep = node_block(mdesc);
- last_node = mdesc->node_sz / 16;
+ while (ret < last_node) {
+ if (ep[ret].tag != MD_NODE)
+ return MDESC_NODE_NULL;
+ if (!strcmp(names + ep[ret].name_offset, name))
+ break;
+ ret = ep[ret].d.val;
+ }
+ if (ret >= last_node)
+ ret = MDESC_NODE_NULL;
+ return ret;
+}
+EXPORT_SYMBOL(mdesc_node_by_name);
- names = name_block(mdesc);
+const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
+ const char *name, int *lenp)
+{
+ const char *names = name_block(&hp->mdesc);
+ u64 last_node = hp->mdesc.node_sz / 16;
+ void *data = data_block(&hp->mdesc);
+ struct mdesc_elem *ep;
- while (1) {
- u64 node = ep - start;
+ if (node == MDESC_NODE_NULL || node >= last_node)
+ return NULL;
- if (ep->tag == MD_LIST_END)
+ ep = node_block(&hp->mdesc) + node;
+ ep++;
+ for (; ep->tag != MD_NODE_END; ep++) {
+ void *val = NULL;
+ int len = 0;
+
+ switch (ep->tag) {
+ case MD_PROP_VAL:
+ val = &ep->d.val;
+ len = 8;
break;
- if (ep->tag != MD_NODE) {
- prom_printf("MDESC: Inconsistent element list.\n");
- prom_halt();
- }
-
- mdesc_node_alloc(node, ep, names);
+ case MD_PROP_STR:
+ case MD_PROP_DATA:
+ val = data + ep->d.data.data_offset;
+ len = ep->d.data.data_len;
+ break;
- if (ep->d.val >= last_node) {
- printk("MDESC: Warning, early break out of node scan.\n");
- printk("MDESC: Next node [%lu] last_node [%lu].\n",
- node, last_node);
+ default:
break;
}
+ if (!val)
+ continue;
- ep = start + ep->d.val;
+ if (!strcmp(names + ep->name_offset, name)) {
+ if (lenp)
+ *lenp = len;
+ return val;
+ }
}
- data = data_block(mdesc);
- for (mp = allnodes; mp; mp = mp->allnodes_next) {
- struct mdesc_elem *ep = start + mp->node;
- struct property **link = &mp->properties;
- unsigned int this_arc = 0;
-
- ep++;
- while (ep->tag != MD_NODE_END) {
- switch (ep->tag) {
- case MD_PROP_ARC: {
- struct mdesc_node *target;
-
- if (this_arc >= mp->num_arcs) {
- prom_printf("MDESC: ARC overrun [%u:%u]\n",
- this_arc, mp->num_arcs);
- prom_halt();
- }
- target = find_node(ep->d.val);
- if (!target) {
- printk("MDESC: Warning, arc points to "
- "missing node, ignoring.\n");
- break;
- }
- mp->arcs[this_arc].name =
- (names + ep->name_offset);
- mp->arcs[this_arc].arc = target;
- this_arc++;
- break;
- }
+ return NULL;
+}
+EXPORT_SYMBOL(mdesc_get_property);
- case MD_PROP_VAL:
- case MD_PROP_STR:
- case MD_PROP_DATA: {
- struct property *p = mdesc_early_alloc(sizeof(*p));
-
- p->unique_id = unique_id++;
- p->name = (char *) names + ep->name_offset;
- if (ep->tag == MD_PROP_VAL) {
- p->value = &ep->d.val;
- p->length = 8;
- } else {
- p->value = data + ep->d.data.data_offset;
- p->length = ep->d.data.data_len;
- }
- *link = p;
- link = &p->next;
- break;
- }
+u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
+{
+ struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+ const char *names = name_block(&hp->mdesc);
+ u64 last_node = hp->mdesc.node_sz / 16;
- case MD_NOOP:
- break;
+ if (from == MDESC_NODE_NULL || from >= last_node)
+ return MDESC_NODE_NULL;
- default:
- printk("MDESC: Warning, ignoring unknown tag type %02x\n",
- ep->tag);
- }
- ep++;
- }
+ ep = base + from;
+
+ ep++;
+ for (; ep->tag != MD_NODE_END; ep++) {
+ if (ep->tag != MD_PROP_ARC)
+ continue;
+
+ if (strcmp(names + ep->name_offset, arc_type))
+ continue;
+
+ return ep - base;
}
+
+ return MDESC_NODE_NULL;
}
+EXPORT_SYMBOL(mdesc_next_arc);
-static unsigned int __init count_nodes(struct mdesc_hdr *mdesc)
+u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
{
- struct mdesc_elem *ep = node_block(mdesc);
- struct mdesc_elem *end;
- unsigned int cnt = 0;
-
- end = ((void *)ep) + mdesc->node_sz;
- while (ep < end) {
- if (ep->tag == MD_NODE)
- cnt++;
- ep++;
- }
- return cnt;
+ struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+
+ ep = base + arc;
+
+ return ep->d.val;
+}
+EXPORT_SYMBOL(mdesc_arc_target);
+
+const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
+{
+ struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+ const char *names = name_block(&hp->mdesc);
+ u64 last_node = hp->mdesc.node_sz / 16;
+
+ if (node == MDESC_NODE_NULL || node >= last_node)
+ return NULL;
+
+ ep = base + node;
+ if (ep->tag != MD_NODE)
+ return NULL;
+
+ return names + ep->name_offset;
}
+EXPORT_SYMBOL(mdesc_node_name);
static void __init report_platform_properties(void)
{
- struct mdesc_node *pn = md_find_node_by_name(NULL, "platform");
+ struct mdesc_handle *hp = mdesc_grab();
+ u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
const char *s;
const u64 *v;
- if (!pn) {
+ if (pn == MDESC_NODE_NULL) {
prom_printf("No platform node in machine-description.\n");
prom_halt();
}
- s = md_get_property(pn, "banner-name", NULL);
+ s = mdesc_get_property(hp, pn, "banner-name", NULL);
printk("PLATFORM: banner-name [%s]\n", s);
- s = md_get_property(pn, "name", NULL);
+ s = mdesc_get_property(hp, pn, "name", NULL);
printk("PLATFORM: name [%s]\n", s);
- v = md_get_property(pn, "hostid", NULL);
+ v = mdesc_get_property(hp, pn, "hostid", NULL);
if (v)
printk("PLATFORM: hostid [%08lx]\n", *v);
- v = md_get_property(pn, "serial#", NULL);
+ v = mdesc_get_property(hp, pn, "serial#", NULL);
if (v)
printk("PLATFORM: serial# [%08lx]\n", *v);
- v = md_get_property(pn, "stick-frequency", NULL);
+ v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
printk("PLATFORM: stick-frequency [%08lx]\n", *v);
- v = md_get_property(pn, "mac-address", NULL);
+ v = mdesc_get_property(hp, pn, "mac-address", NULL);
if (v)
printk("PLATFORM: mac-address [%lx]\n", *v);
- v = md_get_property(pn, "watchdog-resolution", NULL);
+ v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
if (v)
printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
- v = md_get_property(pn, "watchdog-max-timeout", NULL);
+ v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
if (v)
printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
- v = md_get_property(pn, "max-cpus", NULL);
+ v = mdesc_get_property(hp, pn, "max-cpus", NULL);
if (v)
printk("PLATFORM: max-cpus [%lu]\n", *v);
+
+#ifdef CONFIG_SMP
+ {
+ int max_cpu, i;
+
+ if (v) {
+ max_cpu = *v;
+ if (max_cpu > NR_CPUS)
+ max_cpu = NR_CPUS;
+ } else {
+ max_cpu = NR_CPUS;
+ }
+ for (i = 0; i < max_cpu; i++)
+ cpu_set(i, cpu_possible_map);
+ }
+#endif
+
+ mdesc_release(hp);
}
static int inline find_in_proplist(const char *list, const char *match, int len)
@@ -369,15 +462,17 @@ static int inline find_in_proplist(const char *list, const char *match, int len)
return 0;
}
-static void __init fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_node *mp)
+static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
+ struct mdesc_handle *hp,
+ u64 mp)
{
- const u64 *level = md_get_property(mp, "level", NULL);
- const u64 *size = md_get_property(mp, "size", NULL);
- const u64 *line_size = md_get_property(mp, "line-size", NULL);
+ const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
+ const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
+ const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
const char *type;
int type_len;
- type = md_get_property(mp, "type", &type_len);
+ type = mdesc_get_property(hp, mp, "type", &type_len);
switch (*level) {
case 1:
@@ -400,48 +495,45 @@ static void __init fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_node *mp)
}
if (*level == 1) {
- unsigned int i;
-
- for (i = 0; i < mp->num_arcs; i++) {
- struct mdesc_node *t = mp->arcs[i].arc;
+ u64 a;
- if (strcmp(mp->arcs[i].name, "fwd"))
- continue;
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+ u64 target = mdesc_arc_target(hp, a);
+ const char *name = mdesc_node_name(hp, target);
- if (!strcmp(t->name, "cache"))
- fill_in_one_cache(c, t);
+ if (!strcmp(name, "cache"))
+ fill_in_one_cache(c, hp, target);
}
}
}
-static void __init mark_core_ids(struct mdesc_node *mp, int core_id)
+static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
+ int core_id)
{
- unsigned int i;
+ u64 a;
- for (i = 0; i < mp->num_arcs; i++) {
- struct mdesc_node *t = mp->arcs[i].arc;
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+ u64 t = mdesc_arc_target(hp, a);
+ const char *name;
const u64 *id;
- if (strcmp(mp->arcs[i].name, "back"))
- continue;
-
- if (!strcmp(t->name, "cpu")) {
- id = md_get_property(t, "id", NULL);
+ name = mdesc_node_name(hp, t);
+ if (!strcmp(name, "cpu")) {
+ id = mdesc_get_property(hp, t, "id", NULL);
if (*id < NR_CPUS)
cpu_data(*id).core_id = core_id;
} else {
- unsigned int j;
+ u64 j;
- for (j = 0; j < t->num_arcs; j++) {
- struct mdesc_node *n = t->arcs[j].arc;
+ mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
+ u64 n = mdesc_arc_target(hp, j);
+ const char *n_name;
- if (strcmp(t->arcs[j].name, "back"))
+ n_name = mdesc_node_name(hp, n);
+ if (strcmp(n_name, "cpu"))
continue;
- if (strcmp(n->name, "cpu"))
- continue;
-
- id = md_get_property(n, "id", NULL);
+ id = mdesc_get_property(hp, n, "id", NULL);
if (*id < NR_CPUS)
cpu_data(*id).core_id = core_id;
}
@@ -449,78 +541,81 @@ static void __init mark_core_ids(struct mdesc_node *mp, int core_id)
}
}
-static void __init set_core_ids(void)
+static void __devinit set_core_ids(struct mdesc_handle *hp)
{
- struct mdesc_node *mp;
int idx;
+ u64 mp;
idx = 1;
- md_for_each_node_by_name(mp, "cache") {
- const u64 *level = md_get_property(mp, "level", NULL);
+ mdesc_for_each_node_by_name(hp, mp, "cache") {
+ const u64 *level;
const char *type;
int len;
+ level = mdesc_get_property(hp, mp, "level", NULL);
if (*level != 1)
continue;
- type = md_get_property(mp, "type", &len);
+ type = mdesc_get_property(hp, mp, "type", &len);
if (!find_in_proplist(type, "instn", len))
continue;
- mark_core_ids(mp, idx);
+ mark_core_ids(hp, mp, idx);
idx++;
}
}
-static void __init mark_proc_ids(struct mdesc_node *mp, int proc_id)
+static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
+ int proc_id)
{
- int i;
+ u64 a;
- for (i = 0; i < mp->num_arcs; i++) {
- struct mdesc_node *t = mp->arcs[i].arc;
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+ u64 t = mdesc_arc_target(hp, a);
+ const char *name;
const u64 *id;
- if (strcmp(mp->arcs[i].name, "back"))
- continue;
-
- if (strcmp(t->name, "cpu"))
+ name = mdesc_node_name(hp, t);
+ if (strcmp(name, "cpu"))
continue;
- id = md_get_property(t, "id", NULL);
+ id = mdesc_get_property(hp, t, "id", NULL);
if (*id < NR_CPUS)
cpu_data(*id).proc_id = proc_id;
}
}
-static void __init __set_proc_ids(const char *exec_unit_name)
+static void __devinit __set_proc_ids(struct mdesc_handle *hp,
+ const char *exec_unit_name)
{
- struct mdesc_node *mp;
int idx;
+ u64 mp;
idx = 0;
- md_for_each_node_by_name(mp, exec_unit_name) {
+ mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
const char *type;
int len;
- type = md_get_property(mp, "type", &len);
+ type = mdesc_get_property(hp, mp, "type", &len);
if (!find_in_proplist(type, "int", len) &&
!find_in_proplist(type, "integer", len))
continue;
- mark_proc_ids(mp, idx);
+ mark_proc_ids(hp, mp, idx);
idx++;
}
}
-static void __init set_proc_ids(void)
+static void __devinit set_proc_ids(struct mdesc_handle *hp)
{
- __set_proc_ids("exec_unit");
- __set_proc_ids("exec-unit");
+ __set_proc_ids(hp, "exec_unit");
+ __set_proc_ids(hp, "exec-unit");
}
-static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def)
+static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
+ unsigned char def)
{
u64 val;
@@ -538,35 +633,37 @@ use_default:
*mask = ((1U << def) * 64U) - 1U;
}
-static void __init get_mondo_data(struct mdesc_node *mp, struct trap_per_cpu *tb)
+static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
+ struct trap_per_cpu *tb)
{
const u64 *val;
- val = md_get_property(mp, "q-cpu-mondo-#bits", NULL);
+ val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
- val = md_get_property(mp, "q-dev-mondo-#bits", NULL);
+ val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
- val = md_get_property(mp, "q-resumable-#bits", NULL);
+ val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
get_one_mondo_bits(val, &tb->resum_qmask, 6);
- val = md_get_property(mp, "q-nonresumable-#bits", NULL);
+ val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
}
-static void __init mdesc_fill_in_cpu_data(void)
+void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
{
- struct mdesc_node *mp;
+ struct mdesc_handle *hp = mdesc_grab();
+ u64 mp;
ncpus_probed = 0;
- md_for_each_node_by_name(mp, "cpu") {
- const u64 *id = md_get_property(mp, "id", NULL);
- const u64 *cfreq = md_get_property(mp, "clock-frequency", NULL);
+ mdesc_for_each_node_by_name(hp, mp, "cpu") {
+ const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
+ const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
struct trap_per_cpu *tb;
cpuinfo_sparc *c;
- unsigned int i;
int cpuid;
+ u64 a;
ncpus_probed++;
@@ -575,6 +672,8 @@ static void __init mdesc_fill_in_cpu_data(void)
#ifdef CONFIG_SMP
if (cpuid >= NR_CPUS)
continue;
+ if (!cpu_isset(cpuid, mask))
+ continue;
#else
/* On uniprocessor we only want the values for the
* real physical cpu the kernel booted onto, however
@@ -589,35 +688,30 @@ static void __init mdesc_fill_in_cpu_data(void)
c->clock_tick = *cfreq;
tb = &trap_block[cpuid];
- get_mondo_data(mp, tb);
-
- for (i = 0; i < mp->num_arcs; i++) {
- struct mdesc_node *t = mp->arcs[i].arc;
- unsigned int j;
+ get_mondo_data(hp, mp, tb);
- if (strcmp(mp->arcs[i].name, "fwd"))
- continue;
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+ u64 j, t = mdesc_arc_target(hp, a);
+ const char *t_name;
- if (!strcmp(t->name, "cache")) {
- fill_in_one_cache(c, t);
+ t_name = mdesc_node_name(hp, t);
+ if (!strcmp(t_name, "cache")) {
+ fill_in_one_cache(c, hp, t);
continue;
}
- for (j = 0; j < t->num_arcs; j++) {
- struct mdesc_node *n;
+ mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
+ u64 n = mdesc_arc_target(hp, j);
+ const char *n_name;
- n = t->arcs[j].arc;
- if (strcmp(t->arcs[j].name, "fwd"))
- continue;
-
- if (!strcmp(n->name, "cache"))
- fill_in_one_cache(c, n);
+ n_name = mdesc_node_name(hp, n);
+ if (!strcmp(n_name, "cache"))
+ fill_in_one_cache(c, hp, n);
}
}
#ifdef CONFIG_SMP
cpu_set(cpuid, cpu_present_map);
- cpu_set(cpuid, phys_cpu_present_map);
#endif
c->core_id = 0;
@@ -628,45 +722,43 @@ static void __init mdesc_fill_in_cpu_data(void)
sparc64_multi_core = 1;
#endif
- set_core_ids();
- set_proc_ids();
+ set_core_ids(hp);
+ set_proc_ids(hp);
smp_fill_in_sib_core_maps();
+
+ mdesc_release(hp);
}
void __init sun4v_mdesc_init(void)
{
+ struct mdesc_handle *hp;
unsigned long len, real_len, status;
+ cpumask_t mask;
(void) sun4v_mach_desc(0UL, 0UL, &len);
printk("MDESC: Size is %lu bytes.\n", len);
- main_mdesc = mdesc_early_alloc(len);
+ hp = mdesc_alloc(len, &bootmem_mdesc_memops);
+ if (hp == NULL) {
+ prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
+ prom_halt();
+ }
- status = sun4v_mach_desc(__pa(main_mdesc), len, &real_len);
+ status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
if (status != HV_EOK || real_len > len) {
prom_printf("sun4v_mach_desc fails, err(%lu), "
"len(%lu), real_len(%lu)\n",
status, len, real_len);
+ mdesc_free(hp);
prom_halt();
}
- len = count_nodes(main_mdesc);
- printk("MDESC: %lu nodes.\n", len);
-
- len = roundup_pow_of_two(len);
-
- mdesc_hash = mdesc_early_alloc(len * sizeof(struct mdesc_node *));
- mdesc_hash_size = len;
-
- printk("MDESC: Hash size %lu entries.\n", len);
-
- build_all_nodes(main_mdesc);
-
- printk("MDESC: Built graph with %u bytes of memory.\n",
- mdesc_early_allocated);
+ cur_mdesc = hp;
report_platform_properties();
- mdesc_fill_in_cpu_data();
+
+ cpus_setall(mask);
+ mdesc_fill_in_cpu_data(mask);
}
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 5d6adea3967f..8dd4294ad21e 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -1,7 +1,6 @@
-/* $Id: power.c,v 1.10 2001/12/11 01:57:16 davem Exp $
- * power.c: Power management driver.
+/* power.c: Power management driver.
*
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
@@ -19,6 +18,7 @@
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/io.h>
+#include <asm/power.h>
#include <asm/sstate.h>
#include <linux/unistd.h>
@@ -29,24 +29,26 @@
*/
int scons_pwroff = 1;
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
static void __iomem *power_reg;
static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
static int button_pressed;
-static irqreturn_t power_handler(int irq, void *dev_id)
+void wake_up_powerd(void)
{
if (button_pressed == 0) {
button_pressed = 1;
wake_up(&powerd_wait);
}
+}
+
+static irqreturn_t power_handler(int irq, void *dev_id)
+{
+ wake_up_powerd();
/* FIXME: Check registers for status... */
return IRQ_HANDLED;
}
-#endif /* CONFIG_PCI */
extern void machine_halt(void);
extern void machine_alt_power_off(void);
@@ -56,19 +58,18 @@ void machine_power_off(void)
{
sstate_poweroff();
if (!serial_console || scons_pwroff) {
-#ifdef CONFIG_PCI
if (power_reg) {
/* Both register bits seem to have the
* same effect, so until I figure out
* what the difference is...
*/
writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg);
- } else
-#endif /* CONFIG_PCI */
+ } else {
if (poweroff_method != NULL) {
poweroff_method();
/* not reached */
}
+ }
}
machine_halt();
}
@@ -76,7 +77,6 @@ void machine_power_off(void)
void (*pm_power_off)(void) = machine_power_off;
EXPORT_SYMBOL(pm_power_off);
-#ifdef CONFIG_PCI
static int powerd(void *__unused)
{
static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
@@ -86,7 +86,7 @@ static int powerd(void *__unused)
daemonize("powerd");
add_wait_queue(&powerd_wait, &wait);
-again:
+
for (;;) {
set_task_state(current, TASK_INTERRUPTIBLE);
if (button_pressed)
@@ -100,16 +100,28 @@ again:
/* Ok, down we go... */
button_pressed = 0;
if (kernel_execve("/sbin/shutdown", argv, envp) < 0) {
- printk("powerd: shutdown execution failed\n");
- add_wait_queue(&powerd_wait, &wait);
- goto again;
+ printk(KERN_ERR "powerd: shutdown execution failed\n");
+ machine_power_off();
}
return 0;
}
+int start_powerd(void)
+{
+ int err;
+
+ err = kernel_thread(powerd, NULL, CLONE_FS);
+ if (err < 0)
+ printk(KERN_ERR "power: Failed to start power daemon.\n");
+ else
+ printk(KERN_INFO "power: powerd running.\n");
+
+ return err;
+}
+
static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
{
- if (irq == PCI_IRQ_NONE)
+ if (irq == 0xffffffff)
return 0;
if (!of_find_property(dp, "button", NULL))
return 0;
@@ -130,17 +142,14 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id
poweroff_method = machine_halt; /* able to use the standard halt */
if (has_button_interrupt(irq, op->node)) {
- if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
- printk("Failed to start power daemon.\n");
+ if (start_powerd() < 0)
return 0;
- }
- printk("powerd running.\n");
if (request_irq(irq,
power_handler, 0, "power", NULL) < 0)
- printk("power: Error, cannot register IRQ handler.\n");
+ printk(KERN_ERR "power: Cannot setup IRQ handler.\n");
} else {
- printk("not using powerd.\n");
+ printk(KERN_INFO "power: Not using powerd.\n");
}
return 0;
@@ -164,4 +173,3 @@ void __init power_init(void)
of_register_driver(&power_driver, &of_bus_type);
return;
}
-#endif /* CONFIG_PCI */
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index f5f97e2c669c..93557507ec9f 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -29,6 +29,7 @@
#include <linux/compat.h>
#include <linux/tick.h>
#include <linux/init.h>
+#include <linux/cpu.h>
#include <asm/oplib.h>
#include <asm/uaccess.h>
@@ -49,7 +50,7 @@
/* #define VERBOSE_SHOWREGS */
-static void sparc64_yield(void)
+static void sparc64_yield(int cpu)
{
if (tlb_type != hypervisor)
return;
@@ -57,7 +58,7 @@ static void sparc64_yield(void)
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
- while (!need_resched()) {
+ while (!need_resched() && !cpu_is_offline(cpu)) {
unsigned long pstate;
/* Disable interrupts. */
@@ -68,7 +69,7 @@ static void sparc64_yield(void)
: "=&r" (pstate)
: "i" (PSTATE_IE));
- if (!need_resched())
+ if (!need_resched() && !cpu_is_offline(cpu))
sun4v_cpu_yield();
/* Re-enable interrupts. */
@@ -86,15 +87,25 @@ static void sparc64_yield(void)
/* The idle loop on sparc64. */
void cpu_idle(void)
{
+ int cpu = smp_processor_id();
+
set_thread_flag(TIF_POLLING_NRFLAG);
while(1) {
tick_nohz_stop_sched_tick();
- while (!need_resched())
- sparc64_yield();
+
+ while (!need_resched() && !cpu_is_offline(cpu))
+ sparc64_yield(cpu);
+
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
+
+#ifdef CONFIG_HOTPLUG_CPU
+ if (cpu_is_offline(cpu))
+ cpu_play_dead();
+#endif
+
schedule();
preempt_disable();
}
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 61036b346664..5d220302cd50 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -1808,7 +1808,7 @@ static void __init of_fill_in_cpu_data(void)
#ifdef CONFIG_SMP
cpu_set(cpuid, cpu_present_map);
- cpu_set(cpuid, phys_cpu_present_map);
+ cpu_set(cpuid, cpu_possible_map);
#endif
}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 7490cc670a53..aafde3dd9fd4 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -442,7 +442,6 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
"D$ parity tl1\t: %u\n"
"I$ parity tl1\t: %u\n"
#ifndef CONFIG_SMP
- "Cpu0Bogo\t: %lu.%02lu\n"
"Cpu0ClkTck\t: %016lx\n"
#endif
,
@@ -457,9 +456,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
dcache_parity_tl1_occurred,
icache_parity_tl1_occurred
#ifndef CONFIG_SMP
- , cpu_data(0).udelay_val/(500000/HZ),
- (cpu_data(0).udelay_val/(5000/HZ)) % 100,
- cpu_data(0).clock_tick
+ , cpu_data(0).clock_tick
#endif
);
#ifdef CONFIG_SMP
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 203e87301005..fb13775b3682 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -289,9 +289,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
struct rt_signal_frame __user *sf;
unsigned long tpc, tnpc, tstate;
__siginfo_fpu_t __user *fpu_save;
- mm_segment_t old_fs;
sigset_t set;
- stack_t st;
int err;
/* Always make any pending restarted system calls return -EINTR */
@@ -327,20 +325,13 @@ void do_rt_sigreturn(struct pt_regs *regs)
err |= restore_fpu_state(regs, &sf->fpu_state);
err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
- err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t));
-
+ err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
+
if (err)
goto segv;
-
+
regs->tpc = tpc;
regs->tnpc = tnpc;
-
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
- set_fs(old_fs);
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 40e40f968d61..b448d33321c6 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1,6 +1,6 @@
/* smp.c: Sparc64 SMP support.
*
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -28,6 +28,8 @@
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/cpudata.h>
+#include <asm/hvtramp.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <asm/irq_regs.h>
@@ -41,22 +43,26 @@
#include <asm/sections.h>
#include <asm/prom.h>
#include <asm/mdesc.h>
+#include <asm/ldc.h>
+#include <asm/hypervisor.h>
extern void calibrate_delay(void);
int sparc64_multi_core __read_mostly;
-/* Please don't make this stuff initdata!!! --DaveM */
-unsigned char boot_cpu_id;
-
+cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
-cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+
+EXPORT_SYMBOL(cpu_possible_map);
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_sibling_map);
+EXPORT_SYMBOL(cpu_core_map);
+
static cpumask_t smp_commenced_mask;
-static cpumask_t cpu_callout_map;
void smp_info(struct seq_file *m)
{
@@ -73,18 +79,17 @@ void smp_bogo(struct seq_file *m)
for_each_online_cpu(i)
seq_printf(m,
- "Cpu%dBogo\t: %lu.%02lu\n"
"Cpu%dClkTck\t: %016lx\n",
- i, cpu_data(i).udelay_val / (500000/HZ),
- (cpu_data(i).udelay_val / (5000/HZ)) % 100,
i, cpu_data(i).clock_tick);
}
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
+
extern void setup_sparc64_timer(void);
static volatile unsigned long callin_flag = 0;
-void __init smp_callin(void)
+void __devinit smp_callin(void)
{
int cpuid = hard_smp_processor_id();
@@ -102,8 +107,6 @@ void __init smp_callin(void)
local_irq_enable();
- calibrate_delay();
- cpu_data(cpuid).udelay_val = loops_per_jiffy;
callin_flag = 1;
__asm__ __volatile__("membar #Sync\n\t"
"flush %%g6" : : : "memory");
@@ -120,7 +123,9 @@ void __init smp_callin(void)
while (!cpu_isset(cpuid, smp_commenced_mask))
rmb();
+ spin_lock(&call_lock);
cpu_set(cpuid, cpu_online_map);
+ spin_unlock(&call_lock);
/* idle thread is expected to have preempt disabled */
preempt_disable();
@@ -268,6 +273,67 @@ static void smp_synchronize_one_tick(int cpu)
spin_unlock_irqrestore(&itc_sync_lock, flags);
}
+#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
+/* XXX Put this in some common place. XXX */
+static unsigned long kimage_addr_to_ra(void *p)
+{
+ unsigned long val = (unsigned long) p;
+
+ return kern_base + (val - KERNBASE);
+}
+
+static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+{
+ extern unsigned long sparc64_ttable_tl0;
+ extern unsigned long kern_locked_tte_data;
+ extern int bigkernel;
+ struct hvtramp_descr *hdesc;
+ unsigned long trampoline_ra;
+ struct trap_per_cpu *tb;
+ u64 tte_vaddr, tte_data;
+ unsigned long hv_err;
+
+ hdesc = kzalloc(sizeof(*hdesc), GFP_KERNEL);
+ if (!hdesc) {
+ printk(KERN_ERR "ldom_startcpu_cpuid: Cannot allocate "
+ "hvtramp_descr.\n");
+ return;
+ }
+
+ hdesc->cpu = cpu;
+ hdesc->num_mappings = (bigkernel ? 2 : 1);
+
+ tb = &trap_block[cpu];
+ tb->hdesc = hdesc;
+
+ hdesc->fault_info_va = (unsigned long) &tb->fault_info;
+ hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info);
+
+ hdesc->thread_reg = thread_reg;
+
+ tte_vaddr = (unsigned long) KERNBASE;
+ tte_data = kern_locked_tte_data;
+
+ hdesc->maps[0].vaddr = tte_vaddr;
+ hdesc->maps[0].tte = tte_data;
+ if (bigkernel) {
+ tte_vaddr += 0x400000;
+ tte_data += 0x400000;
+ hdesc->maps[1].vaddr = tte_vaddr;
+ hdesc->maps[1].tte = tte_data;
+ }
+
+ trampoline_ra = kimage_addr_to_ra(hv_cpu_startup);
+
+ hv_err = sun4v_cpu_start(cpu, trampoline_ra,
+ kimage_addr_to_ra(&sparc64_ttable_tl0),
+ __pa(hdesc));
+ if (hv_err)
+ printk(KERN_ERR "ldom_startcpu_cpuid: sun4v_cpu_start() "
+ "gives error %lu\n", hv_err);
+}
+#endif
+
extern void sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load);
extern unsigned long sparc64_cpu_startup;
@@ -280,6 +346,7 @@ static struct thread_info *cpu_new_thread = NULL;
static int __devinit smp_boot_one_cpu(unsigned int cpu)
{
+ struct trap_per_cpu *tb = &trap_block[cpu];
unsigned long entry =
(unsigned long)(&sparc64_cpu_startup);
unsigned long cookie =
@@ -290,20 +357,25 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
p = fork_idle(cpu);
callin_flag = 0;
cpu_new_thread = task_thread_info(p);
- cpu_set(cpu, cpu_callout_map);
if (tlb_type == hypervisor) {
/* Alloc the mondo queues, cpu will load them. */
sun4v_init_mondo_queues(0, cpu, 1, 0);
- prom_startcpu_cpuid(cpu, entry, cookie);
+#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
+ if (ldom_domaining_enabled)
+ ldom_startcpu_cpuid(cpu,
+ (unsigned long) cpu_new_thread);
+ else
+#endif
+ prom_startcpu_cpuid(cpu, entry, cookie);
} else {
struct device_node *dp = of_find_node_by_cpuid(cpu);
prom_startcpu(dp->node, entry, cookie);
}
- for (timeout = 0; timeout < 5000000; timeout++) {
+ for (timeout = 0; timeout < 50000; timeout++) {
if (callin_flag)
break;
udelay(100);
@@ -313,11 +385,15 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
ret = 0;
} else {
printk("Processor %d is stuck.\n", cpu);
- cpu_clear(cpu, cpu_callout_map);
ret = -ENODEV;
}
cpu_new_thread = NULL;
+ if (tb->hdesc) {
+ kfree(tb->hdesc);
+ tb->hdesc = NULL;
+ }
+
return ret;
}
@@ -720,7 +796,6 @@ struct call_data_struct {
int wait;
};
-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
static struct call_data_struct *call_data;
extern unsigned long xcall_call_function;
@@ -1152,34 +1227,14 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
preempt_enable();
}
-void __init smp_tick_init(void)
-{
- boot_cpu_id = hard_smp_processor_id();
-}
-
/* /proc/profile writes can call this, don't __init it please. */
int setup_profiling_timer(unsigned int multiplier)
{
return -EINVAL;
}
-/* Constrain the number of cpus to max_cpus. */
void __init smp_prepare_cpus(unsigned int max_cpus)
{
- int i;
-
- if (num_possible_cpus() > max_cpus) {
- for_each_possible_cpu(i) {
- if (i != boot_cpu_id) {
- cpu_clear(i, phys_cpu_present_map);
- cpu_clear(i, cpu_present_map);
- if (num_possible_cpus() <= max_cpus)
- break;
- }
- }
- }
-
- cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
}
void __devinit smp_prepare_boot_cpu(void)
@@ -1190,30 +1245,32 @@ void __devinit smp_fill_in_sib_core_maps(void)
{
unsigned int i;
- for_each_possible_cpu(i) {
+ for_each_present_cpu(i) {
unsigned int j;
+ cpus_clear(cpu_core_map[i]);
if (cpu_data(i).core_id == 0) {
cpu_set(i, cpu_core_map[i]);
continue;
}
- for_each_possible_cpu(j) {
+ for_each_present_cpu(j) {
if (cpu_data(i).core_id ==
cpu_data(j).core_id)
cpu_set(j, cpu_core_map[i]);
}
}
- for_each_possible_cpu(i) {
+ for_each_present_cpu(i) {
unsigned int j;
+ cpus_clear(cpu_sibling_map[i]);
if (cpu_data(i).proc_id == -1) {
cpu_set(i, cpu_sibling_map[i]);
continue;
}
- for_each_possible_cpu(j) {
+ for_each_present_cpu(j) {
if (cpu_data(i).proc_id ==
cpu_data(j).proc_id)
cpu_set(j, cpu_sibling_map[i]);
@@ -1242,18 +1299,112 @@ int __cpuinit __cpu_up(unsigned int cpu)
return ret;
}
-void __init smp_cpus_done(unsigned int max_cpus)
+#ifdef CONFIG_HOTPLUG_CPU
+void cpu_play_dead(void)
+{
+ int cpu = smp_processor_id();
+ unsigned long pstate;
+
+ idle_task_exit();
+
+ if (tlb_type == hypervisor) {
+ struct trap_per_cpu *tb = &trap_block[cpu];
+
+ sun4v_cpu_qconf(HV_CPU_QUEUE_CPU_MONDO,
+ tb->cpu_mondo_pa, 0);
+ sun4v_cpu_qconf(HV_CPU_QUEUE_DEVICE_MONDO,
+ tb->dev_mondo_pa, 0);
+ sun4v_cpu_qconf(HV_CPU_QUEUE_RES_ERROR,
+ tb->resum_mondo_pa, 0);
+ sun4v_cpu_qconf(HV_CPU_QUEUE_NONRES_ERROR,
+ tb->nonresum_mondo_pa, 0);
+ }
+
+ cpu_clear(cpu, smp_commenced_mask);
+ membar_safe("#Sync");
+
+ local_irq_disable();
+
+ __asm__ __volatile__(
+ "rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ while (1)
+ barrier();
+}
+
+int __cpu_disable(void)
{
- unsigned long bogosum = 0;
+ int cpu = smp_processor_id();
+ cpuinfo_sparc *c;
int i;
- for_each_online_cpu(i)
- bogosum += cpu_data(i).udelay_val;
- printk("Total of %ld processors activated "
- "(%lu.%02lu BogoMIPS).\n",
- (long) num_online_cpus(),
- bogosum/(500000/HZ),
- (bogosum/(5000/HZ))%100);
+ for_each_cpu_mask(i, cpu_core_map[cpu])
+ cpu_clear(cpu, cpu_core_map[i]);
+ cpus_clear(cpu_core_map[cpu]);
+
+ for_each_cpu_mask(i, cpu_sibling_map[cpu])
+ cpu_clear(cpu, cpu_sibling_map[i]);
+ cpus_clear(cpu_sibling_map[cpu]);
+
+ c = &cpu_data(cpu);
+
+ c->core_id = 0;
+ c->proc_id = -1;
+
+ spin_lock(&call_lock);
+ cpu_clear(cpu, cpu_online_map);
+ spin_unlock(&call_lock);
+
+ smp_wmb();
+
+ /* Make sure no interrupts point to this cpu. */
+ fixup_irqs();
+
+ local_irq_enable();
+ mdelay(1);
+ local_irq_disable();
+
+ return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ smp_rmb();
+ if (!cpu_isset(cpu, smp_commenced_mask))
+ break;
+ msleep(100);
+ }
+ if (cpu_isset(cpu, smp_commenced_mask)) {
+ printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+ } else {
+#if defined(CONFIG_SUN_LDOMS)
+ unsigned long hv_err;
+ int limit = 100;
+
+ do {
+ hv_err = sun4v_cpu_stop(cpu);
+ if (hv_err == HV_EOK) {
+ cpu_clear(cpu, cpu_present_map);
+ break;
+ }
+ } while (--limit > 0);
+ if (limit <= 0) {
+ printk(KERN_ERR "sun4v_cpu_stop() fails err=%lu\n",
+ hv_err);
+ }
+#endif
+ }
+}
+#endif
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
}
void smp_send_reschedule(int cpu)
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 6fa761612899..719d676c2ddc 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,7 +1,6 @@
-/* $Id: sparc64_ksyms.c,v 1.121 2002/02/09 19:49:31 davem Exp $
- * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
+/* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
@@ -28,7 +27,6 @@
#include <net/compat.h>
#include <asm/oplib.h>
-#include <asm/delay.h>
#include <asm/system.h>
#include <asm/auxio.h>
#include <asm/pgtable.h>
@@ -124,10 +122,6 @@ EXPORT_SYMBOL(__write_lock);
EXPORT_SYMBOL(__write_unlock);
EXPORT_SYMBOL(__write_trylock);
-/* CPU online map and active count. */
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(phys_cpu_present_map);
-
EXPORT_SYMBOL(smp_call_function);
#endif /* CONFIG_SMP */
@@ -330,12 +324,6 @@ EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(strncmp);
-/* Delay routines. */
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__delay);
-
void VISenter(void);
/* RAID code needs this */
EXPORT_SYMBOL(VISenter);
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
index cdb1477af89f..52816c7be0b9 100644
--- a/arch/sparc64/kernel/sysfs.c
+++ b/arch/sparc64/kernel/sysfs.c
@@ -193,7 +193,6 @@ static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
}
SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
-SHOW_CPUDATA_ULONG_NAME(udelay_val, udelay_val);
SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
@@ -203,7 +202,6 @@ SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
static struct sysdev_attribute cpu_core_attrs[] = {
_SYSDEV_ATTR(clock_tick, 0444, show_clock_tick, NULL),
- _SYSDEV_ATTR(udelay_val, 0444, show_udelay_val, NULL),
_SYSDEV_ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL),
_SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
_SYSDEV_ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL),
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index a31a0439244f..62e316ab1339 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -849,9 +849,6 @@ static unsigned long sparc64_init_timers(void)
{
struct device_node *dp;
unsigned long clock;
-#ifdef CONFIG_SMP
- extern void smp_tick_init(void);
-#endif
dp = of_find_node_by_path("/");
if (tlb_type == spitfire) {
@@ -874,10 +871,6 @@ static unsigned long sparc64_init_timers(void)
clock = of_getintprop_default(dp, "stick-frequency", 0);
}
-#ifdef CONFIG_SMP
- smp_tick_init();
-#endif
-
return clock;
}
@@ -1038,10 +1031,31 @@ static void __init setup_clockevent_multiplier(unsigned long hz)
sparc64_clockevent.mult = mult;
}
+static unsigned long tb_ticks_per_usec __read_mostly;
+
+void __delay(unsigned long loops)
+{
+ unsigned long bclock, now;
+
+ bclock = tick_ops->get_tick();
+ do {
+ now = tick_ops->get_tick();
+ } while ((now-bclock) < loops);
+}
+EXPORT_SYMBOL(__delay);
+
+void udelay(unsigned long usecs)
+{
+ __delay(tb_ticks_per_usec * usecs);
+}
+EXPORT_SYMBOL(udelay);
+
void __init time_init(void)
{
unsigned long clock = sparc64_init_timers();
+ tb_ticks_per_usec = clock / USEC_PER_SEC;
+
timer_ticks_per_nsec_quotient =
clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 00a9e3286c83..6ef2d299fb10 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -2225,6 +2225,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
__asm__ __volatile__("flushw");
__show_regs(regs);
+ add_taint(TAINT_DIE);
if (regs->tstate & TSTATE_PRIV) {
struct reg_window *rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS);
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
new file mode 100644
index 000000000000..49569b44ea1f
--- /dev/null
+++ b/arch/sparc64/kernel/vio.c
@@ -0,0 +1,395 @@
+/* vio.c: Virtual I/O channel devices probing infrastructure.
+ *
+ * Copyright (c) 2003-2005 IBM Corp.
+ * Dave Engebretsen engebret@us.ibm.com
+ * Santiago Leon santil@us.ibm.com
+ * Hollis Blanchard <hollisb@us.ibm.com>
+ * Stephen Rothwell
+ *
+ * Adapted to sparc64 by David S. Miller davem@davemloft.net
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+
+#include <asm/mdesc.h>
+#include <asm/vio.h>
+
+static inline int find_in_proplist(const char *list, const char *match,
+ int len)
+{
+ while (len > 0) {
+ int l;
+
+ if (!strcmp(list, match))
+ return 1;
+ l = strlen(list) + 1;
+ list += l;
+ len -= l;
+ }
+ return 0;
+}
+
+static const struct vio_device_id *vio_match_device(
+ const struct vio_device_id *matches,
+ const struct vio_dev *dev)
+{
+ const char *type, *compat;
+ int len;
+
+ type = dev->type;
+ compat = dev->compat;
+ len = dev->compat_len;
+
+ while (matches->type[0] || matches->compat[0]) {
+ int match = 1;
+ if (matches->type[0])
+ match &= !strcmp(matches->type, type);
+
+ if (matches->compat[0]) {
+ match &= len &&
+ find_in_proplist(compat, matches->compat, len);
+ }
+ if (match)
+ return matches;
+ matches++;
+ }
+ return NULL;
+}
+
+static int vio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct vio_dev *vio_dev = to_vio_dev(dev);
+ struct vio_driver *vio_drv = to_vio_driver(drv);
+ const struct vio_device_id *matches = vio_drv->id_table;
+
+ if (!matches)
+ return 0;
+
+ return vio_match_device(matches, vio_dev) != NULL;
+}
+
+static int vio_device_probe(struct device *dev)
+{
+ struct vio_dev *vdev = to_vio_dev(dev);
+ struct vio_driver *drv = to_vio_driver(dev->driver);
+ const struct vio_device_id *id;
+ int error = -ENODEV;
+
+ if (drv->probe) {
+ id = vio_match_device(drv->id_table, vdev);
+ if (id)
+ error = drv->probe(vdev, id);
+ }
+
+ return error;
+}
+
+static int vio_device_remove(struct device *dev)
+{
+ struct vio_dev *vdev = to_vio_dev(dev);
+ struct vio_driver *drv = to_vio_driver(dev->driver);
+
+ if (drv->remove)
+ return drv->remove(vdev);
+
+ return 1;
+}
+
+static ssize_t devspec_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct vio_dev *vdev = to_vio_dev(dev);
+ const char *str = "none";
+
+ if (!strcmp(vdev->type, "network"))
+ str = "vnet";
+ else if (!strcmp(vdev->type, "block"))
+ str = "vdisk";
+
+ return sprintf(buf, "%s\n", str);
+}
+
+static ssize_t type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct vio_dev *vdev = to_vio_dev(dev);
+ return sprintf(buf, "%s\n", vdev->type);
+}
+
+static struct device_attribute vio_dev_attrs[] = {
+ __ATTR_RO(devspec),
+ __ATTR_RO(type),
+ __ATTR_NULL
+};
+
+static struct bus_type vio_bus_type = {
+ .name = "vio",
+ .dev_attrs = vio_dev_attrs,
+ .match = vio_bus_match,
+ .probe = vio_device_probe,
+ .remove = vio_device_remove,
+};
+
+int vio_register_driver(struct vio_driver *viodrv)
+{
+ viodrv->driver.bus = &vio_bus_type;
+
+ return driver_register(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_register_driver);
+
+void vio_unregister_driver(struct vio_driver *viodrv)
+{
+ driver_unregister(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_unregister_driver);
+
+static void __devinit vio_dev_release(struct device *dev)
+{
+ kfree(to_vio_dev(dev));
+}
+
+static ssize_t
+show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vio_dev *vdev;
+ struct device_node *dp;
+
+ vdev = to_vio_dev(dev);
+ dp = vdev->dp;
+
+ return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name);
+}
+
+static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
+ show_pciobppath_attr, NULL);
+
+struct device_node *cdev_node;
+
+static struct vio_dev *root_vdev;
+static u64 cdev_cfg_handle;
+
+static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
+ struct vio_dev *vdev)
+{
+ u64 a;
+
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+ const u64 *chan_id;
+ const u64 *irq;
+ u64 target;
+
+ target = mdesc_arc_target(hp, a);
+
+ irq = mdesc_get_property(hp, target, "tx-ino", NULL);
+ if (irq)
+ vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
+
+ irq = mdesc_get_property(hp, target, "rx-ino", NULL);
+ if (irq)
+ vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
+
+ chan_id = mdesc_get_property(hp, target, "id", NULL);
+ if (chan_id)
+ vdev->channel_id = *chan_id;
+ }
+}
+
+static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
+ struct device *parent)
+{
+ const char *type, *compat;
+ struct device_node *dp;
+ struct vio_dev *vdev;
+ int err, tlen, clen;
+
+ type = mdesc_get_property(hp, mp, "device-type", &tlen);
+ if (!type) {
+ type = mdesc_get_property(hp, mp, "name", &tlen);
+ if (!type) {
+ type = mdesc_node_name(hp, mp);
+ tlen = strlen(type) + 1;
+ }
+ }
+ if (tlen > VIO_MAX_TYPE_LEN) {
+ printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
+ type);
+ return NULL;
+ }
+
+ compat = mdesc_get_property(hp, mp, "device-type", &clen);
+ if (!compat) {
+ clen = 0;
+ } else if (clen > VIO_MAX_COMPAT_LEN) {
+ printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
+ clen, type);
+ return NULL;
+ }
+
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev) {
+ printk(KERN_ERR "VIO: Could not allocate vio_dev\n");
+ return NULL;
+ }
+
+ vdev->mp = mp;
+ memcpy(vdev->type, type, tlen);
+ if (compat)
+ memcpy(vdev->compat, compat, clen);
+ else
+ memset(vdev->compat, 0, sizeof(vdev->compat));
+ vdev->compat_len = clen;
+
+ vdev->channel_id = ~0UL;
+ vdev->tx_irq = ~0;
+ vdev->rx_irq = ~0;
+
+ vio_fill_channel_info(hp, mp, vdev);
+
+ snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp);
+ vdev->dev.parent = parent;
+ vdev->dev.bus = &vio_bus_type;
+ vdev->dev.release = vio_dev_release;
+
+ if (parent == NULL) {
+ dp = cdev_node;
+ } else if (to_vio_dev(parent) == root_vdev) {
+ dp = of_get_next_child(cdev_node, NULL);
+ while (dp) {
+ if (!strcmp(dp->type, type))
+ break;
+
+ dp = of_get_next_child(cdev_node, dp);
+ }
+ } else {
+ dp = to_vio_dev(parent)->dp;
+ }
+ vdev->dp = dp;
+
+ err = device_register(&vdev->dev);
+ if (err) {
+ printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
+ vdev->dev.bus_id, err);
+ kfree(vdev);
+ return NULL;
+ }
+ if (vdev->dp)
+ err = sysfs_create_file(&vdev->dev.kobj,
+ &dev_attr_obppath.attr);
+
+ return vdev;
+}
+
+static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent)
+{
+ u64 a;
+
+ mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) {
+ struct vio_dev *vdev;
+ u64 target;
+
+ target = mdesc_arc_target(hp, a);
+ vdev = vio_create_one(hp, target, &parent->dev);
+ if (vdev)
+ walk_tree(hp, target, vdev);
+ }
+}
+
+static void create_devices(struct mdesc_handle *hp, u64 root)
+{
+ u64 mp;
+
+ root_vdev = vio_create_one(hp, root, NULL);
+ if (!root_vdev) {
+ printk(KERN_ERR "VIO: Coult not create root device.\n");
+ return;
+ }
+
+ walk_tree(hp, root, root_vdev);
+
+ /* Domain services is odd as it doesn't sit underneath the
+ * channel-devices node, so we plug it in manually.
+ */
+ mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services");
+ if (mp != MDESC_NODE_NULL) {
+ struct vio_dev *parent = vio_create_one(hp, mp,
+ &root_vdev->dev);
+
+ if (parent)
+ walk_tree(hp, mp, parent);
+ }
+}
+
+const char *channel_devices_node = "channel-devices";
+const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
+const char *cfg_handle_prop = "cfg-handle";
+
+static int __init vio_init(void)
+{
+ struct mdesc_handle *hp;
+ const char *compat;
+ const u64 *cfg_handle;
+ int err, len;
+ u64 root;
+
+ err = bus_register(&vio_bus_type);
+ if (err) {
+ printk(KERN_ERR "VIO: Could not register bus type err=%d\n",
+ err);
+ return err;
+ }
+
+ hp = mdesc_grab();
+ if (!hp)
+ return 0;
+
+ root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
+ if (root == MDESC_NODE_NULL) {
+ printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
+ mdesc_release(hp);
+ return 0;
+ }
+
+ cdev_node = of_find_node_by_name(NULL, "channel-devices");
+ err = -ENODEV;
+ if (!cdev_node) {
+ printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
+ goto out_release;
+ }
+
+ compat = mdesc_get_property(hp, root, "compatible", &len);
+ if (!compat) {
+ printk(KERN_ERR "VIO: Channel devices lacks compatible "
+ "property\n");
+ goto out_release;
+ }
+ if (!find_in_proplist(compat, channel_devices_compat, len)) {
+ printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
+ "compat entry.\n", channel_devices_compat);
+ goto out_release;
+ }
+
+ cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
+ if (!cfg_handle) {
+ printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
+ cfg_handle_prop);
+ goto out_release;
+ }
+
+ cdev_cfg_handle = *cfg_handle;
+
+ create_devices(hp, root);
+
+ mdesc_release(hp);
+
+ return 0;
+
+out_release:
+ mdesc_release(hp);
+ return err;
+}
+
+postcore_initcall(vio_init);
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c
new file mode 100644
index 000000000000..15613add45d1
--- /dev/null
+++ b/arch/sparc64/kernel/viohs.c
@@ -0,0 +1,792 @@
+/* viohs.c: LDOM Virtual I/O handshake helper layer.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/ldc.h>
+#include <asm/vio.h>
+
+int vio_ldc_send(struct vio_driver_state *vio, void *data, int len)
+{
+ int err, limit = 1000;
+
+ err = -EINVAL;
+ while (limit-- > 0) {
+ err = ldc_write(vio->lp, data, len);
+ if (!err || (err != -EAGAIN))
+ break;
+ udelay(1);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(vio_ldc_send);
+
+static int send_ctrl(struct vio_driver_state *vio,
+ struct vio_msg_tag *tag, int len)
+{
+ tag->sid = vio_send_sid(vio);
+ return vio_ldc_send(vio, tag, len);
+}
+
+static void init_tag(struct vio_msg_tag *tag, u8 type, u8 stype, u16 stype_env)
+{
+ tag->type = type;
+ tag->stype = stype;
+ tag->stype_env = stype_env;
+}
+
+static int send_version(struct vio_driver_state *vio, u16 major, u16 minor)
+{
+ struct vio_ver_info pkt;
+
+ vio->_local_sid = (u32) sched_clock();
+
+ memset(&pkt, 0, sizeof(pkt));
+ init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_VER_INFO);
+ pkt.major = major;
+ pkt.minor = minor;
+ pkt.dev_class = vio->dev_class;
+
+ viodbg(HS, "SEND VERSION INFO maj[%u] min[%u] devclass[%u]\n",
+ major, minor, vio->dev_class);
+
+ return send_ctrl(vio, &pkt.tag, sizeof(pkt));
+}
+
+static int start_handshake(struct vio_driver_state *vio)
+{
+ int err;
+
+ viodbg(HS, "START HANDSHAKE\n");
+
+ vio->hs_state = VIO_HS_INVALID;
+
+ err = send_version(vio,
+ vio->ver_table[0].major,
+ vio->ver_table[0].minor);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+void vio_link_state_change(struct vio_driver_state *vio, int event)
+{
+ if (event == LDC_EVENT_UP) {
+ vio->hs_state = VIO_HS_INVALID;
+
+ switch (vio->dev_class) {
+ case VDEV_NETWORK:
+ case VDEV_NETWORK_SWITCH:
+ vio->dr_state = (VIO_DR_STATE_TXREQ |
+ VIO_DR_STATE_RXREQ);
+ break;
+
+ case VDEV_DISK:
+ vio->dr_state = VIO_DR_STATE_TXREQ;
+ break;
+ case VDEV_DISK_SERVER:
+ vio->dr_state = VIO_DR_STATE_RXREQ;
+ break;
+ }
+ start_handshake(vio);
+ }
+}
+EXPORT_SYMBOL(vio_link_state_change);
+
+static int handshake_failure(struct vio_driver_state *vio)
+{
+ struct vio_dring_state *dr;
+
+ /* XXX Put policy here... Perhaps start a timer to fire
+ * XXX in 100 ms, which will bring the link up and retry
+ * XXX the handshake.
+ */
+
+ viodbg(HS, "HANDSHAKE FAILURE\n");
+
+ vio->dr_state &= ~(VIO_DR_STATE_TXREG |
+ VIO_DR_STATE_RXREG);
+
+ dr = &vio->drings[VIO_DRIVER_RX_RING];
+ memset(dr, 0, sizeof(*dr));
+
+ kfree(vio->desc_buf);
+ vio->desc_buf = NULL;
+ vio->desc_buf_len = 0;
+
+ vio->hs_state = VIO_HS_INVALID;
+
+ return -ECONNRESET;
+}
+
+static int process_unknown(struct vio_driver_state *vio, void *arg)
+{
+ struct vio_msg_tag *pkt = arg;
+
+ viodbg(HS, "UNKNOWN CONTROL [%02x:%02x:%04x:%08x]\n",
+ pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+
+ printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
+ vio->vdev->channel_id);
+
+ ldc_disconnect(vio->lp);
+
+ return -ECONNRESET;
+}
+
+static int send_dreg(struct vio_driver_state *vio)
+{
+ struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_TX_RING];
+ union {
+ struct vio_dring_register pkt;
+ char all[sizeof(struct vio_dring_register) +
+ (sizeof(struct ldc_trans_cookie) *
+ dr->ncookies)];
+ } u;
+ int i;
+
+ memset(&u, 0, sizeof(u));
+ init_tag(&u.pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_DRING_REG);
+ u.pkt.dring_ident = 0;
+ u.pkt.num_descr = dr->num_entries;
+ u.pkt.descr_size = dr->entry_size;
+ u.pkt.options = VIO_TX_DRING;
+ u.pkt.num_cookies = dr->ncookies;
+
+ viodbg(HS, "SEND DRING_REG INFO ndesc[%u] dsz[%u] opt[0x%x] "
+ "ncookies[%u]\n",
+ u.pkt.num_descr, u.pkt.descr_size, u.pkt.options,
+ u.pkt.num_cookies);
+
+ for (i = 0; i < dr->ncookies; i++) {
+ u.pkt.cookies[i] = dr->cookies[i];
+
+ viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
+ i,
+ (unsigned long long) u.pkt.cookies[i].cookie_addr,
+ (unsigned long long) u.pkt.cookies[i].cookie_size);
+ }
+
+ return send_ctrl(vio, &u.pkt.tag, sizeof(u));
+}
+
+static int send_rdx(struct vio_driver_state *vio)
+{
+ struct vio_rdx pkt;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_RDX);
+
+ viodbg(HS, "SEND RDX INFO\n");
+
+ return send_ctrl(vio, &pkt.tag, sizeof(pkt));
+}
+
+static int send_attr(struct vio_driver_state *vio)
+{
+ return vio->ops->send_attr(vio);
+}
+
+static struct vio_version *find_by_major(struct vio_driver_state *vio,
+ u16 major)
+{
+ struct vio_version *ret = NULL;
+ int i;
+
+ for (i = 0; i < vio->ver_table_entries; i++) {
+ struct vio_version *v = &vio->ver_table[i];
+ if (v->major <= major) {
+ ret = v;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int process_ver_info(struct vio_driver_state *vio,
+ struct vio_ver_info *pkt)
+{
+ struct vio_version *vap;
+ int err;
+
+ viodbg(HS, "GOT VERSION INFO maj[%u] min[%u] devclass[%u]\n",
+ pkt->major, pkt->minor, pkt->dev_class);
+
+ if (vio->hs_state != VIO_HS_INVALID) {
+ /* XXX Perhaps invoke start_handshake? XXX */
+ memset(&vio->ver, 0, sizeof(vio->ver));
+ vio->hs_state = VIO_HS_INVALID;
+ }
+
+ vap = find_by_major(vio, pkt->major);
+
+ vio->_peer_sid = pkt->tag.sid;
+
+ if (!vap) {
+ pkt->tag.stype = VIO_SUBTYPE_NACK;
+ pkt->major = 0;
+ pkt->minor = 0;
+ viodbg(HS, "SEND VERSION NACK maj[0] min[0]\n");
+ err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+ } else if (vap->major != pkt->major) {
+ pkt->tag.stype = VIO_SUBTYPE_NACK;
+ pkt->major = vap->major;
+ pkt->minor = vap->minor;
+ viodbg(HS, "SEND VERSION NACK maj[%u] min[%u]\n",
+ pkt->major, pkt->minor);
+ err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+ } else {
+ struct vio_version ver = {
+ .major = pkt->major,
+ .minor = pkt->minor,
+ };
+ if (ver.minor > vap->minor)
+ ver.minor = vap->minor;
+ pkt->minor = ver.minor;
+ pkt->tag.stype = VIO_SUBTYPE_ACK;
+ viodbg(HS, "SEND VERSION ACK maj[%u] min[%u]\n",
+ pkt->major, pkt->minor);
+ err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+ if (err > 0) {
+ vio->ver = ver;
+ vio->hs_state = VIO_HS_GOTVERS;
+ }
+ }
+ if (err < 0)
+ return handshake_failure(vio);
+
+ return 0;
+}
+
+static int process_ver_ack(struct vio_driver_state *vio,
+ struct vio_ver_info *pkt)
+{
+ viodbg(HS, "GOT VERSION ACK maj[%u] min[%u] devclass[%u]\n",
+ pkt->major, pkt->minor, pkt->dev_class);
+
+ if (vio->hs_state & VIO_HS_GOTVERS) {
+ if (vio->ver.major != pkt->major ||
+ vio->ver.minor != pkt->minor) {
+ pkt->tag.stype = VIO_SUBTYPE_NACK;
+ (void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+ return handshake_failure(vio);
+ }
+ } else {
+ vio->ver.major = pkt->major;
+ vio->ver.minor = pkt->minor;
+ vio->hs_state = VIO_HS_GOTVERS;
+ }
+
+ switch (vio->dev_class) {
+ case VDEV_NETWORK:
+ case VDEV_DISK:
+ if (send_attr(vio) < 0)
+ return handshake_failure(vio);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int process_ver_nack(struct vio_driver_state *vio,
+ struct vio_ver_info *pkt)
+{
+ struct vio_version *nver;
+
+ viodbg(HS, "GOT VERSION NACK maj[%u] min[%u] devclass[%u]\n",
+ pkt->major, pkt->minor, pkt->dev_class);
+
+ if ((pkt->major == 0 && pkt->minor == 0) ||
+ !(nver = find_by_major(vio, pkt->major)))
+ return handshake_failure(vio);
+
+ if (send_version(vio, nver->major, nver->minor) < 0)
+ return handshake_failure(vio);
+
+ return 0;
+}
+
+static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt)
+{
+ switch (pkt->tag.stype) {
+ case VIO_SUBTYPE_INFO:
+ return process_ver_info(vio, pkt);
+
+ case VIO_SUBTYPE_ACK:
+ return process_ver_ack(vio, pkt);
+
+ case VIO_SUBTYPE_NACK:
+ return process_ver_nack(vio, pkt);
+
+ default:
+ return handshake_failure(vio);
+ };
+}
+
+static int process_attr(struct vio_driver_state *vio, void *pkt)
+{
+ int err;
+
+ if (!(vio->hs_state & VIO_HS_GOTVERS))
+ return handshake_failure(vio);
+
+ err = vio->ops->handle_attr(vio, pkt);
+ if (err < 0) {
+ return handshake_failure(vio);
+ } else {
+ vio->hs_state |= VIO_HS_GOT_ATTR;
+
+ if ((vio->dr_state & VIO_DR_STATE_TXREQ) &&
+ !(vio->hs_state & VIO_HS_SENT_DREG)) {
+ if (send_dreg(vio) < 0)
+ return handshake_failure(vio);
+
+ vio->hs_state |= VIO_HS_SENT_DREG;
+ }
+ }
+ return 0;
+}
+
+static int all_drings_registered(struct vio_driver_state *vio)
+{
+ int need_rx, need_tx;
+
+ need_rx = (vio->dr_state & VIO_DR_STATE_RXREQ);
+ need_tx = (vio->dr_state & VIO_DR_STATE_TXREQ);
+
+ if (need_rx &&
+ !(vio->dr_state & VIO_DR_STATE_RXREG))
+ return 0;
+
+ if (need_tx &&
+ !(vio->dr_state & VIO_DR_STATE_TXREG))
+ return 0;
+
+ return 1;
+}
+
+static int process_dreg_info(struct vio_driver_state *vio,
+ struct vio_dring_register *pkt)
+{
+ struct vio_dring_state *dr;
+ int i, len;
+
+ viodbg(HS, "GOT DRING_REG INFO ident[%llx] "
+ "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+ (unsigned long long) pkt->dring_ident,
+ pkt->num_descr, pkt->descr_size, pkt->options,
+ pkt->num_cookies);
+
+ if (!(vio->dr_state & VIO_DR_STATE_RXREQ))
+ goto send_nack;
+
+ if (vio->dr_state & VIO_DR_STATE_RXREG)
+ goto send_nack;
+
+ vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
+ if (!vio->desc_buf)
+ goto send_nack;
+
+ vio->desc_buf_len = pkt->descr_size;
+
+ dr = &vio->drings[VIO_DRIVER_RX_RING];
+
+ dr->num_entries = pkt->num_descr;
+ dr->entry_size = pkt->descr_size;
+ dr->ncookies = pkt->num_cookies;
+ for (i = 0; i < dr->ncookies; i++) {
+ dr->cookies[i] = pkt->cookies[i];
+
+ viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
+ i,
+ (unsigned long long)
+ pkt->cookies[i].cookie_addr,
+ (unsigned long long)
+ pkt->cookies[i].cookie_size);
+ }
+
+ pkt->tag.stype = VIO_SUBTYPE_ACK;
+ pkt->dring_ident = ++dr->ident;
+
+ viodbg(HS, "SEND DRING_REG ACK ident[%llx]\n",
+ (unsigned long long) pkt->dring_ident);
+
+ len = (sizeof(*pkt) +
+ (dr->ncookies * sizeof(struct ldc_trans_cookie)));
+ if (send_ctrl(vio, &pkt->tag, len) < 0)
+ goto send_nack;
+
+ vio->dr_state |= VIO_DR_STATE_RXREG;
+
+ return 0;
+
+send_nack:
+ pkt->tag.stype = VIO_SUBTYPE_NACK;
+ viodbg(HS, "SEND DRING_REG NACK\n");
+ (void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
+
+ return handshake_failure(vio);
+}
+
+static int process_dreg_ack(struct vio_driver_state *vio,
+ struct vio_dring_register *pkt)
+{
+ struct vio_dring_state *dr;
+
+ viodbg(HS, "GOT DRING_REG ACK ident[%llx] "
+ "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+ (unsigned long long) pkt->dring_ident,
+ pkt->num_descr, pkt->descr_size, pkt->options,
+ pkt->num_cookies);
+
+ dr = &vio->drings[VIO_DRIVER_TX_RING];
+
+ if (!(vio->dr_state & VIO_DR_STATE_TXREQ))
+ return handshake_failure(vio);
+
+ dr->ident = pkt->dring_ident;
+ vio->dr_state |= VIO_DR_STATE_TXREG;
+
+ if (all_drings_registered(vio)) {
+ if (send_rdx(vio) < 0)
+ return handshake_failure(vio);
+ vio->hs_state = VIO_HS_SENT_RDX;
+ }
+ return 0;
+}
+
+static int process_dreg_nack(struct vio_driver_state *vio,
+ struct vio_dring_register *pkt)
+{
+ viodbg(HS, "GOT DRING_REG NACK ident[%llx] "
+ "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+ (unsigned long long) pkt->dring_ident,
+ pkt->num_descr, pkt->descr_size, pkt->options,
+ pkt->num_cookies);
+
+ return handshake_failure(vio);
+}
+
+static int process_dreg(struct vio_driver_state *vio,
+ struct vio_dring_register *pkt)
+{
+ if (!(vio->hs_state & VIO_HS_GOTVERS))
+ return handshake_failure(vio);
+
+ switch (pkt->tag.stype) {
+ case VIO_SUBTYPE_INFO:
+ return process_dreg_info(vio, pkt);
+
+ case VIO_SUBTYPE_ACK:
+ return process_dreg_ack(vio, pkt);
+
+ case VIO_SUBTYPE_NACK:
+ return process_dreg_nack(vio, pkt);
+
+ default:
+ return handshake_failure(vio);
+ }
+}
+
+static int process_dunreg(struct vio_driver_state *vio,
+ struct vio_dring_unregister *pkt)
+{
+ struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_RX_RING];
+
+ viodbg(HS, "GOT DRING_UNREG\n");
+
+ if (pkt->dring_ident != dr->ident)
+ return 0;
+
+ vio->dr_state &= ~VIO_DR_STATE_RXREG;
+
+ memset(dr, 0, sizeof(*dr));
+
+ kfree(vio->desc_buf);
+ vio->desc_buf = NULL;
+ vio->desc_buf_len = 0;
+
+ return 0;
+}
+
+static int process_rdx_info(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+ viodbg(HS, "GOT RDX INFO\n");
+
+ pkt->tag.stype = VIO_SUBTYPE_ACK;
+ viodbg(HS, "SEND RDX ACK\n");
+ if (send_ctrl(vio, &pkt->tag, sizeof(*pkt)) < 0)
+ return handshake_failure(vio);
+
+ vio->hs_state |= VIO_HS_SENT_RDX_ACK;
+ return 0;
+}
+
+static int process_rdx_ack(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+ viodbg(HS, "GOT RDX ACK\n");
+
+ if (!(vio->hs_state & VIO_HS_SENT_RDX))
+ return handshake_failure(vio);
+
+ vio->hs_state |= VIO_HS_GOT_RDX_ACK;
+ return 0;
+}
+
+static int process_rdx_nack(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+ viodbg(HS, "GOT RDX NACK\n");
+
+ return handshake_failure(vio);
+}
+
+static int process_rdx(struct vio_driver_state *vio, struct vio_rdx *pkt)
+{
+ if (!all_drings_registered(vio))
+ handshake_failure(vio);
+
+ switch (pkt->tag.stype) {
+ case VIO_SUBTYPE_INFO:
+ return process_rdx_info(vio, pkt);
+
+ case VIO_SUBTYPE_ACK:
+ return process_rdx_ack(vio, pkt);
+
+ case VIO_SUBTYPE_NACK:
+ return process_rdx_nack(vio, pkt);
+
+ default:
+ return handshake_failure(vio);
+ }
+}
+
+int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt)
+{
+ struct vio_msg_tag *tag = pkt;
+ u8 prev_state = vio->hs_state;
+ int err;
+
+ switch (tag->stype_env) {
+ case VIO_VER_INFO:
+ err = process_ver(vio, pkt);
+ break;
+
+ case VIO_ATTR_INFO:
+ err = process_attr(vio, pkt);
+ break;
+
+ case VIO_DRING_REG:
+ err = process_dreg(vio, pkt);
+ break;
+
+ case VIO_DRING_UNREG:
+ err = process_dunreg(vio, pkt);
+ break;
+
+ case VIO_RDX:
+ err = process_rdx(vio, pkt);
+ break;
+
+ default:
+ err = process_unknown(vio, pkt);
+ break;
+ }
+ if (!err &&
+ vio->hs_state != prev_state &&
+ (vio->hs_state & VIO_HS_COMPLETE))
+ vio->ops->handshake_complete(vio);
+
+ return err;
+}
+EXPORT_SYMBOL(vio_control_pkt_engine);
+
+void vio_conn_reset(struct vio_driver_state *vio)
+{
+}
+EXPORT_SYMBOL(vio_conn_reset);
+
+/* The issue is that the Solaris virtual disk server just mirrors the
+ * SID values it gets from the client peer. So we work around that
+ * here in vio_{validate,send}_sid() so that the drivers don't need
+ * to be aware of this crap.
+ */
+int vio_validate_sid(struct vio_driver_state *vio, struct vio_msg_tag *tp)
+{
+ u32 sid;
+
+ /* Always let VERSION+INFO packets through unchecked, they
+ * define the new SID.
+ */
+ if (tp->type == VIO_TYPE_CTRL &&
+ tp->stype == VIO_SUBTYPE_INFO &&
+ tp->stype_env == VIO_VER_INFO)
+ return 0;
+
+ /* Ok, now figure out which SID to use. */
+ switch (vio->dev_class) {
+ case VDEV_NETWORK:
+ case VDEV_NETWORK_SWITCH:
+ case VDEV_DISK_SERVER:
+ default:
+ sid = vio->_peer_sid;
+ break;
+
+ case VDEV_DISK:
+ sid = vio->_local_sid;
+ break;
+ }
+
+ if (sid == tp->sid)
+ return 0;
+ viodbg(DATA, "BAD SID tag->sid[%08x] peer_sid[%08x] local_sid[%08x]\n",
+ tp->sid, vio->_peer_sid, vio->_local_sid);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(vio_validate_sid);
+
+u32 vio_send_sid(struct vio_driver_state *vio)
+{
+ switch (vio->dev_class) {
+ case VDEV_NETWORK:
+ case VDEV_NETWORK_SWITCH:
+ case VDEV_DISK:
+ default:
+ return vio->_local_sid;
+
+ case VDEV_DISK_SERVER:
+ return vio->_peer_sid;
+ }
+}
+EXPORT_SYMBOL(vio_send_sid);
+
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+ struct ldc_channel_config *base_cfg,
+ void *event_arg)
+{
+ struct ldc_channel_config cfg = *base_cfg;
+ struct ldc_channel *lp;
+
+ cfg.tx_irq = vio->vdev->tx_irq;
+ cfg.rx_irq = vio->vdev->rx_irq;
+
+ lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg);
+ if (IS_ERR(lp))
+ return PTR_ERR(lp);
+
+ vio->lp = lp;
+
+ return 0;
+}
+EXPORT_SYMBOL(vio_ldc_alloc);
+
+void vio_ldc_free(struct vio_driver_state *vio)
+{
+ ldc_free(vio->lp);
+ vio->lp = NULL;
+
+ kfree(vio->desc_buf);
+ vio->desc_buf = NULL;
+ vio->desc_buf_len = 0;
+}
+EXPORT_SYMBOL(vio_ldc_free);
+
+void vio_port_up(struct vio_driver_state *vio)
+{
+ unsigned long flags;
+ int err, state;
+
+ spin_lock_irqsave(&vio->lock, flags);
+
+ state = ldc_state(vio->lp);
+
+ err = 0;
+ if (state == LDC_STATE_INIT) {
+ err = ldc_bind(vio->lp, vio->name);
+ if (err)
+ printk(KERN_WARNING "%s: Port %lu bind failed, "
+ "err=%d\n",
+ vio->name, vio->vdev->channel_id, err);
+ }
+
+ if (!err) {
+ err = ldc_connect(vio->lp);
+ if (err)
+ printk(KERN_WARNING "%s: Port %lu connect failed, "
+ "err=%d\n",
+ vio->name, vio->vdev->channel_id, err);
+ }
+ if (err) {
+ unsigned long expires = jiffies + HZ;
+
+ expires = round_jiffies(expires);
+ mod_timer(&vio->timer, expires);
+ }
+
+ spin_unlock_irqrestore(&vio->lock, flags);
+}
+EXPORT_SYMBOL(vio_port_up);
+
+static void vio_port_timer(unsigned long _arg)
+{
+ struct vio_driver_state *vio = (struct vio_driver_state *) _arg;
+
+ vio_port_up(vio);
+}
+
+int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+ u8 dev_class, struct vio_version *ver_table,
+ int ver_table_size, struct vio_driver_ops *ops,
+ char *name)
+{
+ switch (dev_class) {
+ case VDEV_NETWORK:
+ case VDEV_NETWORK_SWITCH:
+ case VDEV_DISK:
+ case VDEV_DISK_SERVER:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (!ops->send_attr ||
+ !ops->handle_attr ||
+ !ops->handshake_complete)
+ return -EINVAL;
+
+ if (!ver_table || ver_table_size < 0)
+ return -EINVAL;
+
+ if (!name)
+ return -EINVAL;
+
+ spin_lock_init(&vio->lock);
+
+ vio->name = name;
+
+ vio->dev_class = dev_class;
+ vio->vdev = vdev;
+
+ vio->ver_table = ver_table;
+ vio->ver_table_entries = ver_table_size;
+
+ vio->ops = ops;
+
+ setup_timer(&vio->timer, vio_port_timer, (unsigned long) vio);
+
+ return 0;
+}
+EXPORT_SYMBOL(vio_driver_init);
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 4a725d8985f1..c4a6d6e7d03c 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,6 +14,6 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
NGpage.o NGbzero.o \
copy_in_user.o user_fixup.o memmove.o \
- mcount.o ipcsum.o rwsem.o xor.o delay.o
+ mcount.o ipcsum.o rwsem.o xor.o
obj-y += iomap.o
diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
deleted file mode 100644
index fb27e54a03ee..000000000000
--- a/arch/sparc64/lib/delay.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* delay.c: Delay loops for sparc64
- *
- * Copyright (C) 2004, 2006 David S. Miller <davem@davemloft.net>
- *
- * Based heavily upon x86 variant which is:
- * Copyright (C) 1993 Linus Torvalds
- * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-
-#include <linux/delay.h>
-#include <asm/timer.h>
-
-void __delay(unsigned long loops)
-{
- unsigned long bclock, now;
-
- bclock = tick_ops->get_tick();
- do {
- now = tick_ops->get_tick();
- } while ((now-bclock) < loops);
-}
-
-/* We used to multiply by HZ after shifting down by 32 bits
- * but that runs into problems for higher values of HZ and
- * slow cpus.
- */
-void __const_udelay(unsigned long n)
-{
- n *= 4;
-
- n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4));
- n >>= 32;
-
- __delay(n + 1);
-}
-
-void __udelay(unsigned long n)
-{
- __const_udelay(n * 0x10c7UL);
-}
-
-
-void __ndelay(unsigned long n)
-{
- __const_udelay(n * 0x5UL);
-}
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index f3e0c14e9eef..33c5b7da31e5 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -14,6 +14,7 @@
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/system.h>
+#include <asm/ldc.h>
int prom_service_exists(const char *service_name)
{
@@ -37,6 +38,10 @@ void prom_sun4v_guest_soft_state(void)
/* Reset and reboot the machine with the command 'bcommand'. */
void prom_reboot(const char *bcommand)
{
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_reboot(bcommand);
+#endif
p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_INOUT(1, 0), bcommand);
}
@@ -91,6 +96,10 @@ void prom_cmdline(void)
*/
void prom_halt(void)
{
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+#endif
again:
p1275_cmd("exit", P1275_INOUT(0, 0));
goto again; /* PROM is out to get me -DaveM */
@@ -98,6 +107,10 @@ again:
void prom_halt_power_off(void)
{
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+#endif
p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
/* if nothing else helps, we just halt */
diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c
index 2b32c489860c..7fcccc0e19cf 100644
--- a/arch/sparc64/prom/p1275.c
+++ b/arch/sparc64/prom/p1275.c
@@ -16,6 +16,7 @@
#include <asm/system.h>
#include <asm/spitfire.h>
#include <asm/pstate.h>
+#include <asm/ldc.h>
struct {
long prom_callback; /* 0x00 */
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c
index 500f05e2cfcb..17b7ecfe7ca9 100644
--- a/arch/sparc64/prom/tree.c
+++ b/arch/sparc64/prom/tree.c
@@ -13,6 +13,7 @@
#include <asm/openprom.h>
#include <asm/oplib.h>
+#include <asm/ldc.h>
/* Return the child of node 'node' or zero if no this node has no
* direct descendent.
@@ -261,9 +262,17 @@ int prom_node_has_property(int node, const char *prop)
int
prom_setprop(int node, const char *pname, char *value, int size)
{
- if(size == 0) return 0;
- if((pname == 0) || (value == 0)) return 0;
+ if (size == 0)
+ return 0;
+ if ((pname == 0) || (value == 0))
+ return 0;
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled) {
+ ldom_set_var(pname, value);
+ return 0;
+ }
+#endif
return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
P1275_ARG(2,P1275_ARG_IN_BUF)|
P1275_INOUT(4, 1),
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 09c1aca6339f..c86f5eb29fd5 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -47,4 +47,13 @@ config GCOV
If you're involved in UML kernel development and want to use gcov,
say Y. If you're unsure, say N.
+config DEBUG_STACK_USAGE
+ bool "Stack utilization instrumentation"
+ default N
+ help
+ Track the maximum kernel stack usage - this will look at each
+ kernel stack at process exit and log it if it's the deepest
+ stack seen so far.
+
+ This option will slow down process creation and destruction somewhat.
endmenu
diff --git a/arch/um/config.release b/arch/um/config.release
deleted file mode 100644
index fc68bcb9294e..000000000000
--- a/arch/um/config.release
+++ /dev/null
@@ -1,333 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_USERMODE=y
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCI is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
-#
-CONFIG_STDIO_CONSOLE=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_SSL=y
-CONFIG_HOSTFS=y
-CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
-# CONFIG_SMP is not set
-CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
-CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_KMOD=y
-
-#
-# Devices
-#
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_MMAPPER is not set
-CONFIG_UML_SOUND=y
-CONFIG_SOUND=y
-CONFIG_HOSTAUDIO=y
-# CONFIG_UML_WATCHDOG is not set
-# CONFIG_TTY_LOG is not set
-CONFIG_FD_CHAN=y
-# CONFIG_NULL_CHAN is not set
-CONFIG_PORT_CHAN=y
-CONFIG_PTY_CHAN=y
-CONFIG_TTY_CHAN=y
-CONFIG_XTERM_CHAN=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network device support
-#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_UMSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_EFS_FS=m
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=m
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_MINIX_FS=m
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-CONFIG_HPFS_FS=m
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_QNX4FS_FS=m
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_ZLIB_FS_INFLATE=m
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_PT_PROXY is not set
-# CONFIG_GPROF is not set
-# CONFIG_GCOV is not set
diff --git a/arch/um/defconfig b/arch/um/defconfig
index a54d0efecae1..a25cd25d55d4 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -189,7 +189,7 @@ CONFIG_XTERM_CHAN=y
# CONFIG_NOCONFIG_CHAN is not set
CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
+CONFIG_SSL_CHAN="pts"
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -527,3 +527,4 @@ CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_GPROF is not set
# CONFIG_GCOV is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 3aa351611763..368d3e97dfd9 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -203,22 +203,37 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
}
}
-void enable_chan(struct line *line)
+int enable_chan(struct line *line)
{
struct list_head *ele;
struct chan *chan;
+ int err;
list_for_each(ele, &line->chan_list){
chan = list_entry(ele, struct chan, list);
- if(open_one_chan(chan))
+ err = open_one_chan(chan);
+ if (err) {
+ if (chan->primary)
+ goto out_close;
+
continue;
+ }
if(chan->enabled)
continue;
- line_setup_irq(chan->fd, chan->input, chan->output, line,
- chan);
+ err = line_setup_irq(chan->fd, chan->input, chan->output, line,
+ chan);
+ if (err)
+ goto out_close;
+
chan->enabled = 1;
}
+
+ return 0;
+
+ out_close:
+ close_chan(&line->chan_list, 0);
+ return err;
}
/* Items are added in IRQ context, when free_irq can't be called, and
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 13f0bf852b2a..4d438f36ea2e 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -51,19 +51,21 @@ error:
/*
* UML SIGWINCH handling
*
- * The point of this is to handle SIGWINCH on consoles which have host ttys and
- * relay them inside UML to whatever might be running on the console and cares
- * about the window size (since SIGWINCH notifies about terminal size changes).
+ * The point of this is to handle SIGWINCH on consoles which have host
+ * ttys and relay them inside UML to whatever might be running on the
+ * console and cares about the window size (since SIGWINCH notifies
+ * about terminal size changes).
*
- * So, we have a separate thread for each host tty attached to a UML device
- * (side-issue - I'm annoyed that one thread can't have multiple controlling
- * ttys for purposed of handling SIGWINCH, but I imagine there are other reasons
- * that doesn't make any sense).
+ * So, we have a separate thread for each host tty attached to a UML
+ * device (side-issue - I'm annoyed that one thread can't have
+ * multiple controlling ttys for the purpose of handling SIGWINCH, but
+ * I imagine there are other reasons that doesn't make any sense).
*
- * SIGWINCH can't be received synchronously, so you have to set up to receive it
- * as a signal. That being the case, if you are going to wait for it, it is
- * convenient to sit in sigsuspend() and wait for the signal to bounce you out of
- * it (see below for how we make sure to exit only on SIGWINCH).
+ * SIGWINCH can't be received synchronously, so you have to set up to
+ * receive it as a signal. That being the case, if you are going to
+ * wait for it, it is convenient to sit in sigsuspend() and wait for
+ * the signal to bounce you out of it (see below for how we make sure
+ * to exit only on SIGWINCH).
*/
static void winch_handler(int sig)
@@ -112,7 +114,8 @@ static int winch_thread(void *arg)
err = os_new_tty_pgrp(pty_fd, os_getpid());
if(err < 0){
- printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
+ printk("winch_thread : new_tty_pgrp failed on fd %d, "
+ "err = %d\n", pty_fd, -err);
exit(1);
}
@@ -126,8 +129,9 @@ static int winch_thread(void *arg)
"err = %d\n", -count);
while(1){
- /* This will be interrupted by SIGWINCH only, since other signals
- * are blocked.*/
+ /* This will be interrupted by SIGWINCH only, since
+ * other signals are blocked.
+ */
sigsuspend(&sigs);
count = os_write_file(pipe_fd, &c, sizeof(c));
@@ -137,10 +141,10 @@ static int winch_thread(void *arg)
}
}
-static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
+static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
+ unsigned long *stack_out)
{
struct winch_data data;
- unsigned long stack;
int fds[2], n, err;
char c;
@@ -153,9 +157,11 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
data = ((struct winch_data) { .pty_fd = fd,
.pipe_fd = fds[1] } );
/* CLONE_FILES so this thread doesn't hold open files which are open
- * now, but later closed. This is a problem with /dev/net/tun.
+ * now, but later closed in a different thread. This is a
+ * problem with /dev/net/tun, which if held open by this
+ * thread, prevents the TUN/TAP device from being reused.
*/
- err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
+ err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
if(err < 0){
printk("fork of winch_thread failed - errno = %d\n", -err);
goto out_close;
@@ -170,7 +176,13 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
err = -EINVAL;
goto out_close;
}
- return err ;
+
+ if (os_set_fd_block(*fd_out, 0)) {
+ printk("winch_tramp: failed to set thread_fd non-blocking.\n");
+ goto out_close;
+ }
+
+ return err;
out_close:
os_close_file(fds[1]);
@@ -181,25 +193,25 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
void register_winch(int fd, struct tty_struct *tty)
{
- int pid, thread, thread_fd = -1;
- int count;
+ unsigned long stack;
+ int pid, thread, count, thread_fd = -1;
char c = 1;
if(!isatty(fd))
return;
pid = tcgetpgrp(fd);
- if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
- tty) && (pid == -1)){
- thread = winch_tramp(fd, tty, &thread_fd);
- if(thread > 0){
- register_winch_irq(thread_fd, fd, thread, tty);
-
- count = os_write_file(thread_fd, &c, sizeof(c));
- if(count != sizeof(c))
- printk("register_winch : failed to write "
- "synchronization byte, err = %d\n",
- -count);
- }
+ if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) &&
+ (pid == -1)) {
+ thread = winch_tramp(fd, tty, &thread_fd, &stack);
+ if (thread < 0)
+ return;
+
+ register_winch_irq(thread_fd, fd, thread, tty, stack);
+
+ count = os_write_file(thread_fd, &c, sizeof(c));
+ if(count != sizeof(c))
+ printk("register_winch : failed to write "
+ "synchronization byte, err = %d\n", -count);
}
}
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 15453845d2ba..ca8c9e11a39b 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -8,7 +8,7 @@
static inline void *cow_malloc(int size)
{
- return um_kmalloc(size);
+ return kmalloc(size, UM_GFP_KERNEL);
}
static inline void cow_free(void *ptr)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index b869e3899683..8d2008f06682 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -35,7 +35,7 @@ static struct sockaddr_un *new_addr(void *name, int len)
{
struct sockaddr_un *sun;
- sun = um_kmalloc(sizeof(struct sockaddr_un));
+ sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
if(sun == NULL){
printk("new_addr: allocation of sockaddr_un failed\n");
return NULL;
@@ -83,7 +83,7 @@ static int connect_to_switch(struct daemon_data *pri)
goto out_close;
}
- sun = um_kmalloc(sizeof(struct sockaddr_un));
+ sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
if(sun == NULL){
printk("new_addr: allocation of sockaddr_un failed\n");
err = -ENOMEM;
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 7f083ec47a4f..39c01ffd45c9 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -37,7 +37,7 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts)
printk("fd_init : couldn't parse file descriptor '%s'\n", str);
return(NULL);
}
- data = um_kmalloc(sizeof(*data));
+ data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
if(data == NULL) return(NULL);
*data = ((struct fd_chan) { .fd = n,
.raw = opts->raw });
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index 5eeecf8917c3..1171790f742c 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -68,7 +68,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
args = pid_args;
}
- pid = run_helper(pre_exec, &data, args, NULL);
+ pid = run_helper(pre_exec, &data, args);
os_close_file(out_fds[0]);
os_close_file(in_fds[1]);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 4bd40bb43ec2..3e0b68e297f2 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -454,7 +454,10 @@ int line_open(struct line *lines, struct tty_struct *tty)
tty->driver_data = line;
line->tty = tty;
- enable_chan(line);
+ err = enable_chan(line);
+ if (err)
+ return err;
+
INIT_DELAYED_WORK(&line->task, line_timer_cb);
if(!line->sigio){
@@ -746,8 +749,24 @@ struct winch {
int tty_fd;
int pid;
struct tty_struct *tty;
+ unsigned long stack;
};
+static void free_winch(struct winch *winch, int free_irq_ok)
+{
+ list_del(&winch->list);
+
+ if (winch->pid != -1)
+ os_kill_process(winch->pid, 1);
+ if (winch->fd != -1)
+ os_close_file(winch->fd);
+ if (winch->stack != 0)
+ free_stack(winch->stack, 0);
+ if (free_irq_ok)
+ free_irq(WINCH_IRQ, winch);
+ kfree(winch);
+}
+
static irqreturn_t winch_interrupt(int irq, void *data)
{
struct winch *winch = data;
@@ -764,12 +783,13 @@ static irqreturn_t winch_interrupt(int irq, void *data)
"errno = %d\n", -err);
printk("fd %d is losing SIGWINCH support\n",
winch->tty_fd);
+ free_winch(winch, 0);
return IRQ_HANDLED;
}
goto out;
}
}
- tty = winch->tty;
+ tty = winch->tty;
if (tty != NULL) {
line = tty->driver_data;
chan_window_size(&line->chan_list, &tty->winsize.ws_row,
@@ -782,43 +802,44 @@ static irqreturn_t winch_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
-void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
+void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+ unsigned long stack)
{
struct winch *winch;
winch = kmalloc(sizeof(*winch), GFP_KERNEL);
if (winch == NULL) {
printk("register_winch_irq - kmalloc failed\n");
- return;
+ goto cleanup;
}
*winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
.fd = fd,
.tty_fd = tty_fd,
.pid = pid,
- .tty = tty });
+ .tty = tty,
+ .stack = stack });
+
+ if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+ IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+ "winch", winch) < 0) {
+ printk("register_winch_irq - failed to register IRQ\n");
+ goto out_free;
+ }
spin_lock(&winch_handler_lock);
list_add(&winch->list, &winch_handlers);
spin_unlock(&winch_handler_lock);
- if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
- IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- "winch", winch) < 0)
- printk("register_winch_irq - failed to register IRQ\n");
-}
-
-static void free_winch(struct winch *winch)
-{
- list_del(&winch->list);
-
- if(winch->pid != -1)
- os_kill_process(winch->pid, 1);
- if(winch->fd != -1)
- os_close_file(winch->fd);
+ return;
- free_irq(WINCH_IRQ, winch);
+ out_free:
kfree(winch);
+ cleanup:
+ os_kill_process(pid, 1);
+ os_close_file(fd);
+ if (stack != 0)
+ free_stack(stack, 0);
}
static void unregister_winch(struct tty_struct *tty)
@@ -831,7 +852,7 @@ static void unregister_winch(struct tty_struct *tty)
list_for_each(ele, &winch_handlers){
winch = list_entry(ele, struct winch, list);
if(winch->tty == tty){
- free_winch(winch);
+ free_winch(winch, 1);
break;
}
}
@@ -847,7 +868,7 @@ static void winch_cleanup(void)
list_for_each_safe(ele, next, &winch_handlers){
winch = list_entry(ele, struct winch, list);
- free_winch(winch);
+ free_winch(winch, 1);
}
spin_unlock(&winch_handler_lock);
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index d319db16d4ec..236a3dfc297d 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -30,7 +30,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
{
struct sockaddr_in *sin;
- sin = um_kmalloc(sizeof(struct sockaddr_in));
+ sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
if(sin == NULL){
printk("new_addr: allocation of sockaddr_in failed\n");
return NULL;
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 62e5ad63181a..f31e71546e52 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -86,8 +86,9 @@ int mconsole_get_request(int fd, struct mc_request *req)
int len;
req->originlen = sizeof(req->origin);
- req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
- (struct sockaddr *) req->origin, &req->originlen);
+ req->len = recvfrom(fd, &req->request, sizeof(req->request),
+ MSG_DONTWAIT, (struct sockaddr *) req->origin,
+ &req->originlen);
if (req->len < 0)
return 0;
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 3503cff867c3..da946e3e1bf2 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -187,7 +187,7 @@ static int change_tramp(char **argv, char *output, int output_len)
}
pe_data.close_me = fds[0];
pe_data.stdout = fds[1];
- pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
+ pid = run_helper(change_pre_exec, &pe_data, argv);
if (pid > 0) /* Avoid hang as we won't get data in failure case. */
read_output(fds[0], output, output_len);
@@ -217,7 +217,7 @@ static void change(char *dev, char *what, unsigned char *addr,
netmask[2], netmask[3]);
output_len = UM_KERN_PAGE_SIZE;
- output = um_kmalloc(output_len);
+ output = kmalloc(output_len, UM_GFP_KERNEL);
if(output == NULL)
printk("change : failed to allocate output buffer\n");
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 483aa15222a4..1316456e2a28 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -53,7 +53,7 @@ static int pcap_open(void *data)
return -EIO;
}
- pri->compiled = um_kmalloc(sizeof(struct bpf_program));
+ pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL);
if(pri->compiled == NULL){
printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
return -ENOMEM;
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 3f6357d24bee..c799b00012c7 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -50,7 +50,7 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
if(kern_data == NULL)
return NULL;
- data = um_kmalloc(sizeof(*data));
+ data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
if(data == NULL)
goto err;
@@ -188,7 +188,7 @@ int port_connection(int fd, int *socket, int *pid_out)
{ .sock_fd = new,
.pipe_fd = socket[1] });
- err = run_helper(port_pre_exec, &data, argv, NULL);
+ err = run_helper(port_pre_exec, &data, argv);
if(err < 0)
goto out_shutdown;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index df4976c9eef2..1e3fd619a837 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,12 +7,14 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <fcntl.h>
#include <errno.h>
#include <termios.h>
+#include <sys/stat.h>
#include "chan_user.h"
-#include "user.h"
-#include "kern_util.h"
#include "os.h"
+#include "user.h"
+#include "kern_constants.h"
#include "um_malloc.h"
struct pty_chan {
@@ -27,12 +29,14 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct pty_chan *data;
- data = um_kmalloc(sizeof(*data));
- if(data == NULL) return(NULL);
+ data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ if (data == NULL)
+ return NULL;
+
*data = ((struct pty_chan) { .announce = opts->announce,
.dev = device,
.raw = opts->raw });
- return(data);
+ return data;
}
static int pts_open(int input, int output, int primary, void *d,
@@ -43,31 +47,35 @@ static int pts_open(int input, int output, int primary, void *d,
int fd, err;
fd = get_pty();
- if(fd < 0){
+ if (fd < 0) {
err = -errno;
- printk("open_pts : Failed to open pts\n");
+ printk(UM_KERN_ERR "open_pts : Failed to open pts\n");
return err;
}
- if(data->raw){
+
+ if (data->raw) {
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
- if(err)
- return(err);
+ if (err)
+ return err;
err = raw(fd);
- if(err)
- return(err);
+ if (err)
+ return err;
}
dev = ptsname(fd);
sprintf(data->dev_name, "%s", dev);
*dev_out = data->dev_name;
+
if (data->announce)
(*data->announce)(dev, data->dev);
- return(fd);
+
+ return fd;
}
static int getmaster(char *line)
{
+ struct stat buf;
char *pty, *bank, *cp;
int master, err;
@@ -75,24 +83,29 @@ static int getmaster(char *line)
for (bank = "pqrs"; *bank; bank++) {
line[strlen("/dev/pty")] = *bank;
*pty = '0';
- if (os_stat_file(line, NULL) < 0)
+ /* Did we hit the end ? */
+ if ((stat(line, &buf) < 0) && (errno == ENOENT))
break;
+
for (cp = "0123456789abcdef"; *cp; cp++) {
*pty = *cp;
- master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
+ master = open(line, O_RDWR);
if (master >= 0) {
char *tp = &line[strlen("/dev/")];
/* verify slave side is usable */
*tp = 't';
- err = os_access(line, OS_ACC_RW_OK);
+ err = access(line, R_OK | W_OK);
*tp = 'p';
- if(err == 0) return(master);
- (void) os_close_file(master);
+ if(!err)
+ return master;
+ close(master);
}
}
}
- return(-1);
+
+ printk(UM_KERN_ERR "getmaster - no usable host pty devices\n");
+ return -ENOENT;
}
static int pty_open(int input, int output, int primary, void *d,
@@ -103,20 +116,22 @@ static int pty_open(int input, int output, int primary, void *d,
char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
fd = getmaster(dev);
- if(fd < 0)
- return(-errno);
+ if (fd < 0)
+ return fd;
if(data->raw){
err = raw(fd);
- if(err)
- return(err);
+ if (err)
+ return err;
}
- if(data->announce) (*data->announce)(dev, data->dev);
+ if (data->announce)
+ (*data->announce)(dev, data->dev);
sprintf(data->dev_name, "%s", dev);
*dev_out = data->dev_name;
- return(fd);
+
+ return fd;
}
const struct chan_ops pty_ops = {
@@ -144,14 +159,3 @@ const struct chan_ops pts_ops = {
.free = generic_free,
.winch = 0,
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 78f0e515da8f..c0b73c28cff0 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -85,13 +85,13 @@ static int slip_tramp(char **argv, int fd)
pe_data.stdin = fd;
pe_data.stdout = fds[1];
pe_data.close_me = fds[0];
- err = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+ err = run_helper(slip_pre_exec, &pe_data, argv);
if(err < 0)
goto out_close;
pid = err;
output_len = UM_KERN_PAGE_SIZE;
- output = um_kmalloc(output_len);
+ output = kmalloc(output_len, UM_GFP_KERNEL);
if(output == NULL){
printk("slip_tramp : failed to allocate output buffer\n");
os_kill_process(pid, 1);
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 39f889fe9949..0e462f64f227 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -42,7 +42,7 @@ static int slirp_tramp(char **argv, int fd)
pe_data.stdin = fd;
pe_data.stdout = fd;
- pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL);
+ pid = run_helper(slirp_pre_exec, &pe_data, argv);
return(pid);
}
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index fd09ad9e9c0a..875d60d0c6a2 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -42,8 +42,6 @@ static struct chan_opts opts = {
.announce = ssl_announce,
.xterm_title = "Serial Line #%d",
.raw = 1,
- .tramp_stack = 0,
- .in_kernel = 1,
};
static int ssl_config(char *str, char **error_out);
@@ -99,7 +97,13 @@ static int ssl_remove(int n, char **error_out)
static int ssl_open(struct tty_struct *tty, struct file *filp)
{
- return line_open(serial_lines, tty);
+ int err = line_open(serial_lines, tty);
+
+ if (err)
+ printk(KERN_ERR "Failed to open serial line %d, err = %d\n",
+ tty->index, err);
+
+ return err;
}
#if 0
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 2bb4193ac1aa..656036e90b19 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -46,8 +46,6 @@ static struct chan_opts opts = {
.announce = stdio_announce,
.xterm_title = "Virtual Console #%d",
.raw = 1,
- .tramp_stack = 0,
- .in_kernel = 1,
};
static int con_config(char *str, char **error_out);
@@ -101,7 +99,12 @@ static int con_remove(int n, char **error_out)
static int con_open(struct tty_struct *tty, struct file *filp)
{
- return line_open(vts, tty);
+ int err = line_open(vts, tty);
+ if (err)
+ printk(KERN_ERR "Failed to open console %d, err = %d\n",
+ tty->index, err);
+
+ return err;
}
/* Set in an initcall, checked in an exitcall */
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index c07d0d562780..a9f87e19c5bf 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -29,7 +29,7 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
}
str++;
- data = um_kmalloc(sizeof(*data));
+ data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
if(data == NULL)
return NULL;
*data = ((struct tty_chan) { .dev = str,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 2e09f162c42f..fc27f6c72b41 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -712,6 +712,8 @@ static int ubd_add(int n, char **error_out)
ubd_dev->queue->queuedata = ubd_dev;
blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG);
+ if(ubd_dev->cow.file != NULL)
+ blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long));
err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
if(err){
*error_out = "Failed to register device";
@@ -1083,7 +1085,7 @@ static void do_ubd_request(request_queue_t *q)
{
struct io_thread_req *io_req;
struct request *req;
- int n;
+ int n, last_sectors;
while(1){
struct ubd *dev = q->queuedata;
@@ -1099,9 +1101,11 @@ static void do_ubd_request(request_queue_t *q)
}
req = dev->request;
+ last_sectors = 0;
while(dev->start_sg < dev->end_sg){
struct scatterlist *sg = &dev->sg[dev->start_sg];
+ req->sector += last_sectors;
io_req = kmalloc(sizeof(struct io_thread_req),
GFP_ATOMIC);
if(io_req == NULL){
@@ -1113,6 +1117,7 @@ static void do_ubd_request(request_queue_t *q)
(unsigned long long) req->sector << 9,
sg->offset, sg->length, sg->page);
+ last_sectors = sg->length >> 9;
n = os_write_file(thread_fd, &io_req,
sizeof(struct io_thread_req *));
if(n != sizeof(struct io_thread_req *)){
@@ -1124,7 +1129,6 @@ static void do_ubd_request(request_queue_t *q)
return;
}
- req->sector += sg->length >> 9;
dev->start_sg++;
}
dev->end_sg = 0;
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 4707b3f14c2f..41d254bd38df 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -43,6 +43,12 @@ int start_io_thread(unsigned long sp, int *fd_out)
kernel_fd = fds[0];
*fd_out = fds[1];
+ err = os_set_fd_block(*fd_out, 0);
+ if (err) {
+ printk("start_io_thread - failed to set nonblocking I/O.\n");
+ goto out_close;
+ }
+
pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
NULL);
if(pid < 0){
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 571c2b3325d5..fd817e541543 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -1,22 +1,20 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
#include <stdlib.h>
+#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <termios.h>
-#include <signal.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include "kern_util.h"
#include "chan_user.h"
-#include "user.h"
#include "os.h"
+#include "init.h"
+#include "user.h"
#include "xterm.h"
+#include "kern_constants.h"
struct xterm_chan {
int pid;
@@ -25,25 +23,21 @@ struct xterm_chan {
int device;
int raw;
struct termios tt;
- unsigned long stack;
- int direct_rcv;
};
-/* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, const struct chan_opts *opts)
+static void *xterm_init(char *str, int device, const struct chan_opts *opts)
{
struct xterm_chan *data;
data = malloc(sizeof(*data));
- if(data == NULL) return(NULL);
- *data = ((struct xterm_chan) { .pid = -1,
+ if (data == NULL)
+ return NULL;
+ *data = ((struct xterm_chan) { .pid = -1,
.helper_pid = -1,
- .device = device,
+ .device = device,
.title = opts->xterm_title,
- .raw = opts->raw,
- .stack = opts->tramp_stack,
- .direct_rcv = !opts->in_kernel } );
- return(data);
+ .raw = opts->raw } );
+ return data;
}
/* Only changed by xterm_setup, which is a setup */
@@ -57,16 +51,22 @@ static int __init xterm_setup(char *line, int *add)
terminal_emulator = line;
line = strchr(line, ',');
- if(line == NULL) return(0);
+ if (line == NULL)
+ return 0;
+
*line++ = '\0';
- if(*line) title_switch = line;
+ if (*line)
+ title_switch = line;
line = strchr(line, ',');
- if(line == NULL) return(0);
+ if (line == NULL)
+ return 0;
+
*line++ = '\0';
- if(*line) exec_switch = line;
+ if (*line)
+ exec_switch = line;
- return(0);
+ return 0;
}
__uml_setup("xterm=", xterm_setup,
@@ -82,107 +82,128 @@ __uml_setup("xterm=", xterm_setup,
" are 'xterm=gnome-terminal,-t,-x'.\n\n"
);
-/* XXX This badly needs some cleaning up in the error paths
- * Not static because it's called directly by the tt mode gdb code
- */
-int xterm_open(int input, int output, int primary, void *d,
+static int xterm_open(int input, int output, int primary, void *d,
char **dev_out)
{
struct xterm_chan *data = d;
- unsigned long stack;
int pid, fd, new, err;
char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
- char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
+ char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
"/usr/lib/uml/port-helper", "-uml-socket",
file, NULL };
- if(os_access(argv[4], OS_ACC_X_OK) < 0)
+ if (access(argv[4], X_OK) < 0)
argv[4] = "port-helper";
/* Check that DISPLAY is set, this doesn't guarantee the xterm
* will work but w/o it we can be pretty sure it won't. */
- if (!getenv("DISPLAY")) {
- printk("xterm_open: $DISPLAY not set.\n");
+ if (getenv("DISPLAY") == NULL) {
+ printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
return -ENODEV;
}
+ /*
+ * This business of getting a descriptor to a temp file,
+ * deleting the file and closing the descriptor is just to get
+ * a known-unused name for the Unix socket that we really
+ * want.
+ */
fd = mkstemp(file);
- if(fd < 0){
+ if (fd < 0) {
err = -errno;
- printk("xterm_open : mkstemp failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
+ errno);
return err;
}
- if(unlink(file)){
+ if (unlink(file)) {
err = -errno;
- printk("xterm_open : unlink failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
+ errno);
return err;
}
- os_close_file(fd);
+ close(fd);
fd = os_create_unix_socket(file, sizeof(file), 1);
- if(fd < 0){
- printk("xterm_open : create_unix_socket failed, errno = %d\n",
- -fd);
- return(fd);
+ if (fd < 0) {
+ printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
+ "errno = %d\n", -fd);
+ return fd;
}
sprintf(title, data->title, data->device);
- stack = data->stack;
- pid = run_helper(NULL, NULL, argv, &stack);
- if(pid < 0){
- printk("xterm_open : run_helper failed, errno = %d\n", -pid);
- return(pid);
+ pid = run_helper(NULL, NULL, argv);
+ if (pid < 0) {
+ err = pid;
+ printk(UM_KERN_ERR "xterm_open : run_helper failed, "
+ "errno = %d\n", -err);
+ goto out_close1;
}
- if (data->direct_rcv) {
- new = os_rcv_fd(fd, &data->helper_pid);
- } else {
- err = os_set_fd_block(fd, 0);
- if(err < 0){
- printk("xterm_open : failed to set descriptor "
- "non-blocking, err = %d\n", -err);
- return(err);
- }
- new = xterm_fd(fd, &data->helper_pid);
+ err = os_set_fd_block(fd, 0);
+ if (err < 0) {
+ printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
+ "non-blocking, err = %d\n", -err);
+ goto out_kill;
}
- if(new < 0){
- printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
- goto out;
+
+ new = xterm_fd(fd, &data->helper_pid);
+ if (new < 0) {
+ err = new;
+ printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
+ -err);
+ goto out_kill;
+ }
+
+ err = os_set_fd_block(new, 0);
+ if (err) {
+ printk(UM_KERN_ERR "xterm_open : failed to set xterm "
+ "descriptor non-blocking, err = %d\n", -err);
+ goto out_close2;
}
CATCH_EINTR(err = tcgetattr(new, &data->tt));
- if(err){
+ if (err) {
new = err;
- goto out;
+ goto out_close2;
}
- if(data->raw){
+ if (data->raw) {
err = raw(new);
- if(err){
+ if (err) {
new = err;
- goto out;
+ goto out_close2;
}
}
+ unlink(file);
data->pid = pid;
*dev_out = NULL;
- out:
- unlink(file);
- return(new);
+
+ return new;
+
+ out_close2:
+ close(new);
+ out_kill:
+ os_kill_process(pid, 1);
+ out_close1:
+ close(fd);
+
+ return err;
}
-/* Not static because it's called directly by the tt mode gdb code */
-void xterm_close(int fd, void *d)
+static void xterm_close(int fd, void *d)
{
struct xterm_chan *data = d;
- if(data->pid != -1)
+ if (data->pid != -1)
os_kill_process(data->pid, 1);
data->pid = -1;
- if(data->helper_pid != -1)
+
+ if (data->helper_pid != -1)
os_kill_process(data->helper_pid, 0);
data->helper_pid = -1;
+
os_close_file(fd);
}
@@ -203,14 +224,3 @@ const struct chan_ops xterm_ops = {
.free = xterm_free,
.winch = 1,
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4ce7058e10e..b646bccef37a 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -1,18 +1,14 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/errno.h"
-#include "linux/slab.h"
-#include "linux/signal.h"
-#include "linux/interrupt.h"
-#include "asm/irq.h"
-#include "irq_user.h"
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/irqreturn.h>
+#include <asm/irq.h>
#include "irq_kern.h"
-#include "kern_util.h"
#include "os.h"
-#include "xterm.h"
struct xterm_wait {
struct completion ready;
@@ -27,12 +23,13 @@ static irqreturn_t xterm_interrupt(int irq, void *data)
int fd;
fd = os_rcv_fd(xterm->fd, &xterm->pid);
- if(fd == -EAGAIN)
- return(IRQ_NONE);
+ if (fd == -EAGAIN)
+ return IRQ_NONE;
xterm->new_fd = fd;
complete(&xterm->ready);
- return(IRQ_HANDLED);
+
+ return IRQ_HANDLED;
}
int xterm_fd(int socket, int *pid_out)
@@ -41,22 +38,21 @@ int xterm_fd(int socket, int *pid_out)
int err, ret;
data = kmalloc(sizeof(*data), GFP_KERNEL);
- if(data == NULL){
+ if (data == NULL) {
printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n");
- return(-ENOMEM);
+ return -ENOMEM;
}
/* This is a locked semaphore... */
- *data = ((struct xterm_wait)
- { .fd = socket,
- .pid = -1,
- .new_fd = -1 });
+ *data = ((struct xterm_wait) { .fd = socket,
+ .pid = -1,
+ .new_fd = -1 });
init_completion(&data->ready);
- err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
+ err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"xterm", data);
- if (err){
+ if (err) {
printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
"err = %d\n", err);
ret = err;
@@ -76,16 +72,5 @@ int xterm_fd(int socket, int *pid_out)
out:
kfree(data);
- return(ret);
+ return ret;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index c4b41bb1035f..624b5100a3cd 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -40,7 +40,7 @@ extern int console_open_chan(struct line *line, struct console *co);
extern void deactivate_chan(struct list_head *chans, int irq);
extern void reactivate_chan(struct list_head *chans, int irq);
extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern void enable_chan(struct line *line);
+extern int enable_chan(struct line *line);
extern void close_chan(struct list_head *chans, int delay_free_irq);
extern int chan_window_size(struct list_head *chans,
unsigned short *rows_out,
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 38f16d812e7c..5a2263e05bb2 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -12,8 +12,6 @@ struct chan_opts {
void (*const announce)(char *dev_name, int dev);
char *xterm_title;
const int raw;
- const unsigned long tramp_stack;
- const int in_kernel;
};
enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
@@ -44,7 +42,8 @@ extern void generic_free(void *data);
struct tty_struct;
extern void register_winch(int fd, struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+ struct tty_struct *tty, unsigned long stack);
#define __channel_help(fn, prefix) \
__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 7376ee44e330..6eee343e53eb 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -27,6 +27,9 @@ DEFINE(UM_ELFCLASS64, ELFCLASS64);
DEFINE(UM_NR_CPUS, NR_CPUS);
+DEFINE(UM_GFP_KERNEL, GFP_KERNEL);
+DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
+
/* For crypto assembler code. */
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 4d9fb26387d5..930b261ea483 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -239,11 +239,9 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n,
/* execvp.c */
extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
/* helper.c */
-extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
- unsigned long *stack_out);
+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
extern int run_helper_thread(int (*proc)(void *), void *arg,
- unsigned int flags, unsigned long *stack_out,
- int stack_order);
+ unsigned int flags, unsigned long *stack_out);
extern int helper_wait(int pid);
diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h
index e6d7c5aa3f4e..0ad17cb83d96 100644
--- a/arch/um/include/um_malloc.h
+++ b/arch/um/include/um_malloc.h
@@ -6,11 +6,17 @@
#ifndef __UM_MALLOC_H__
#define __UM_MALLOC_H__
-extern void *um_kmalloc(int size);
-extern void *um_kmalloc_atomic(int size);
+#include "kern_constants.h"
+
+extern void *__kmalloc(int size, int flags);
+static inline void *kmalloc(int size, int flags)
+{
+ return __kmalloc(size, flags);
+}
+
extern void kfree(const void *ptr);
-extern void *um_vmalloc(int size);
+extern void *vmalloc(unsigned long size);
extern void vfree(void *ptr);
#endif /* __UM_MALLOC_H__ */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index dba04d88b432..9870febdbead 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -30,7 +30,6 @@
#include "irq_kern.h"
#include "os.h"
#include "sigio.h"
-#include "um_malloc.h"
#include "misc_constants.h"
#include "as-layout.h"
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 8d2c5496532b..bfa52f206bb6 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -46,7 +46,6 @@
#include "mode.h"
#include "mode_kern.h"
#include "choose-mode.h"
-#include "um_malloc.h"
/* This is a per-cpu array. A processor only modifies its entry and it only
* cares about its entry, so it's OK if another processor is modifying its
@@ -262,21 +261,6 @@ void dump_thread(struct pt_regs *regs, struct user *u)
{
}
-void *um_kmalloc(int size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-void *um_kmalloc_atomic(int size)
-{
- return kmalloc(size, GFP_ATOMIC);
-}
-
-void *um_vmalloc(int size)
-{
- return vmalloc(size);
-}
-
int __cant_sleep(void) {
return in_atomic() || irqs_disabled() || in_interrupt();
/* Is in_interrupt() really needed? */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 627742d89434..6916c8888dba 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -52,17 +52,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- ret = -EIO;
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp, p);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR:
@@ -72,11 +64,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = -EIO;
- if (access_process_vm(child, addr, &data, sizeof(data),
- 1) != sizeof(data))
- break;
- ret = 0;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 9bf944f6a1db..b126df4ea168 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -177,6 +177,7 @@ static int do_not_aio(struct aio_thread_req *req)
static int aio_req_fd_r = -1;
static int aio_req_fd_w = -1;
static int aio_pid = -1;
+static unsigned long aio_stack;
static int not_aio_thread(void *arg)
{
@@ -212,7 +213,6 @@ static int not_aio_thread(void *arg)
static int init_aio_24(void)
{
- unsigned long stack;
int fds[2], err;
err = os_pipe(fds, 1, 1);
@@ -227,7 +227,7 @@ static int init_aio_24(void)
goto out_close_pipe;
err = run_helper_thread(not_aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+ CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
if(err < 0)
goto out_close_pipe;
@@ -252,7 +252,6 @@ out:
#define DEFAULT_24_AIO 0
static int init_aio_26(void)
{
- unsigned long stack;
int err;
if(io_setup(256, &ctx)){
@@ -263,7 +262,7 @@ static int init_aio_26(void)
}
err = run_helper_thread(aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+ CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
if(err < 0)
return err;
@@ -365,8 +364,10 @@ __initcall(init_aio);
static void exit_aio(void)
{
- if(aio_pid != -1)
+ if (aio_pid != -1) {
os_kill_process(aio_pid, 1);
+ free_stack(aio_stack, 0);
+ }
}
__uml_exitcall(exit_aio);
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index acba30161287..61d3953c7ac9 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -54,7 +54,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
return;
}
- output = um_kmalloc(UM_KERN_PAGE_SIZE);
+ output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
if(output == NULL)
printk("etap_change : Failed to allocate output buffer\n");
read_output(fd, output, UM_KERN_PAGE_SIZE);
@@ -117,7 +117,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
pe_data.control_remote = control_remote;
pe_data.control_me = control_me;
pe_data.data_me = data_me;
- pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
+ pid = run_helper(etap_pre_exec, &pe_data, args);
if(pid < 0)
err = pid;
@@ -166,7 +166,7 @@ static int etap_open(void *data)
err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
control_fds[1], data_fds[0], data_fds[1]);
output_len = UM_KERN_PAGE_SIZE;
- output = um_kmalloc(output_len);
+ output = kmalloc(output_len, UM_GFP_KERNEL);
read_output(control_fds[0], output, output_len);
if(output == NULL)
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 11a9779dc9f1..f848b4ea9343 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -83,7 +83,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
data.stdout = remote;
data.close_me = me;
- pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
+ pid = run_helper(tuntap_pre_exec, &data, argv);
if(pid < 0)
return -pid;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 97bed16bf4c7..d81af7b8587a 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -44,17 +44,13 @@ static int helper_child(void *arg)
/* Returns either the pid of the child process we run or -E* on failure.
* XXX The alloc_stack here breaks if this is called in the tracing thread, so
* we need to receive a preallocated stack (a local buffer is ok). */
-int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
- unsigned long *stack_out)
+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
{
struct helper_data data;
unsigned long stack, sp;
int pid, fds[2], ret, n;
- if ((stack_out != NULL) && (*stack_out != 0))
- stack = *stack_out;
- else
- stack = alloc_stack(0, __cant_sleep());
+ stack = alloc_stack(0, __cant_sleep());
if (stack == 0)
return -ENOMEM;
@@ -76,8 +72,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
data.pre_data = pre_data;
data.argv = argv;
data.fd = fds[1];
- data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) :
- um_kmalloc(PATH_MAX);
+ data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
+ kmalloc(PATH_MAX, UM_GFP_KERNEL);
pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
if (pid < 0) {
ret = -errno;
@@ -113,22 +109,21 @@ out_close:
close(fds[1]);
close(fds[0]);
out_free:
- if ((stack_out == NULL) || (*stack_out == 0))
- free_stack(stack, 0);
+ free_stack(stack, 0);
return ret;
}
int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
- unsigned long *stack_out, int stack_order)
+ unsigned long *stack_out)
{
unsigned long stack, sp;
int pid, status, err;
- stack = alloc_stack(stack_order, __cant_sleep());
+ stack = alloc_stack(0, __cant_sleep());
if (stack == 0)
return -ENOMEM;
- sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *);
+ sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
if (pid < 0) {
err = -errno;
@@ -147,7 +142,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
printk("run_helper_thread - thread returned status "
"0x%x\n", status);
- free_stack(stack, stack_order);
+ free_stack(stack, 0);
} else
*stack_out = stack;
return pid;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index fb510d40480c..e85f4995a011 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -235,8 +235,8 @@ void *__wrap_malloc(int size)
return __real_malloc(size);
else if(size <= UM_KERN_PAGE_SIZE)
/* finding contiguous pages can be hard*/
- ret = um_kmalloc(size);
- else ret = um_vmalloc(size);
+ ret = kmalloc(size, UM_GFP_KERNEL);
+ else ret = vmalloc(size);
/* glibc people insist that if malloc fails, errno should be
* set by malloc as well. So we do.
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 8d4e0c6b8c92..dc03e9cccb63 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -26,6 +26,7 @@
* exitcall.
*/
static int write_sigio_pid = -1;
+static unsigned long write_sigio_stack;
/* These arrays are initialized before the sigio thread is started, and
* the descriptors closed after it is killed. So, it can't see them change.
@@ -104,7 +105,7 @@ static int need_poll(struct pollfds *polls, int n)
if(n <= polls->size)
return 0;
- new = um_kmalloc_atomic(n * sizeof(struct pollfd));
+ new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
if(new == NULL){
printk("need_poll : failed to allocate new pollfds\n");
return -ENOMEM;
@@ -144,8 +145,10 @@ static void update_thread(void)
return;
fail:
/* Critical section start */
- if(write_sigio_pid != -1)
+ if (write_sigio_pid != -1) {
os_kill_process(write_sigio_pid, 1);
+ free_stack(write_sigio_stack, 0);
+ }
write_sigio_pid = -1;
close(sigio_private[0]);
close(sigio_private[1]);
@@ -230,7 +233,7 @@ static struct pollfd *setup_initial_poll(int fd)
{
struct pollfd *p;
- p = um_kmalloc(sizeof(struct pollfd));
+ p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
if (p == NULL) {
printk("setup_initial_poll : failed to allocate poll\n");
return NULL;
@@ -243,7 +246,6 @@ static struct pollfd *setup_initial_poll(int fd)
static void write_sigio_workaround(void)
{
- unsigned long stack;
struct pollfd *p;
int err;
int l_write_sigio_fds[2];
@@ -293,7 +295,8 @@ static void write_sigio_workaround(void)
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
- CLONE_FILES | CLONE_VM, &stack, 0);
+ CLONE_FILES | CLONE_VM,
+ &write_sigio_stack);
if (write_sigio_pid < 0)
goto out_clear;
@@ -356,10 +359,12 @@ out:
static void sigio_cleanup(void)
{
- if(write_sigio_pid != -1){
- os_kill_process(write_sigio_pid, 1);
- write_sigio_pid = -1;
- }
+ if (write_sigio_pid == -1)
+ return;
+
+ os_kill_process(write_sigio_pid, 1);
+ free_stack(write_sigio_stack, 0);
+ write_sigio_pid = -1;
}
__uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 46c00cc429bc..ba9af8d62055 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -41,7 +41,7 @@ int is_skas_winch(int pid, int fd, void *data)
if(pid != os_getpgrp())
return(0);
- register_winch_irq(-1, fd, -1, data);
+ register_winch_irq(-1, fd, -1, data, 0);
return(1);
}
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 3f33165ada68..419b2d5ff6de 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -5,7 +5,8 @@
* so I *must* declare good prototypes for them and then EXPORT them.
* The kernel code uses the macro defined by include/linux/string.h,
* so I undef macros; the userspace code does not include that and I
- * add an EXPORT for the glibc one.*/
+ * add an EXPORT for the glibc one.
+ */
#undef strlen
#undef strstr
@@ -61,12 +62,18 @@ EXPORT_SYMBOL_PROTO(dup2);
EXPORT_SYMBOL_PROTO(__xstat);
EXPORT_SYMBOL_PROTO(__lxstat);
EXPORT_SYMBOL_PROTO(__lxstat64);
+EXPORT_SYMBOL_PROTO(__fxstat64);
EXPORT_SYMBOL_PROTO(lseek);
EXPORT_SYMBOL_PROTO(lseek64);
EXPORT_SYMBOL_PROTO(chown);
+EXPORT_SYMBOL_PROTO(fchown);
EXPORT_SYMBOL_PROTO(truncate);
+EXPORT_SYMBOL_PROTO(ftruncate64);
EXPORT_SYMBOL_PROTO(utime);
+EXPORT_SYMBOL_PROTO(utimes);
+EXPORT_SYMBOL_PROTO(futimes);
EXPORT_SYMBOL_PROTO(chmod);
+EXPORT_SYMBOL_PROTO(fchmod);
EXPORT_SYMBOL_PROTO(rename);
EXPORT_SYMBOL_PROTO(__xmknod);
@@ -102,14 +109,3 @@ EXPORT_SYMBOL(__stack_smash_handler);
extern long __guard __attribute__((weak));
EXPORT_SYMBOL(__guard);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index a9b09343097d..a458ac941b25 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -117,24 +117,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int rval;
switch (request) {
- unsigned long val, copied;
+ unsigned long val;
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
- copied = access_process_vm(child, addr, &val, sizeof(val), 0);
- rval = -EIO;
- if (copied != sizeof(val))
- break;
- rval = put_user(val, (unsigned long *)data);
+ rval = generic_ptrace_peekdata(child, addr, data);
goto out;
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- rval = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1)
- == sizeof(data))
- break;
- rval = -EIO;
+ rval = generic_ptrace_pokedata(child, addr, data);
goto out;
/* Read/write the word at location ADDR in the registers. */
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 8bdd25ac1542..14bf8ce3ea23 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -774,8 +774,8 @@ menu "Instrumentation Support"
source "arch/x86_64/oprofile/Kconfig"
config KPROBES
- bool "Kprobes (EXPERIMENTAL)"
- depends on KALLSYMS && EXPERIMENTAL && MODULES
+ bool "Kprobes"
+ depends on KALLSYMS && MODULES
help
Kprobes allows you to trap at almost any kernel address and
execute a callback function. register_kprobe() establishes
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 47565c3345d2..782dea819438 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -526,7 +526,7 @@ ia32_sys_call_table:
.quad sys_init_module
.quad sys_delete_module
.quad quiet_ni_syscall /* 130 get_kernel_syms */
- .quad sys_quotactl
+ .quad sys32_quotactl
.quad sys_getpgid
.quad sys_fchdir
.quad quiet_ni_syscall /* bdflush */
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 1fab487dee86..941c84baecc8 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -73,7 +73,11 @@ startup_64:
addq %rbp, init_level4_pgt + (511*8)(%rip)
addq %rbp, level3_ident_pgt + 0(%rip)
+
addq %rbp, level3_kernel_pgt + (510*8)(%rip)
+ addq %rbp, level3_kernel_pgt + (511*8)(%rip)
+
+ addq %rbp, level2_fixmap_pgt + (506*8)(%rip)
/* Add an Identity mapping if I am above 1G */
leaq _text(%rip), %rdi
@@ -314,7 +318,16 @@ NEXT_PAGE(level3_kernel_pgt)
.fill 510,8,0
/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
.quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
- .fill 1,8,0
+ .quad level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+
+NEXT_PAGE(level2_fixmap_pgt)
+ .fill 506,8,0
+ .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+ /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
+ .fill 5,8,0
+
+NEXT_PAGE(level1_fixmap_pgt)
+ .fill 512,8,0
NEXT_PAGE(level2_ident_pgt)
/* Since I easily can, map the first 1G.
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 931c64bad5e6..edbbc59b7523 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -296,7 +296,7 @@ static DEFINE_PER_CPU(unsigned, last_irq_sum);
static DEFINE_PER_CPU(local_t, alert_counter);
static DEFINE_PER_CPU(int, nmi_touch);
-void touch_nmi_watchdog (void)
+void touch_nmi_watchdog(void)
{
if (nmi_watchdog > 0) {
unsigned cpu;
@@ -306,8 +306,10 @@ void touch_nmi_watchdog (void)
* do it ourselves because the alert count increase is not
* atomic.
*/
- for_each_present_cpu (cpu)
- per_cpu(nmi_touch, cpu) = 1;
+ for_each_present_cpu(cpu) {
+ if (per_cpu(nmi_touch, cpu) != 1)
+ per_cpu(nmi_touch, cpu) = 1;
+ }
}
touch_softlockup_watchdog();
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 9409117b9f19..fa6775ef729f 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -313,17 +313,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long __user *) data);
+ case PTRACE_PEEKDATA:
+ ret = generic_ptrace_peekdata(child, addr, data);
break;
- }
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
@@ -367,10 +359,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 2ff468591625..0694940b2e73 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -357,7 +357,7 @@ __smp_call_function_single(int cpu, void (*func) (void *info), void *info,
}
/*
- * smp_call_function_single - Run a function on another CPU
+ * smp_call_function_single - Run a function on a specific CPU
* @func: The function to run. This must be fast and non-blocking.
* @info: An arbitrary pointer to pass to the function.
* @nonatomic: Currently unused.
@@ -374,14 +374,18 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
{
/* prevent preemption and reschedule on another processor */
int me = get_cpu();
+
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+
if (cpu == me) {
+ local_irq_disable();
+ func(info);
+ local_irq_enable();
put_cpu();
return 0;
}
- /* Can deadlock when called with interrupts disabled */
- WARN_ON(irqs_disabled());
-
spin_lock_bh(&call_lock);
__smp_call_function_single(cpu, func, info, nonatomic, wait);
spin_unlock_bh(&call_lock);
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index aac1c0be54c6..74cbeb2e99a6 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -330,6 +330,7 @@ static int print_trace_stack(void *data, char *name)
static void print_trace_address(void *data, unsigned long addr)
{
+ touch_nmi_watchdog();
printk_address(addr);
}
@@ -518,6 +519,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
show_registers(regs);
+ add_taint(TAINT_DIE);
/* Executive summary in case the oops scrolled away */
printk(KERN_ALERT "RIP ");
printk_address(regs->rip);
@@ -531,7 +533,7 @@ void die(const char * str, struct pt_regs * regs, long err)
unsigned long flags = oops_begin();
if (!user_mode(regs))
- report_bug(regs->rip);
+ report_bug(regs->rip, regs);
__die(str, regs, err);
oops_end(flags);
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 14104ff63093..06a13d9b69db 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -50,18 +50,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
- {
- unsigned long tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp,(unsigned long *) data);
-
+ ret = generic_ptrace_peekdata(child, addr, data);
goto out;
- }
/* Read the word at location addr in the USER area. */
@@ -138,10 +128,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- if (access_process_vm(child, addr, &data, sizeof(data), 1)
- == sizeof(data))
- break;
- ret = -EIO;
+ ret = generic_ptrace_pokedata(child, addr, data);
goto out;
case PTRACE_POKEUSR:
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 693ab268485e..c5e62f9d9f50 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -482,6 +482,7 @@ void die(const char * str, struct pt_regs * regs, long err)
if (!user_mode(regs))
show_stack(NULL, (unsigned long*)regs->areg[1]);
+ add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
diff --git a/block/Kconfig b/block/Kconfig
index 285935134bcd..0768741d6813 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -51,4 +51,17 @@ config LSF
endif # BLOCK
+config BLK_DEV_BSG
+ bool "Block layer SG support v4 (EXPERIMENTAL)"
+ depends on (SCSI=y) && EXPERIMENTAL
+ ---help---
+ Saying Y here will enable generic SG (SCSI generic) v4 support
+ for any block device.
+
+ Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
+ can handle complicated SCSI commands: tagged variable length cdbs
+ with bidirectional data transfers and generic request/response
+ protocols (e.g. Task Management Functions and SMP in Serial
+ Attached SCSI).
+
source block/Kconfig.iosched
diff --git a/block/Makefile b/block/Makefile
index 4b84d0d5947b..959feeb253be 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
+obj-$(CONFIG_BLK_DEV_BSG) += bsg.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_AS) += as-iosched.o
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 109e91b91ffa..3e316dd72529 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1322,10 +1322,9 @@ static void *as_init_queue(request_queue_t *q)
{
struct as_data *ad;
- ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
+ ad = kmalloc_node(sizeof(*ad), GFP_KERNEL | __GFP_ZERO, q->node);
if (!ad)
return NULL;
- memset(ad, 0, sizeof(*ad));
ad->q = q; /* Identify what queue the data belongs to */
diff --git a/block/bsg.c b/block/bsg.c
new file mode 100644
index 000000000000..baa04e7adf19
--- /dev/null
+++ b/block/bsg.c
@@ -0,0 +1,1095 @@
+/*
+ * bsg.c - block layer implementation of the sg v3 interface
+ *
+ * Copyright (C) 2004 Jens Axboe <axboe@suse.de> SUSE Labs
+ * Copyright (C) 2004 Peter M. Jones <pjones@redhat.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ */
+/*
+ * TODO
+ * - Should this get merged, block/scsi_ioctl.c will be migrated into
+ * this file. To keep maintenance down, it's easier to have them
+ * seperated right now.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/blkdev.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/percpu.h>
+#include <linux/uio.h>
+#include <linux/bsg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/sg.h>
+
+#define BSG_DESCRIPTION "Block layer SCSI generic (bsg) driver"
+#define BSG_VERSION "0.4"
+
+struct bsg_device {
+ request_queue_t *queue;
+ spinlock_t lock;
+ struct list_head busy_list;
+ struct list_head done_list;
+ struct hlist_node dev_list;
+ atomic_t ref_count;
+ int minor;
+ int queued_cmds;
+ int done_cmds;
+ wait_queue_head_t wq_done;
+ wait_queue_head_t wq_free;
+ char name[BUS_ID_SIZE];
+ int max_queue;
+ unsigned long flags;
+};
+
+enum {
+ BSG_F_BLOCK = 1,
+ BSG_F_WRITE_PERM = 2,
+};
+
+#define BSG_DEFAULT_CMDS 64
+#define BSG_MAX_DEVS 32768
+
+#undef BSG_DEBUG
+
+#ifdef BSG_DEBUG
+#define dprintk(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ##args)
+#else
+#define dprintk(fmt, args...)
+#endif
+
+static DEFINE_MUTEX(bsg_mutex);
+static int bsg_device_nr, bsg_minor_idx;
+
+#define BSG_LIST_ARRAY_SIZE 8
+static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE];
+
+static struct class *bsg_class;
+static LIST_HEAD(bsg_class_list);
+static int bsg_major;
+
+static struct kmem_cache *bsg_cmd_cachep;
+
+/*
+ * our internal command type
+ */
+struct bsg_command {
+ struct bsg_device *bd;
+ struct list_head list;
+ struct request *rq;
+ struct bio *bio;
+ struct bio *bidi_bio;
+ int err;
+ struct sg_io_v4 hdr;
+ struct sg_io_v4 __user *uhdr;
+ char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static void bsg_free_command(struct bsg_command *bc)
+{
+ struct bsg_device *bd = bc->bd;
+ unsigned long flags;
+
+ kmem_cache_free(bsg_cmd_cachep, bc);
+
+ spin_lock_irqsave(&bd->lock, flags);
+ bd->queued_cmds--;
+ spin_unlock_irqrestore(&bd->lock, flags);
+
+ wake_up(&bd->wq_free);
+}
+
+static struct bsg_command *bsg_alloc_command(struct bsg_device *bd)
+{
+ struct bsg_command *bc = ERR_PTR(-EINVAL);
+
+ spin_lock_irq(&bd->lock);
+
+ if (bd->queued_cmds >= bd->max_queue)
+ goto out;
+
+ bd->queued_cmds++;
+ spin_unlock_irq(&bd->lock);
+
+ bc = kmem_cache_zalloc(bsg_cmd_cachep, GFP_KERNEL);
+ if (unlikely(!bc)) {
+ spin_lock_irq(&bd->lock);
+ bd->queued_cmds--;
+ bc = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ bc->bd = bd;
+ INIT_LIST_HEAD(&bc->list);
+ dprintk("%s: returning free cmd %p\n", bd->name, bc);
+ return bc;
+out:
+ spin_unlock_irq(&bd->lock);
+ return bc;
+}
+
+static inline struct hlist_head *bsg_dev_idx_hash(int index)
+{
+ return &bsg_device_list[index & (BSG_LIST_ARRAY_SIZE - 1)];
+}
+
+static int bsg_io_schedule(struct bsg_device *bd)
+{
+ DEFINE_WAIT(wait);
+ int ret = 0;
+
+ spin_lock_irq(&bd->lock);
+
+ BUG_ON(bd->done_cmds > bd->queued_cmds);
+
+ /*
+ * -ENOSPC or -ENODATA? I'm going for -ENODATA, meaning "I have no
+ * work to do", even though we return -ENOSPC after this same test
+ * during bsg_write() -- there, it means our buffer can't have more
+ * bsg_commands added to it, thus has no space left.
+ */
+ if (bd->done_cmds == bd->queued_cmds) {
+ ret = -ENODATA;
+ goto unlock;
+ }
+
+ if (!test_bit(BSG_F_BLOCK, &bd->flags)) {
+ ret = -EAGAIN;
+ goto unlock;
+ }
+
+ prepare_to_wait(&bd->wq_done, &wait, TASK_UNINTERRUPTIBLE);
+ spin_unlock_irq(&bd->lock);
+ io_schedule();
+ finish_wait(&bd->wq_done, &wait);
+
+ return ret;
+unlock:
+ spin_unlock_irq(&bd->lock);
+ return ret;
+}
+
+static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq,
+ struct sg_io_v4 *hdr, int has_write_perm)
+{
+ memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+
+ if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
+ hdr->request_len))
+ return -EFAULT;
+
+ if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
+ if (blk_verify_command(rq->cmd, has_write_perm))
+ return -EPERM;
+ } else if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ /*
+ * fill in request structure
+ */
+ rq->cmd_len = hdr->request_len;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+ rq->timeout = (hdr->timeout * HZ) / 1000;
+ if (!rq->timeout)
+ rq->timeout = q->sg_timeout;
+ if (!rq->timeout)
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+
+ return 0;
+}
+
+/*
+ * Check if sg_io_v4 from user is allowed and valid
+ */
+static int
+bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw)
+{
+ int ret = 0;
+
+ if (hdr->guard != 'Q')
+ return -EINVAL;
+ if (hdr->request_len > BLK_MAX_CDB)
+ return -EINVAL;
+ if (hdr->dout_xfer_len > (q->max_sectors << 9) ||
+ hdr->din_xfer_len > (q->max_sectors << 9))
+ return -EIO;
+
+ switch (hdr->protocol) {
+ case BSG_PROTOCOL_SCSI:
+ switch (hdr->subprotocol) {
+ case BSG_SUB_PROTOCOL_SCSI_CMD:
+ case BSG_SUB_PROTOCOL_SCSI_TRANSPORT:
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ *rw = hdr->dout_xfer_len ? WRITE : READ;
+ return ret;
+}
+
+/*
+ * map sg_io_v4 to a request.
+ */
+static struct request *
+bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
+{
+ request_queue_t *q = bd->queue;
+ struct request *rq, *next_rq = NULL;
+ int ret, rw;
+ unsigned int dxfer_len;
+ void *dxferp = NULL;
+
+ dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
+ hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
+ hdr->din_xfer_len);
+
+ ret = bsg_validate_sgv4_hdr(q, hdr, &rw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /*
+ * map scatter-gather elements seperately and string them to request
+ */
+ rq = blk_get_request(q, rw, GFP_KERNEL);
+ if (!rq)
+ return ERR_PTR(-ENOMEM);
+ ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM,
+ &bd->flags));
+ if (ret)
+ goto out;
+
+ if (rw == WRITE && hdr->din_xfer_len) {
+ if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ next_rq = blk_get_request(q, READ, GFP_KERNEL);
+ if (!next_rq) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ rq->next_rq = next_rq;
+
+ dxferp = (void*)(unsigned long)hdr->din_xferp;
+ ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len);
+ if (ret)
+ goto out;
+ }
+
+ if (hdr->dout_xfer_len) {
+ dxfer_len = hdr->dout_xfer_len;
+ dxferp = (void*)(unsigned long)hdr->dout_xferp;
+ } else if (hdr->din_xfer_len) {
+ dxfer_len = hdr->din_xfer_len;
+ dxferp = (void*)(unsigned long)hdr->din_xferp;
+ } else
+ dxfer_len = 0;
+
+ if (dxfer_len) {
+ ret = blk_rq_map_user(q, rq, dxferp, dxfer_len);
+ if (ret)
+ goto out;
+ }
+ return rq;
+out:
+ blk_put_request(rq);
+ if (next_rq) {
+ blk_rq_unmap_user(next_rq->bio);
+ blk_put_request(next_rq);
+ }
+ return ERR_PTR(ret);
+}
+
+/*
+ * async completion call-back from the block layer, when scsi/ide/whatever
+ * calls end_that_request_last() on a request
+ */
+static void bsg_rq_end_io(struct request *rq, int uptodate)
+{
+ struct bsg_command *bc = rq->end_io_data;
+ struct bsg_device *bd = bc->bd;
+ unsigned long flags;
+
+ dprintk("%s: finished rq %p bc %p, bio %p stat %d\n",
+ bd->name, rq, bc, bc->bio, uptodate);
+
+ bc->hdr.duration = jiffies_to_msecs(jiffies - bc->hdr.duration);
+
+ spin_lock_irqsave(&bd->lock, flags);
+ list_move_tail(&bc->list, &bd->done_list);
+ bd->done_cmds++;
+ spin_unlock_irqrestore(&bd->lock, flags);
+
+ wake_up(&bd->wq_done);
+}
+
+/*
+ * do final setup of a 'bc' and submit the matching 'rq' to the block
+ * layer for io
+ */
+static void bsg_add_command(struct bsg_device *bd, request_queue_t *q,
+ struct bsg_command *bc, struct request *rq)
+{
+ rq->sense = bc->sense;
+ rq->sense_len = 0;
+
+ /*
+ * add bc command to busy queue and submit rq for io
+ */
+ bc->rq = rq;
+ bc->bio = rq->bio;
+ if (rq->next_rq)
+ bc->bidi_bio = rq->next_rq->bio;
+ bc->hdr.duration = jiffies;
+ spin_lock_irq(&bd->lock);
+ list_add_tail(&bc->list, &bd->busy_list);
+ spin_unlock_irq(&bd->lock);
+
+ dprintk("%s: queueing rq %p, bc %p\n", bd->name, rq, bc);
+
+ rq->end_io_data = bc;
+ blk_execute_rq_nowait(q, NULL, rq, 1, bsg_rq_end_io);
+}
+
+static struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd)
+{
+ struct bsg_command *bc = NULL;
+
+ spin_lock_irq(&bd->lock);
+ if (bd->done_cmds) {
+ bc = list_entry(bd->done_list.next, struct bsg_command, list);
+ list_del(&bc->list);
+ bd->done_cmds--;
+ }
+ spin_unlock_irq(&bd->lock);
+
+ return bc;
+}
+
+/*
+ * Get a finished command from the done list
+ */
+static struct bsg_command *bsg_get_done_cmd(struct bsg_device *bd)
+{
+ struct bsg_command *bc;
+ int ret;
+
+ do {
+ bc = bsg_next_done_cmd(bd);
+ if (bc)
+ break;
+
+ if (!test_bit(BSG_F_BLOCK, &bd->flags)) {
+ bc = ERR_PTR(-EAGAIN);
+ break;
+ }
+
+ ret = wait_event_interruptible(bd->wq_done, bd->done_cmds);
+ if (ret) {
+ bc = ERR_PTR(-ERESTARTSYS);
+ break;
+ }
+ } while (1);
+
+ dprintk("%s: returning done %p\n", bd->name, bc);
+
+ return bc;
+}
+
+static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
+ struct bio *bio, struct bio *bidi_bio)
+{
+ int ret = 0;
+
+ dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
+ /*
+ * fill in all the output members
+ */
+ hdr->device_status = status_byte(rq->errors);
+ hdr->transport_status = host_byte(rq->errors);
+ hdr->driver_status = driver_byte(rq->errors);
+ hdr->info = 0;
+ if (hdr->device_status || hdr->transport_status || hdr->driver_status)
+ hdr->info |= SG_INFO_CHECK;
+ hdr->din_resid = rq->data_len;
+ hdr->response_len = 0;
+
+ if (rq->sense_len && hdr->response) {
+ int len = min_t(unsigned int, hdr->max_response_len,
+ rq->sense_len);
+
+ ret = copy_to_user((void*)(unsigned long)hdr->response,
+ rq->sense, len);
+ if (!ret)
+ hdr->response_len = len;
+ else
+ ret = -EFAULT;
+ }
+
+ if (rq->next_rq) {
+ blk_rq_unmap_user(bidi_bio);
+ blk_put_request(rq->next_rq);
+ }
+
+ blk_rq_unmap_user(bio);
+ blk_put_request(rq);
+
+ return ret;
+}
+
+static int bsg_complete_all_commands(struct bsg_device *bd)
+{
+ struct bsg_command *bc;
+ int ret, tret;
+
+ dprintk("%s: entered\n", bd->name);
+
+ set_bit(BSG_F_BLOCK, &bd->flags);
+
+ /*
+ * wait for all commands to complete
+ */
+ ret = 0;
+ do {
+ ret = bsg_io_schedule(bd);
+ /*
+ * look for -ENODATA specifically -- we'll sometimes get
+ * -ERESTARTSYS when we've taken a signal, but we can't
+ * return until we're done freeing the queue, so ignore
+ * it. The signal will get handled when we're done freeing
+ * the bsg_device.
+ */
+ } while (ret != -ENODATA);
+
+ /*
+ * discard done commands
+ */
+ ret = 0;
+ do {
+ spin_lock_irq(&bd->lock);
+ if (!bd->queued_cmds) {
+ spin_unlock_irq(&bd->lock);
+ break;
+ }
+ spin_unlock_irq(&bd->lock);
+
+ bc = bsg_get_done_cmd(bd);
+ if (IS_ERR(bc))
+ break;
+
+ tret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio,
+ bc->bidi_bio);
+ if (!ret)
+ ret = tret;
+
+ bsg_free_command(bc);
+ } while (1);
+
+ return ret;
+}
+
+static int
+__bsg_read(char __user *buf, size_t count, struct bsg_device *bd,
+ const struct iovec *iov, ssize_t *bytes_read)
+{
+ struct bsg_command *bc;
+ int nr_commands, ret;
+
+ if (count % sizeof(struct sg_io_v4))
+ return -EINVAL;
+
+ ret = 0;
+ nr_commands = count / sizeof(struct sg_io_v4);
+ while (nr_commands) {
+ bc = bsg_get_done_cmd(bd);
+ if (IS_ERR(bc)) {
+ ret = PTR_ERR(bc);
+ break;
+ }
+
+ /*
+ * this is the only case where we need to copy data back
+ * after completing the request. so do that here,
+ * bsg_complete_work() cannot do that for us
+ */
+ ret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio,
+ bc->bidi_bio);
+
+ if (copy_to_user(buf, &bc->hdr, sizeof(bc->hdr)))
+ ret = -EFAULT;
+
+ bsg_free_command(bc);
+
+ if (ret)
+ break;
+
+ buf += sizeof(struct sg_io_v4);
+ *bytes_read += sizeof(struct sg_io_v4);
+ nr_commands--;
+ }
+
+ return ret;
+}
+
+static inline void bsg_set_block(struct bsg_device *bd, struct file *file)
+{
+ if (file->f_flags & O_NONBLOCK)
+ clear_bit(BSG_F_BLOCK, &bd->flags);
+ else
+ set_bit(BSG_F_BLOCK, &bd->flags);
+}
+
+static inline void bsg_set_write_perm(struct bsg_device *bd, struct file *file)
+{
+ if (file->f_mode & FMODE_WRITE)
+ set_bit(BSG_F_WRITE_PERM, &bd->flags);
+ else
+ clear_bit(BSG_F_WRITE_PERM, &bd->flags);
+}
+
+/*
+ * Check if the error is a "real" error that we should return.
+ */
+static inline int err_block_err(int ret)
+{
+ if (ret && ret != -ENOSPC && ret != -ENODATA && ret != -EAGAIN)
+ return 1;
+
+ return 0;
+}
+
+static ssize_t
+bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct bsg_device *bd = file->private_data;
+ int ret;
+ ssize_t bytes_read;
+
+ dprintk("%s: read %Zd bytes\n", bd->name, count);
+
+ bsg_set_block(bd, file);
+ bytes_read = 0;
+ ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
+ *ppos = bytes_read;
+
+ if (!bytes_read || (bytes_read && err_block_err(ret)))
+ bytes_read = ret;
+
+ return bytes_read;
+}
+
+static int __bsg_write(struct bsg_device *bd, const char __user *buf,
+ size_t count, ssize_t *bytes_written)
+{
+ struct bsg_command *bc;
+ struct request *rq;
+ int ret, nr_commands;
+
+ if (count % sizeof(struct sg_io_v4))
+ return -EINVAL;
+
+ nr_commands = count / sizeof(struct sg_io_v4);
+ rq = NULL;
+ bc = NULL;
+ ret = 0;
+ while (nr_commands) {
+ request_queue_t *q = bd->queue;
+
+ bc = bsg_alloc_command(bd);
+ if (IS_ERR(bc)) {
+ ret = PTR_ERR(bc);
+ bc = NULL;
+ break;
+ }
+
+ bc->uhdr = (struct sg_io_v4 __user *) buf;
+ if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ /*
+ * get a request, fill in the blanks, and add to request queue
+ */
+ rq = bsg_map_hdr(bd, &bc->hdr);
+ if (IS_ERR(rq)) {
+ ret = PTR_ERR(rq);
+ rq = NULL;
+ break;
+ }
+
+ bsg_add_command(bd, q, bc, rq);
+ bc = NULL;
+ rq = NULL;
+ nr_commands--;
+ buf += sizeof(struct sg_io_v4);
+ *bytes_written += sizeof(struct sg_io_v4);
+ }
+
+ if (bc)
+ bsg_free_command(bc);
+
+ return ret;
+}
+
+static ssize_t
+bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct bsg_device *bd = file->private_data;
+ ssize_t bytes_written;
+ int ret;
+
+ dprintk("%s: write %Zd bytes\n", bd->name, count);
+
+ bsg_set_block(bd, file);
+ bsg_set_write_perm(bd, file);
+
+ bytes_written = 0;
+ ret = __bsg_write(bd, buf, count, &bytes_written);
+ *ppos = bytes_written;
+
+ /*
+ * return bytes written on non-fatal errors
+ */
+ if (!bytes_written || (bytes_written && err_block_err(ret)))
+ bytes_written = ret;
+
+ dprintk("%s: returning %Zd\n", bd->name, bytes_written);
+ return bytes_written;
+}
+
+static struct bsg_device *bsg_alloc_device(void)
+{
+ struct bsg_device *bd;
+
+ bd = kzalloc(sizeof(struct bsg_device), GFP_KERNEL);
+ if (unlikely(!bd))
+ return NULL;
+
+ spin_lock_init(&bd->lock);
+
+ bd->max_queue = BSG_DEFAULT_CMDS;
+
+ INIT_LIST_HEAD(&bd->busy_list);
+ INIT_LIST_HEAD(&bd->done_list);
+ INIT_HLIST_NODE(&bd->dev_list);
+
+ init_waitqueue_head(&bd->wq_free);
+ init_waitqueue_head(&bd->wq_done);
+ return bd;
+}
+
+static int bsg_put_device(struct bsg_device *bd)
+{
+ int ret = 0;
+
+ mutex_lock(&bsg_mutex);
+
+ if (!atomic_dec_and_test(&bd->ref_count))
+ goto out;
+
+ dprintk("%s: tearing down\n", bd->name);
+
+ /*
+ * close can always block
+ */
+ set_bit(BSG_F_BLOCK, &bd->flags);
+
+ /*
+ * correct error detection baddies here again. it's the responsibility
+ * of the app to properly reap commands before close() if it wants
+ * fool-proof error detection
+ */
+ ret = bsg_complete_all_commands(bd);
+
+ blk_put_queue(bd->queue);
+ hlist_del(&bd->dev_list);
+ kfree(bd);
+out:
+ mutex_unlock(&bsg_mutex);
+ return ret;
+}
+
+static struct bsg_device *bsg_add_device(struct inode *inode,
+ struct request_queue *rq,
+ struct file *file)
+{
+ struct bsg_device *bd;
+#ifdef BSG_DEBUG
+ unsigned char buf[32];
+#endif
+
+ bd = bsg_alloc_device();
+ if (!bd)
+ return ERR_PTR(-ENOMEM);
+
+ bd->queue = rq;
+ kobject_get(&rq->kobj);
+ bsg_set_block(bd, file);
+
+ atomic_set(&bd->ref_count, 1);
+ bd->minor = iminor(inode);
+ mutex_lock(&bsg_mutex);
+ hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(bd->minor));
+
+ strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1);
+ dprintk("bound to <%s>, max queue %d\n",
+ format_dev_t(buf, inode->i_rdev), bd->max_queue);
+
+ mutex_unlock(&bsg_mutex);
+ return bd;
+}
+
+static struct bsg_device *__bsg_get_device(int minor)
+{
+ struct bsg_device *bd = NULL;
+ struct hlist_node *entry;
+
+ mutex_lock(&bsg_mutex);
+
+ hlist_for_each(entry, bsg_dev_idx_hash(minor)) {
+ bd = hlist_entry(entry, struct bsg_device, dev_list);
+ if (bd->minor == minor) {
+ atomic_inc(&bd->ref_count);
+ break;
+ }
+
+ bd = NULL;
+ }
+
+ mutex_unlock(&bsg_mutex);
+ return bd;
+}
+
+static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+{
+ struct bsg_device *bd = __bsg_get_device(iminor(inode));
+ struct bsg_class_device *bcd, *__bcd;
+
+ if (bd)
+ return bd;
+
+ /*
+ * find the class device
+ */
+ bcd = NULL;
+ mutex_lock(&bsg_mutex);
+ list_for_each_entry(__bcd, &bsg_class_list, list) {
+ if (__bcd->minor == iminor(inode)) {
+ bcd = __bcd;
+ break;
+ }
+ }
+ mutex_unlock(&bsg_mutex);
+
+ if (!bcd)
+ return ERR_PTR(-ENODEV);
+
+ return bsg_add_device(inode, bcd->queue, file);
+}
+
+static int bsg_open(struct inode *inode, struct file *file)
+{
+ struct bsg_device *bd = bsg_get_device(inode, file);
+
+ if (IS_ERR(bd))
+ return PTR_ERR(bd);
+
+ file->private_data = bd;
+ return 0;
+}
+
+static int bsg_release(struct inode *inode, struct file *file)
+{
+ struct bsg_device *bd = file->private_data;
+
+ file->private_data = NULL;
+ return bsg_put_device(bd);
+}
+
+static unsigned int bsg_poll(struct file *file, poll_table *wait)
+{
+ struct bsg_device *bd = file->private_data;
+ unsigned int mask = 0;
+
+ poll_wait(file, &bd->wq_done, wait);
+ poll_wait(file, &bd->wq_free, wait);
+
+ spin_lock_irq(&bd->lock);
+ if (!list_empty(&bd->done_list))
+ mask |= POLLIN | POLLRDNORM;
+ if (bd->queued_cmds >= bd->max_queue)
+ mask |= POLLOUT;
+ spin_unlock_irq(&bd->lock);
+
+ return mask;
+}
+
+static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct bsg_device *bd = file->private_data;
+ int __user *uarg = (int __user *) arg;
+
+ switch (cmd) {
+ /*
+ * our own ioctls
+ */
+ case SG_GET_COMMAND_Q:
+ return put_user(bd->max_queue, uarg);
+ case SG_SET_COMMAND_Q: {
+ int queue;
+
+ if (get_user(queue, uarg))
+ return -EFAULT;
+ if (queue < 1)
+ return -EINVAL;
+
+ spin_lock_irq(&bd->lock);
+ bd->max_queue = queue;
+ spin_unlock_irq(&bd->lock);
+ return 0;
+ }
+
+ /*
+ * SCSI/sg ioctls
+ */
+ case SG_GET_VERSION_NUM:
+ case SCSI_IOCTL_GET_IDLUN:
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ case SG_SET_TIMEOUT:
+ case SG_GET_TIMEOUT:
+ case SG_GET_RESERVED_SIZE:
+ case SG_SET_RESERVED_SIZE:
+ case SG_EMULATED_HOST:
+ case SCSI_IOCTL_SEND_COMMAND: {
+ void __user *uarg = (void __user *) arg;
+ return scsi_cmd_ioctl(file, bd->queue, NULL, cmd, uarg);
+ }
+ case SG_IO: {
+ struct request *rq;
+ struct bio *bio, *bidi_bio = NULL;
+ struct sg_io_v4 hdr;
+
+ if (copy_from_user(&hdr, uarg, sizeof(hdr)))
+ return -EFAULT;
+
+ rq = bsg_map_hdr(bd, &hdr);
+ if (IS_ERR(rq))
+ return PTR_ERR(rq);
+
+ bio = rq->bio;
+ if (rq->next_rq)
+ bidi_bio = rq->next_rq->bio;
+ blk_execute_rq(bd->queue, NULL, rq, 0);
+ blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);
+
+ if (copy_to_user(uarg, &hdr, sizeof(hdr)))
+ return -EFAULT;
+
+ return 0;
+ }
+ /*
+ * block device ioctls
+ */
+ default:
+#if 0
+ return ioctl_by_bdev(bd->bdev, cmd, arg);
+#else
+ return -ENOTTY;
+#endif
+ }
+}
+
+static struct file_operations bsg_fops = {
+ .read = bsg_read,
+ .write = bsg_write,
+ .poll = bsg_poll,
+ .open = bsg_open,
+ .release = bsg_release,
+ .unlocked_ioctl = bsg_ioctl,
+ .owner = THIS_MODULE,
+};
+
+void bsg_unregister_queue(struct request_queue *q)
+{
+ struct bsg_class_device *bcd = &q->bsg_dev;
+
+ WARN_ON(!bcd->class_dev);
+
+ mutex_lock(&bsg_mutex);
+ sysfs_remove_link(&q->kobj, "bsg");
+ class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor));
+ bcd->class_dev = NULL;
+ list_del_init(&bcd->list);
+ bsg_device_nr--;
+ mutex_unlock(&bsg_mutex);
+}
+EXPORT_SYMBOL_GPL(bsg_unregister_queue);
+
+int bsg_register_queue(struct request_queue *q, const char *name)
+{
+ struct bsg_class_device *bcd, *__bcd;
+ dev_t dev;
+ int ret = -EMFILE;
+ struct class_device *class_dev = NULL;
+
+ /*
+ * we need a proper transport to send commands, not a stacked device
+ */
+ if (!q->request_fn)
+ return 0;
+
+ bcd = &q->bsg_dev;
+ memset(bcd, 0, sizeof(*bcd));
+ INIT_LIST_HEAD(&bcd->list);
+
+ mutex_lock(&bsg_mutex);
+ if (bsg_device_nr == BSG_MAX_DEVS) {
+ printk(KERN_ERR "bsg: too many bsg devices\n");
+ goto err;
+ }
+
+retry:
+ list_for_each_entry(__bcd, &bsg_class_list, list) {
+ if (__bcd->minor == bsg_minor_idx) {
+ bsg_minor_idx++;
+ if (bsg_minor_idx == BSG_MAX_DEVS)
+ bsg_minor_idx = 0;
+ goto retry;
+ }
+ }
+
+ bcd->minor = bsg_minor_idx++;
+ if (bsg_minor_idx == BSG_MAX_DEVS)
+ bsg_minor_idx = 0;
+
+ bcd->queue = q;
+ dev = MKDEV(bsg_major, bcd->minor);
+ class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name);
+ if (IS_ERR(class_dev)) {
+ ret = PTR_ERR(class_dev);
+ goto err;
+ }
+ bcd->class_dev = class_dev;
+
+ if (q->kobj.sd) {
+ ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg");
+ if (ret)
+ goto err;
+ }
+
+ list_add_tail(&bcd->list, &bsg_class_list);
+ bsg_device_nr++;
+
+ mutex_unlock(&bsg_mutex);
+ return 0;
+err:
+ if (class_dev)
+ class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor));
+ mutex_unlock(&bsg_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(bsg_register_queue);
+
+static int bsg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+{
+ int ret;
+ struct scsi_device *sdp = to_scsi_device(cl_dev->dev);
+ struct request_queue *rq = sdp->request_queue;
+
+ if (rq->kobj.parent)
+ ret = bsg_register_queue(rq, kobject_name(rq->kobj.parent));
+ else
+ ret = bsg_register_queue(rq, kobject_name(&sdp->sdev_gendev.kobj));
+ return ret;
+}
+
+static void bsg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
+{
+ bsg_unregister_queue(to_scsi_device(cl_dev->dev)->request_queue);
+}
+
+static struct class_interface bsg_intf = {
+ .add = bsg_add,
+ .remove = bsg_remove,
+};
+
+static struct cdev bsg_cdev = {
+ .kobj = {.name = "bsg", },
+ .owner = THIS_MODULE,
+};
+
+static int __init bsg_init(void)
+{
+ int ret, i;
+ dev_t devid;
+
+ bsg_cmd_cachep = kmem_cache_create("bsg_cmd",
+ sizeof(struct bsg_command), 0, 0, NULL, NULL);
+ if (!bsg_cmd_cachep) {
+ printk(KERN_ERR "bsg: failed creating slab cache\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < BSG_LIST_ARRAY_SIZE; i++)
+ INIT_HLIST_HEAD(&bsg_device_list[i]);
+
+ bsg_class = class_create(THIS_MODULE, "bsg");
+ if (IS_ERR(bsg_class)) {
+ ret = PTR_ERR(bsg_class);
+ goto destroy_kmemcache;
+ }
+
+ ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
+ if (ret)
+ goto destroy_bsg_class;
+
+ bsg_major = MAJOR(devid);
+
+ cdev_init(&bsg_cdev, &bsg_fops);
+ ret = cdev_add(&bsg_cdev, MKDEV(bsg_major, 0), BSG_MAX_DEVS);
+ if (ret)
+ goto unregister_chrdev;
+
+ ret = scsi_register_interface(&bsg_intf);
+ if (ret)
+ goto remove_cdev;
+
+ printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
+ " loaded (major %d)\n", bsg_major);
+ return 0;
+remove_cdev:
+ printk(KERN_ERR "bsg: failed register scsi interface %d\n", ret);
+ cdev_del(&bsg_cdev);
+unregister_chrdev:
+ unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS);
+destroy_bsg_class:
+ class_destroy(bsg_class);
+destroy_kmemcache:
+ kmem_cache_destroy(bsg_cmd_cachep);
+ return ret;
+}
+
+MODULE_AUTHOR("Jens Axboe");
+MODULE_DESCRIPTION(BSG_DESCRIPTION);
+MODULE_LICENSE("GPL");
+
+device_initcall(bsg_init);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index e0aa4dad6742..9755a3cfad26 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1251,9 +1251,9 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct cfq_io_context *cic;
- cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask, cfqd->queue->node);
+ cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
+ cfqd->queue->node);
if (cic) {
- memset(cic, 0, sizeof(*cic));
cic->last_end_request = jiffies;
INIT_LIST_HEAD(&cic->queue_list);
cic->dtor = cfq_free_io_context;
@@ -1376,17 +1376,19 @@ retry:
* free memory.
*/
spin_unlock_irq(cfqd->queue->queue_lock);
- new_cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask|__GFP_NOFAIL, cfqd->queue->node);
+ new_cfqq = kmem_cache_alloc_node(cfq_pool,
+ gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
+ cfqd->queue->node);
spin_lock_irq(cfqd->queue->queue_lock);
goto retry;
} else {
- cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask, cfqd->queue->node);
+ cfqq = kmem_cache_alloc_node(cfq_pool,
+ gfp_mask | __GFP_ZERO,
+ cfqd->queue->node);
if (!cfqq)
goto out;
}
- memset(cfqq, 0, sizeof(*cfqq));
-
RB_CLEAR_NODE(&cfqq->rb_node);
INIT_LIST_HEAD(&cfqq->fifo);
@@ -2079,12 +2081,10 @@ static void *cfq_init_queue(request_queue_t *q)
{
struct cfq_data *cfqd;
- cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node);
+ cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
if (!cfqd)
return NULL;
- memset(cfqd, 0, sizeof(*cfqd));
-
cfqd->service_tree = CFQ_RB_ROOT;
INIT_LIST_HEAD(&cfqd->cic_list);
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 6d673e938d3e..87ca02ac84cb 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -360,10 +360,9 @@ static void *deadline_init_queue(request_queue_t *q)
{
struct deadline_data *dd;
- dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
+ dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node);
if (!dd)
return NULL;
- memset(dd, 0, sizeof(*dd));
INIT_LIST_HEAD(&dd->fifo_list[READ]);
INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
diff --git a/block/elevator.c b/block/elevator.c
index 4769a25d7037..d265963d1ed3 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -177,11 +177,10 @@ static elevator_t *elevator_alloc(request_queue_t *q, struct elevator_type *e)
elevator_t *eq;
int i;
- eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL, q->node);
+ eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL | __GFP_ZERO, q->node);
if (unlikely(!eq))
goto err;
- memset(eq, 0, sizeof(*eq));
eq->ops = &e->ops;
eq->elevator_type = e;
kobject_init(&eq->kobj);
diff --git a/block/genhd.c b/block/genhd.c
index 863a8c0623ed..3af1e7a378d4 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -108,28 +108,24 @@ out:
EXPORT_SYMBOL(register_blkdev);
-/* todo: make void - error printk here */
-int unregister_blkdev(unsigned int major, const char *name)
+void unregister_blkdev(unsigned int major, const char *name)
{
struct blk_major_name **n;
struct blk_major_name *p = NULL;
int index = major_to_index(major);
- int ret = 0;
mutex_lock(&block_subsys_lock);
for (n = &major_names[index]; *n; n = &(*n)->next)
if ((*n)->major == major)
break;
- if (!*n || strcmp((*n)->name, name))
- ret = -EINVAL;
- else {
+ if (!*n || strcmp((*n)->name, name)) {
+ WARN_ON(1);
+ } else {
p = *n;
*n = p->next;
}
mutex_unlock(&block_subsys_lock);
kfree(p);
-
- return ret;
}
EXPORT_SYMBOL(unregister_blkdev);
@@ -726,21 +722,21 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
{
struct gendisk *disk;
- disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
+ disk = kmalloc_node(sizeof(struct gendisk),
+ GFP_KERNEL | __GFP_ZERO, node_id);
if (disk) {
- memset(disk, 0, sizeof(struct gendisk));
if (!init_disk_stats(disk)) {
kfree(disk);
return NULL;
}
if (minors > 1) {
int size = (minors - 1) * sizeof(struct hd_struct *);
- disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
+ disk->part = kmalloc_node(size,
+ GFP_KERNEL | __GFP_ZERO, node_id);
if (!disk->part) {
kfree(disk);
return NULL;
}
- memset(disk->part, 0, size);
}
disk->minors = minors;
kobj_set_kset_s(disk,block_subsys);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index ef42bb2b12b6..d7cadf304168 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -256,6 +256,7 @@ static void rq_init(request_queue_t *q, struct request *rq)
rq->end_io = NULL;
rq->end_io_data = NULL;
rq->completion_data = NULL;
+ rq->next_rq = NULL;
}
/**
@@ -1828,11 +1829,11 @@ request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
{
request_queue_t *q;
- q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
+ q = kmem_cache_alloc_node(requestq_cachep,
+ gfp_mask | __GFP_ZERO, node_id);
if (!q)
return NULL;
- memset(q, 0, sizeof(*q));
init_timer(&q->unplug_timer);
snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index e83f1dbf7c29..a26ba07955fe 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -41,8 +41,6 @@ const unsigned char scsi_command_size[8] =
EXPORT_SYMBOL(scsi_command_size);
-#define BLK_DEFAULT_TIMEOUT (60 * HZ)
-
#include <scsi/sg.h>
static int sg_get_version(int __user *p)
@@ -114,7 +112,7 @@ static int sg_emulated_host(request_queue_t *q, int __user *p)
#define safe_for_read(cmd) [cmd] = CMD_READ_SAFE
#define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE
-static int verify_command(struct file *file, unsigned char *cmd)
+int blk_verify_command(unsigned char *cmd, int has_write_perm)
{
static unsigned char cmd_type[256] = {
@@ -193,18 +191,11 @@ static int verify_command(struct file *file, unsigned char *cmd)
safe_for_write(GPCMD_SET_STREAMING),
};
unsigned char type = cmd_type[cmd[0]];
- int has_write_perm = 0;
/* Anybody who can open the device can do a read-safe command */
if (type & CMD_READ_SAFE)
return 0;
- /*
- * file can be NULL from ioctl_by_bdev()...
- */
- if (file)
- has_write_perm = file->f_mode & FMODE_WRITE;
-
/* Write-safe commands just require a writable open.. */
if ((type & CMD_WRITE_SAFE) && has_write_perm)
return 0;
@@ -221,25 +212,96 @@ static int verify_command(struct file *file, unsigned char *cmd)
/* Otherwise fail it with an "Operation not permitted" */
return -EPERM;
}
+EXPORT_SYMBOL_GPL(blk_verify_command);
+
+int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
+ struct sg_io_hdr *hdr, int has_write_perm)
+{
+ memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+
+ if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
+ return -EFAULT;
+ if (blk_verify_command(rq->cmd, has_write_perm))
+ return -EPERM;
+
+ /*
+ * fill in request structure
+ */
+ rq->cmd_len = hdr->cmd_len;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+ rq->timeout = (hdr->timeout * HZ) / 1000;
+ if (!rq->timeout)
+ rq->timeout = q->sg_timeout;
+ if (!rq->timeout)
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
+
+/*
+ * unmap a request that was previously mapped to this sg_io_hdr. handles
+ * both sg and non-sg sg_io_hdr.
+ */
+int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
+{
+ blk_rq_unmap_user(rq->bio);
+ blk_put_request(rq);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq);
+
+int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
+ struct bio *bio)
+{
+ int r, ret = 0;
+
+ /*
+ * fill in all the output members
+ */
+ hdr->status = rq->errors & 0xff;
+ hdr->masked_status = status_byte(rq->errors);
+ hdr->msg_status = msg_byte(rq->errors);
+ hdr->host_status = host_byte(rq->errors);
+ hdr->driver_status = driver_byte(rq->errors);
+ hdr->info = 0;
+ if (hdr->masked_status || hdr->host_status || hdr->driver_status)
+ hdr->info |= SG_INFO_CHECK;
+ hdr->resid = rq->data_len;
+ hdr->sb_len_wr = 0;
+
+ if (rq->sense_len && hdr->sbp) {
+ int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
+
+ if (!copy_to_user(hdr->sbp, rq->sense, len))
+ hdr->sb_len_wr = len;
+ else
+ ret = -EFAULT;
+ }
+
+ rq->bio = bio;
+ r = blk_unmap_sghdr_rq(rq, hdr);
+ if (ret)
+ r = ret;
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq);
static int sg_io(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
{
- unsigned long start_time, timeout;
- int writing = 0, ret = 0;
+ unsigned long start_time;
+ int writing = 0, ret = 0, has_write_perm = 0;
struct request *rq;
char sense[SCSI_SENSE_BUFFERSIZE];
- unsigned char cmd[BLK_MAX_CDB];
struct bio *bio;
if (hdr->interface_id != 'S')
return -EINVAL;
if (hdr->cmd_len > BLK_MAX_CDB)
return -EINVAL;
- if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
- return -EFAULT;
- if (verify_command(file, cmd))
- return -EPERM;
if (hdr->dxfer_len > (q->max_hw_sectors << 9))
return -EIO;
@@ -260,25 +322,13 @@ static int sg_io(struct file *file, request_queue_t *q,
if (!rq)
return -ENOMEM;
- /*
- * fill in request structure
- */
- rq->cmd_len = hdr->cmd_len;
- memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
- memcpy(rq->cmd, cmd, hdr->cmd_len);
-
- memset(sense, 0, sizeof(sense));
- rq->sense = sense;
- rq->sense_len = 0;
-
- rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ if (file)
+ has_write_perm = file->f_mode & FMODE_WRITE;
- timeout = msecs_to_jiffies(hdr->timeout);
- rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
- if (!rq->timeout)
- rq->timeout = q->sg_timeout;
- if (!rq->timeout)
- rq->timeout = BLK_DEFAULT_TIMEOUT;
+ if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) {
+ blk_put_request(rq);
+ return -EFAULT;
+ }
if (hdr->iovec_count) {
const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
@@ -306,6 +356,9 @@ static int sg_io(struct file *file, request_queue_t *q,
goto out;
bio = rq->bio;
+ memset(sense, 0, sizeof(sense));
+ rq->sense = sense;
+ rq->sense_len = 0;
rq->retries = 0;
start_time = jiffies;
@@ -316,31 +369,9 @@ static int sg_io(struct file *file, request_queue_t *q,
*/
blk_execute_rq(q, bd_disk, rq, 0);
- /* write to all output members */
- hdr->status = 0xff & rq->errors;
- hdr->masked_status = status_byte(rq->errors);
- hdr->msg_status = msg_byte(rq->errors);
- hdr->host_status = host_byte(rq->errors);
- hdr->driver_status = driver_byte(rq->errors);
- hdr->info = 0;
- if (hdr->masked_status || hdr->host_status || hdr->driver_status)
- hdr->info |= SG_INFO_CHECK;
- hdr->resid = rq->data_len;
hdr->duration = ((jiffies - start_time) * 1000) / HZ;
- hdr->sb_len_wr = 0;
-
- if (rq->sense_len && hdr->sbp) {
- int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
-
- if (!copy_to_user(hdr->sbp, rq->sense, len))
- hdr->sb_len_wr = len;
- }
- if (blk_rq_unmap_user(bio))
- ret = -EFAULT;
-
- /* may not have succeeded, but output values written to control
- * structure (struct sg_io_hdr). */
+ return blk_complete_sghdr_rq(rq, hdr, bio);
out:
blk_put_request(rq);
return ret;
@@ -427,7 +458,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
goto error;
- err = verify_command(file, rq->cmd);
+ err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE);
if (err)
goto error;
@@ -454,7 +485,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
rq->retries = 1;
break;
default:
- rq->timeout = BLK_DEFAULT_TIMEOUT;
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
break;
}
@@ -501,7 +532,7 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->data = NULL;
rq->data_len = 0;
- rq->timeout = BLK_DEFAULT_TIMEOUT;
+ rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
memset(rq->cmd, 0, sizeof(rq->cmd));
rq->cmd[0] = cmd;
rq->cmd[4] = data;
@@ -517,16 +548,12 @@ static inline int blk_send_start_stop(request_queue_t *q, struct gendisk *bd_dis
return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
}
-int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
+int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
+ struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
{
- request_queue_t *q;
int err;
- q = bd_disk->queue;
- if (!q)
- return -ENXIO;
-
- if (blk_get_queue(q))
+ if (!q || blk_get_queue(q))
return -ENXIO;
switch (cmd) {
diff --git a/crypto/proc.c b/crypto/proc.c
index 102c751a124c..3d73323ff79b 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -23,24 +23,13 @@
static void *c_start(struct seq_file *m, loff_t *pos)
{
- struct list_head *v;
- loff_t n = *pos;
-
down_read(&crypto_alg_sem);
- list_for_each(v, &crypto_alg_list)
- if (!n--)
- return list_entry(v, struct crypto_alg, cra_list);
- return NULL;
+ return seq_list_start(&crypto_alg_list, *pos);
}
static void *c_next(struct seq_file *m, void *p, loff_t *pos)
{
- struct list_head *v = p;
-
- (*pos)++;
- v = v->next;
- return (v == &crypto_alg_list) ?
- NULL : list_entry(v, struct crypto_alg, cra_list);
+ return seq_list_next(p, &crypto_alg_list, pos);
}
static void c_stop(struct seq_file *m, void *p)
@@ -50,7 +39,7 @@ static void c_stop(struct seq_file *m, void *p)
static int c_show(struct seq_file *m, void *p)
{
- struct crypto_alg *alg = (struct crypto_alg *)p;
+ struct crypto_alg *alg = list_entry(p, struct crypto_alg, cra_list);
seq_printf(m, "name : %s\n", alg->cra_name);
seq_printf(m, "driver : %s\n", alg->cra_driver_name);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 5d576435fccc..fb8a749423ca 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -2666,7 +2666,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
mv_print_info(host);
pci_set_master(pdev);
- pci_set_mwi(pdev);
+ pci_try_set_mwi(pdev);
return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
}
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index 5b4fab24155f..bb4ae6281491 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -142,7 +142,7 @@ config ATM_ENI_BURST_RX_2W
config ATM_FIRESTREAM
tristate "Fujitsu FireStream (FS50/FS155) "
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
Driver for the Fujitsu FireStream 155 (MB86697) and
FireStream 50 (MB86695) ATM PCI chips.
@@ -152,7 +152,7 @@ config ATM_FIRESTREAM
config ATM_ZATM
tristate "ZeitNet ZN1221/ZN1225"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM
adapters.
@@ -240,7 +240,7 @@ config ATM_IDT77252_USE_SUNI
config ATM_AMBASSADOR
tristate "Madge Ambassador (Collage PCI 155 Server)"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
select BITREVERSE
help
This is a driver for ATMizer based ATM card produced by Madge
@@ -265,7 +265,7 @@ config ATM_AMBASSADOR_DEBUG
config ATM_HORIZON
tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
This is a driver for the Horizon chipset ATM adapter cards once
produced by Madge Networks Ltd. Say Y (or M to compile as a module
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 59651abfa4f8..b34b3829f6a9 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1040,7 +1040,7 @@ static int amb_open (struct atm_vcc * atm_vcc)
struct atm_qos * qos;
struct atm_trafprm * txtp;
struct atm_trafprm * rxtp;
- u16 tx_rate_bits;
+ u16 tx_rate_bits = -1; // hush gcc
u16 tx_vc_bits = -1; // hush gcc
u16 tx_frame_bits = -1; // hush gcc
@@ -1096,6 +1096,8 @@ static int amb_open (struct atm_vcc * atm_vcc)
r = round_up;
}
error = make_rate (pcr, r, &tx_rate_bits, NULL);
+ if (error)
+ return error;
tx_vc_bits = TX_UBR_CAPPED;
tx_frame_bits = TX_FRAME_CAPPED;
}
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 020a87a476c8..58583c6ac5be 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -915,7 +915,7 @@ static int open_tx_first(struct atm_vcc *vcc)
unsigned long flags;
u32 *loop;
unsigned short chan;
- int pcr,unlimited;
+ int unlimited;
DPRINTK("open_tx_first\n");
zatm_dev = ZATM_DEV(vcc->dev);
@@ -936,6 +936,8 @@ static int open_tx_first(struct atm_vcc *vcc)
vcc->qos.txtp.max_pcr >= ATM_OC3_PCR);
if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr;
else {
+ int uninitialized_var(pcr);
+
if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU;
if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr,
vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,unlimited))
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index ea4fe3e48f33..de2fcce10ba5 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -5,8 +5,11 @@
# Auxiliary display drivers configuration.
#
-menu "Auxiliary Display support"
+menuconfig AUXDISPLAY
depends on PARPORT
+ bool "Auxiliary Display support"
+
+if AUXDISPLAY && PARPORT
config KS0108
tristate "KS0108 LCD Controller"
@@ -111,4 +114,5 @@ config CFAG12864B_RATE
If you compile this as a module, you can still override this
value using the module parameters.
-endmenu
+
+endif # AUXDISPLAY
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 91970e9bb05e..7647abfe1890 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -127,7 +127,7 @@ dma_pool_create (const char *name, struct device *dev,
} else if (allocation < size)
return NULL;
- if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL)))
+ if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev))))
return retval;
strlcpy (retval->name, name, sizeof retval->name);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 6e23af1ecbdb..8f65b88cf711 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -59,17 +59,6 @@ config AMIGA_Z2RAM
To compile this driver as a module, choose M here: the
module will be called z2ram.
-config ATARI_SLM
- tristate "Atari SLM laser printer support"
- depends on ATARI
- help
- If you have an Atari SLM laser printer, say Y to include support for
- it in the kernel. Otherwise, say N. This driver is also available as
- a module ( = code which can be inserted in and removed from the
- running kernel whenever you want). The module will be called
- acsi_slm. Be warned: the driver needs much ST-RAM and can cause
- problems due to that fact!
-
config BLK_DEV_XD
tristate "XT hard disk support"
depends on ISA && ISA_DMA_API
@@ -113,7 +102,7 @@ source "drivers/block/paride/Kconfig"
config BLK_CPQ_DA
tristate "Compaq SMART2 support"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
This is the driver for Compaq Smart Array controllers. Everyone
using these boards should say Y here. See the file
@@ -423,6 +412,19 @@ config ATA_OVER_ETH
This driver provides Support for ATA over Ethernet block
devices like the Coraid EtherDrive (R) Storage Blade.
+config SUNVDC
+ tristate "Sun Virtual Disk Client support"
+ depends on SUN_LDOMS
+ help
+ Support for virtual disk devices as a client under Sun
+ Logical Domains.
+
source "drivers/s390/block/Kconfig"
+config XILINX_SYSACE
+ tristate "Xilinx SystemACE support"
+ depends on 4xx
+ help
+ Include support for the Xilinx SystemACE CompactFlash interface
+
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index e5f98acc5d52..9ee08ab4ffa8 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
-obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_BLK_DEV_RAM) += rd.o
obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
@@ -18,7 +17,9 @@ obj-$(CONFIG_BLK_DEV_XD) += xd.o
obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
+obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
+obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
deleted file mode 100644
index 1d9d9b4f48cc..000000000000
--- a/drivers/block/acsi_slm.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * acsi_slm.c -- Device driver for the Atari SLM laser printer
- *
- * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * 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.
- *
- */
-
-/*
-
-Notes:
-
-The major number for SLM printers is 28 (like ACSI), but as a character
-device, not block device. The minor number is the number of the printer (if
-you have more than one SLM; currently max. 2 (#define-constant) SLMs are
-supported). The device can be opened for reading and writing. If reading it,
-you get some status infos (MODE SENSE data). Writing mode is used for the data
-to be printed. Some ioctls allow to get the printer status and to tune printer
-modes and some internal variables.
-
-A special problem of the SLM driver is the timing and thus the buffering of
-the print data. The problem is that all the data for one page must be present
-in memory when printing starts, else --when swapping occurs-- the timing could
-not be guaranteed. There are several ways to assure this:
-
- 1) Reserve a buffer of 1196k (maximum page size) statically by
- atari_stram_alloc(). The data are collected there until they're complete,
- and then printing starts. Since the buffer is reserved, no further
- considerations about memory and swapping are needed. So this is the
- simplest method, but it needs a lot of memory for just the SLM.
-
- An striking advantage of this method is (supposed the SLM_CONT_CNT_REPROG
- method works, see there), that there are no timing problems with the DMA
- anymore.
-
- 2) The other method would be to reserve the buffer dynamically each time
- printing is required. I could think of looking at mem_map where the
- largest unallocted ST-RAM area is, taking the area, and then extending it
- by swapping out the neighbored pages, until the needed size is reached.
- This requires some mm hacking, but seems possible. The only obstacle could
- be pages that cannot be swapped out (reserved pages)...
-
- 3) Another possibility would be to leave the real data in user space and to
- work with two dribble buffers of about 32k in the driver: While the one
- buffer is DMAed to the SLM, the other can be filled with new data. But
- to keep the timing, that requires that the user data remain in memory and
- are not swapped out. Requires mm hacking, too, but maybe not so bad as
- method 2).
-
-*/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-#include <asm/atari_SLM.h>
-
-
-#undef DEBUG
-
-/* Define this if the page data are continuous in physical memory. That
- * requires less reprogramming of the ST-DMA */
-#define SLM_CONTINUOUS_DMA
-
-/* Use continuous reprogramming of the ST-DMA counter register. This is
- * --strictly speaking-- not allowed, Atari recommends not to look at the
- * counter register while a DMA is going on. But I don't know if that applies
- * only for reading the register, or also writing to it. Writing only works
- * fine for me... The advantage is that the timing becomes absolutely
- * uncritical: Just update each, say 200ms, the counter reg to its maximum,
- * and the DMA will work until the status byte interrupt occurs.
- */
-#define SLM_CONT_CNT_REPROG
-
-#define CMDSET_TARG_LUN(cmd,targ,lun) \
- do { \
- cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \
- cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \
- } while(0)
-
-#define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to))
-#define STOP_TIMER() del_timer(&slm_timer)
-
-
-static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
-static char slmprint_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 };
-static char slminquiry_cmd[6] = { 0x12, 0, 0, 0, 0, 0x80 };
-static char slmmsense_cmd[6] = { 0x1a, 0, 0, 0, 255, 0 };
-#if 0
-static char slmmselect_cmd[6] = { 0x15, 0, 0, 0, 0, 0 };
-#endif
-
-
-#define MAX_SLM 2
-
-static struct slm {
- unsigned target; /* target number */
- unsigned lun; /* LUN in target controller */
- atomic_t wr_ok; /* set to 0 if output part busy */
- atomic_t rd_ok; /* set to 0 if status part busy */
-} slm_info[MAX_SLM];
-
-int N_SLM_Printers = 0;
-
-/* printer buffer */
-static unsigned char *SLMBuffer; /* start of buffer */
-static unsigned char *BufferP; /* current position in buffer */
-static int BufferSize; /* length of buffer for page size */
-
-typedef enum { IDLE, FILLING, PRINTING } SLMSTATE;
-static SLMSTATE SLMState;
-static int SLMBufOwner; /* SLM# currently using the buffer */
-
-/* DMA variables */
-#ifndef SLM_CONT_CNT_REPROG
-static unsigned long SLMCurAddr; /* current base addr of DMA chunk */
-static unsigned long SLMEndAddr; /* expected end addr */
-static unsigned long SLMSliceSize; /* size of one DMA chunk */
-#endif
-static int SLMError;
-
-/* wait queues */
-static DECLARE_WAIT_QUEUE_HEAD(slm_wait); /* waiting for buffer */
-static DECLARE_WAIT_QUEUE_HEAD(print_wait); /* waiting for printing finished */
-
-/* status codes */
-#define SLMSTAT_OK 0x00
-#define SLMSTAT_ORNERY 0x02
-#define SLMSTAT_TONER 0x03
-#define SLMSTAT_WARMUP 0x04
-#define SLMSTAT_PAPER 0x05
-#define SLMSTAT_DRUM 0x06
-#define SLMSTAT_INJAM 0x07
-#define SLMSTAT_THRJAM 0x08
-#define SLMSTAT_OUTJAM 0x09
-#define SLMSTAT_COVER 0x0a
-#define SLMSTAT_FUSER 0x0b
-#define SLMSTAT_IMAGER 0x0c
-#define SLMSTAT_MOTOR 0x0d
-#define SLMSTAT_VIDEO 0x0e
-#define SLMSTAT_SYSTO 0x10
-#define SLMSTAT_OPCODE 0x12
-#define SLMSTAT_DEVNUM 0x15
-#define SLMSTAT_PARAM 0x1a
-#define SLMSTAT_ACSITO 0x1b /* driver defined */
-#define SLMSTAT_NOTALL 0x1c /* driver defined */
-
-static char *SLMErrors[] = {
- /* 0x00 */ "OK and ready",
- /* 0x01 */ NULL,
- /* 0x02 */ "ornery printer",
- /* 0x03 */ "toner empty",
- /* 0x04 */ "warming up",
- /* 0x05 */ "paper empty",
- /* 0x06 */ "drum empty",
- /* 0x07 */ "input jam",
- /* 0x08 */ "through jam",
- /* 0x09 */ "output jam",
- /* 0x0a */ "cover open",
- /* 0x0b */ "fuser malfunction",
- /* 0x0c */ "imager malfunction",
- /* 0x0d */ "motor malfunction",
- /* 0x0e */ "video malfunction",
- /* 0x0f */ NULL,
- /* 0x10 */ "printer system timeout",
- /* 0x11 */ NULL,
- /* 0x12 */ "invalid operation code",
- /* 0x13 */ NULL,
- /* 0x14 */ NULL,
- /* 0x15 */ "invalid device number",
- /* 0x16 */ NULL,
- /* 0x17 */ NULL,
- /* 0x18 */ NULL,
- /* 0x19 */ NULL,
- /* 0x1a */ "invalid parameter list",
- /* 0x1b */ "ACSI timeout",
- /* 0x1c */ "not all printed"
-};
-
-#define N_ERRORS (sizeof(SLMErrors)/sizeof(*SLMErrors))
-
-/* real (driver caused) error? */
-#define IS_REAL_ERROR(x) (x > 0x10)
-
-
-static struct {
- char *name;
- int w, h;
-} StdPageSize[] = {
- { "Letter", 2400, 3180 },
- { "Legal", 2400, 4080 },
- { "A4", 2336, 3386 },
- { "B5", 2016, 2914 }
-};
-
-#define N_STD_SIZES (sizeof(StdPageSize)/sizeof(*StdPageSize))
-
-#define SLM_BUFFER_SIZE (2336*3386/8) /* A4 for now */
-#define SLM_DMA_AMOUNT 255 /* #sectors to program the DMA for */
-
-#ifdef SLM_CONTINUOUS_DMA
-# define SLM_DMA_INT_OFFSET 0 /* DMA goes until seccnt 0, no offs */
-# define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */
-# define SLM_SLICE_SIZE(w) (255*512)
-#else
-# define SLM_DMA_INT_OFFSET 32 /* 32 Byte ST-DMA FIFO */
-# define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */
-# define SLM_SLICE_SIZE(w) ((254*512)/(w/8)*(w/8))
-#endif
-
-/* calculate the number of jiffies to wait for 'n' bytes */
-#ifdef SLM_CONT_CNT_REPROG
-#define DMA_TIME_FOR(n) 50
-#define DMA_STARTUP_TIME 0
-#else
-#define DMA_TIME_FOR(n) (n/1400-1)
-#define DMA_STARTUP_TIME 650
-#endif
-
-/***************************** Prototypes *****************************/
-
-static char *slm_errstr( int stat );
-static int slm_getstats( char *buffer, int device );
-static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
- *ppos );
-static void start_print( int device );
-static irqreturn_t slm_interrupt(int irc, void *data);
-static void slm_test_ready( unsigned long dummy );
-static void set_dma_addr( unsigned long paddr );
-static unsigned long get_dma_addr( void );
-static ssize_t slm_write( struct file *file, const char *buf, size_t count,
- loff_t *ppos );
-static int slm_ioctl( struct inode *inode, struct file *file, unsigned int
- cmd, unsigned long arg );
-static int slm_open( struct inode *inode, struct file *file );
-static int slm_release( struct inode *inode, struct file *file );
-static int slm_req_sense( int device );
-static int slm_mode_sense( int device, char *buffer, int abs_flag );
-#if 0
-static int slm_mode_select( int device, char *buffer, int len, int
- default_flag );
-#endif
-static int slm_get_pagesize( int device, int *w, int *h );
-
-/************************* End of Prototypes **************************/
-
-
-static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
-
-static const struct file_operations slm_fops = {
- .owner = THIS_MODULE,
- .read = slm_read,
- .write = slm_write,
- .ioctl = slm_ioctl,
- .open = slm_open,
- .release = slm_release,
-};
-
-
-/* ---------------------------------------------------------------------- */
-/* Status Functions */
-
-
-static char *slm_errstr( int stat )
-
-{ char *p;
- static char str[22];
-
- stat &= 0x1f;
- if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat]))
- return( p );
- sprintf( str, "unknown status 0x%02x", stat );
- return( str );
-}
-
-
-static int slm_getstats( char *buffer, int device )
-
-{ int len = 0, stat, i, w, h;
- unsigned char buf[256];
-
- stat = slm_mode_sense( device, buf, 0 );
- if (IS_REAL_ERROR(stat))
- return( -EIO );
-
-#define SHORTDATA(i) ((buf[i] << 8) | buf[i+1])
-#define BOOLDATA(i,mask) ((buf[i] & mask) ? "on" : "off")
-
- w = SHORTDATA( 3 );
- h = SHORTDATA( 1 );
-
- len += sprintf( buffer+len, "Status\t\t%s\n",
- slm_errstr( stat ) );
- len += sprintf( buffer+len, "Page Size\t%dx%d",
- w, h );
-
- for( i = 0; i < N_STD_SIZES; ++i ) {
- if (w == StdPageSize[i].w && h == StdPageSize[i].h)
- break;
- }
- if (i < N_STD_SIZES)
- len += sprintf( buffer+len, " (%s)", StdPageSize[i].name );
- buffer[len++] = '\n';
-
- len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n",
- SHORTDATA( 5 ), SHORTDATA( 7 ) );
- len += sprintf( buffer+len, "Manual Feed\t%s\n",
- BOOLDATA( 9, 0x01 ) );
- len += sprintf( buffer+len, "Input Select\t%d\n",
- (buf[9] >> 1) & 7 );
- len += sprintf( buffer+len, "Auto Select\t%s\n",
- BOOLDATA( 9, 0x10 ) );
- len += sprintf( buffer+len, "Prefeed Paper\t%s\n",
- BOOLDATA( 9, 0x20 ) );
- len += sprintf( buffer+len, "Thick Pixels\t%s\n",
- BOOLDATA( 9, 0x40 ) );
- len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n",
- SHORTDATA( 12 ), SHORTDATA( 10 ) );
- len += sprintf( buffer+len, "System Timeout\t%d\n",
- buf[14] );
- len += sprintf( buffer+len, "Scan Time\t%d\n",
- SHORTDATA( 15 ) );
- len += sprintf( buffer+len, "Page Count\t%d\n",
- SHORTDATA( 17 ) );
- len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n",
- SHORTDATA( 19 ), SHORTDATA( 21 ) );
- len += sprintf( buffer+len, "Stagger Output\t%s\n",
- BOOLDATA( 23, 0x01 ) );
- len += sprintf( buffer+len, "Output Select\t%d\n",
- (buf[23] >> 1) & 7 );
- len += sprintf( buffer+len, "Duplex Print\t%s\n",
- BOOLDATA( 23, 0x10 ) );
- len += sprintf( buffer+len, "Color Sep.\t%s\n",
- BOOLDATA( 23, 0x20 ) );
-
- return( len );
-}
-
-
-static ssize_t slm_read( struct file *file, char *buf, size_t count,
- loff_t *ppos )
-
-{
- struct inode *node = file->f_path.dentry->d_inode;
- unsigned long page;
- int length;
- int end;
-
- if (!(page = __get_free_page( GFP_KERNEL )))
- return( -ENOMEM );
-
- length = slm_getstats( (char *)page, iminor(node) );
- if (length < 0) {
- count = length;
- goto out;
- }
- if (file->f_pos >= length) {
- count = 0;
- goto out;
- }
- if (count + file->f_pos > length)
- count = length - file->f_pos;
- end = count + file->f_pos;
- if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
- count = -EFAULT;
- goto out;
- }
- file->f_pos = end;
-out: free_page( page );
- return( count );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/* Printing */
-
-
-static void start_print( int device )
-
-{ struct slm *sip = &slm_info[device];
- unsigned char *cmd;
- unsigned long paddr;
- int i;
-
- stdma_lock( slm_interrupt, NULL );
-
- CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
- cmd = slmprint_cmd;
- paddr = virt_to_phys( SLMBuffer );
- dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
- DISABLE_IRQ();
-
- /* Low on A1 */
- dma_wd.dma_mode_status = 0x88;
- MFPDELAY();
-
- /* send the command bytes except the last */
- for( i = 0; i < 5; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) {
- SLMError = 1;
- return; /* timeout */
- }
- }
- /* last command byte */
- DMA_LONG_WRITE( *cmd++, 0x82 );
- MFPDELAY();
- /* set DMA address */
- set_dma_addr( paddr );
- /* program DMA for write and select sector counter reg */
- dma_wd.dma_mode_status = 0x192;
- MFPDELAY();
- /* program for 255*512 bytes and start DMA */
- DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
-
-#ifndef SLM_CONT_CNT_REPROG
- SLMCurAddr = paddr;
- SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
-#endif
- START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize ));
-#if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG)
- printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
- SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
-#endif
-
- ENABLE_IRQ();
-}
-
-
-/* Only called when an error happened or at the end of a page */
-
-static irqreturn_t slm_interrupt(int irc, void *data)
-
-{ unsigned long addr;
- int stat;
-
- STOP_TIMER();
- addr = get_dma_addr();
- stat = acsi_getstatus();
- SLMError = (stat < 0) ? SLMSTAT_ACSITO :
- (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
- stat;
-
- dma_wd.dma_mode_status = 0x80;
- MFPDELAY();
-#ifdef DEBUG
- printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError );
-#endif
-
- wake_up( &print_wait );
- stdma_release();
- ENABLE_IRQ();
- return IRQ_HANDLED;
-}
-
-
-static void slm_test_ready( unsigned long dummy )
-
-{
-#ifdef SLM_CONT_CNT_REPROG
- /* program for 255*512 bytes again */
- dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
- START_TIMER( DMA_TIME_FOR(0) );
-#ifdef DEBUG
- printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n",
- DMA_TIME_FOR(0), get_dma_addr() );
-#endif
-
-#else /* !SLM_CONT_CNT_REPROG */
-
- unsigned long flags, addr;
- int d, ti;
-#ifdef DEBUG
- struct timeval start_tm, end_tm;
- int did_wait = 0;
-#endif
-
- local_irq_save(flags);
-
- addr = get_dma_addr();
- if ((d = SLMEndAddr - addr) > 0) {
- local_irq_restore(flags);
-
- /* slice not yet finished, decide whether to start another timer or to
- * busy-wait */
- ti = DMA_TIME_FOR( d );
- if (ti > 0) {
-#ifdef DEBUG
- printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n",
- ti, d );
-#endif
- START_TIMER( ti );
- return;
- }
- /* wait for desired end address to be reached */
-#ifdef DEBUG
- do_gettimeofday( &start_tm );
- did_wait = 1;
-#endif
- local_irq_disable();
- while( get_dma_addr() < SLMEndAddr )
- barrier();
- }
-
- /* slice finished, start next one */
- SLMCurAddr += SLMSliceSize;
-
-#ifdef SLM_CONTINUOUS_DMA
- /* program for 255*512 bytes again */
- dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
-#else
- /* set DMA address;
- * add 2 bytes for the ones in the SLM controller FIFO! */
- set_dma_addr( SLMCurAddr + 2 );
- /* toggle DMA to write and select sector counter reg */
- dma_wd.dma_mode_status = 0x92;
- MFPDELAY();
- dma_wd.dma_mode_status = 0x192;
- MFPDELAY();
- /* program for 255*512 bytes and start DMA */
- DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
-#endif
-
- local_irq_restore(flags);
-
-#ifdef DEBUG
- if (did_wait) {
- int ms;
- do_gettimeofday( &end_tm );
- ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) -
- (start_tm.tv_sec*1000000+start_tm.tv_usec);
- printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n",
- ms/1000, ms%1000, d );
- }
- else
- printk( "SLM: didn't wait (!)\n" );
-#endif
-
- if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) {
- /* will be last slice, no timer necessary */
-#ifdef DEBUG
- printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n",
- SLMCurAddr, SLMEndAddr );
-#endif
- }
- else {
- /* not last slice */
- SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
- START_TIMER( DMA_TIME_FOR( SLMSliceSize ));
-#ifdef DEBUG
- printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
- SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
-#endif
- }
-#endif /* SLM_CONT_CNT_REPROG */
-}
-
-
-static void set_dma_addr( unsigned long paddr )
-
-{ unsigned long flags;
-
- local_irq_save(flags);
- dma_wd.dma_lo = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- dma_wd.dma_md = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- if (ATARIHW_PRESENT( EXTD_DMA ))
- st_dma_ext_dmahi = (unsigned short)paddr;
- else
- dma_wd.dma_hi = (unsigned char)paddr;
- MFPDELAY();
- local_irq_restore(flags);
-}
-
-
-static unsigned long get_dma_addr( void )
-
-{ unsigned long addr;
-
- addr = dma_wd.dma_lo & 0xff;
- MFPDELAY();
- addr |= (dma_wd.dma_md & 0xff) << 8;
- MFPDELAY();
- addr |= (dma_wd.dma_hi & 0xff) << 16;
- MFPDELAY();
-
- return( addr );
-}
-
-
-static ssize_t slm_write( struct file *file, const char *buf, size_t count,
- loff_t *ppos )
-
-{
- struct inode *node = file->f_path.dentry->d_inode;
- int device = iminor(node);
- int n, filled, w, h;
-
- while( SLMState == PRINTING ||
- (SLMState == FILLING && SLMBufOwner != device) ) {
- interruptible_sleep_on( &slm_wait );
- if (signal_pending(current))
- return( -ERESTARTSYS );
- }
- if (SLMState == IDLE) {
- /* first data of page: get current page size */
- if (slm_get_pagesize( device, &w, &h ))
- return( -EIO );
- BufferSize = w*h/8;
- if (BufferSize > SLM_BUFFER_SIZE)
- return( -ENOMEM );
-
- SLMState = FILLING;
- SLMBufOwner = device;
- }
-
- n = count;
- filled = BufferP - SLMBuffer;
- if (filled + n > BufferSize)
- n = BufferSize - filled;
-
- if (copy_from_user(BufferP, buf, n))
- return -EFAULT;
- BufferP += n;
- filled += n;
-
- if (filled == BufferSize) {
- /* Check the paper size again! The user may have switched it in the
- * time between starting the data and finishing them. Would end up in
- * a trashy page... */
- if (slm_get_pagesize( device, &w, &h ))
- return( -EIO );
- if (BufferSize != w*h/8) {
- printk( KERN_NOTICE "slm%d: page size changed while printing\n",
- device );
- return( -EAGAIN );
- }
-
- SLMState = PRINTING;
- /* choose a slice size that is a multiple of the line size */
-#ifndef SLM_CONT_CNT_REPROG
- SLMSliceSize = SLM_SLICE_SIZE(w);
-#endif
-
- start_print( device );
- sleep_on( &print_wait );
- if (SLMError && IS_REAL_ERROR(SLMError)) {
- printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) );
- n = -EIO;
- }
-
- SLMState = IDLE;
- BufferP = SLMBuffer;
- wake_up_interruptible( &slm_wait );
- }
-
- return( n );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/* ioctl Functions */
-
-
-static int slm_ioctl( struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg )
-
-{ int device = iminor(inode), err;
-
- /* I can think of setting:
- * - manual feed
- * - paper format
- * - copy count
- * - ...
- * but haven't implemented that yet :-)
- * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data?
- */
- switch( cmd ) {
-
- case SLMIORESET: /* reset buffer, i.e. empty the buffer */
- if (!(file->f_mode & 2))
- return( -EINVAL );
- if (SLMState == PRINTING)
- return( -EBUSY );
- SLMState = IDLE;
- BufferP = SLMBuffer;
- wake_up_interruptible( &slm_wait );
- return( 0 );
-
- case SLMIOGSTAT: { /* get status */
- int stat;
- char *str;
-
- stat = slm_req_sense( device );
- if (arg) {
- str = slm_errstr( stat );
- if (put_user(stat,
- (long *)&((struct SLM_status *)arg)->stat))
- return -EFAULT;
- if (copy_to_user( ((struct SLM_status *)arg)->str, str,
- strlen(str) + 1))
- return -EFAULT;
- }
- return( stat );
- }
-
- case SLMIOGPSIZE: { /* get paper size */
- int w, h;
-
- if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
-
- if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
- return -EFAULT;
- if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height))
- return -EFAULT;
- return( 0 );
- }
-
- case SLMIOGMFEED: /* get manual feed */
- return( -EINVAL );
-
- case SLMIOSPSIZE: /* set paper size */
- return( -EINVAL );
-
- case SLMIOSMFEED: /* set manual feed */
- return( -EINVAL );
-
- }
- return( -EINVAL );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/* Opening and Closing */
-
-
-static int slm_open( struct inode *inode, struct file *file )
-
-{ int device;
- struct slm *sip;
-
- device = iminor(inode);
- if (device >= N_SLM_Printers)
- return( -ENXIO );
- sip = &slm_info[device];
-
- if (file->f_mode & 2) {
- /* open for writing is exclusive */
- if ( !atomic_dec_and_test(&sip->wr_ok) ) {
- atomic_inc(&sip->wr_ok);
- return( -EBUSY );
- }
- }
- if (file->f_mode & 1) {
- /* open for reading is exclusive */
- if ( !atomic_dec_and_test(&sip->rd_ok) ) {
- atomic_inc(&sip->rd_ok);
- return( -EBUSY );
- }
- }
-
- return( 0 );
-}
-
-
-static int slm_release( struct inode *inode, struct file *file )
-
-{ int device;
- struct slm *sip;
-
- device = iminor(inode);
- sip = &slm_info[device];
-
- if (file->f_mode & 2)
- atomic_inc( &sip->wr_ok );
- if (file->f_mode & 1)
- atomic_inc( &sip->rd_ok );
-
- return( 0 );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/* ACSI Primitives for the SLM */
-
-
-static int slm_req_sense( int device )
-
-{ int stat, rv;
- struct slm *sip = &slm_info[device];
-
- stdma_lock( NULL, NULL );
-
- CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun );
- if (!acsicmd_nodma( slmreqsense_cmd, 0 ) ||
- (stat = acsi_getstatus()) < 0)
- rv = SLMSTAT_ACSITO;
- else
- rv = stat & 0x1f;
-
- ENABLE_IRQ();
- stdma_release();
- return( rv );
-}
-
-
-static int slm_mode_sense( int device, char *buffer, int abs_flag )
-
-{ unsigned char stat, len;
- int rv = 0;
- struct slm *sip = &slm_info[device];
-
- stdma_lock( NULL, NULL );
-
- CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun );
- slmmsense_cmd[5] = abs_flag ? 0x80 : 0;
- if (!acsicmd_nodma( slmmsense_cmd, 0 )) {
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
-
- if (!acsi_extstatus( &stat, 1 )) {
- acsi_end_extstatus();
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
-
- if (!acsi_extstatus( &len, 1 )) {
- acsi_end_extstatus();
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
- buffer[0] = len;
- if (!acsi_extstatus( buffer+1, len )) {
- acsi_end_extstatus();
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
-
- acsi_end_extstatus();
- rv = stat & 0x1f;
-
- the_end:
- ENABLE_IRQ();
- stdma_release();
- return( rv );
-}
-
-
-#if 0
-/* currently unused */
-static int slm_mode_select( int device, char *buffer, int len,
- int default_flag )
-
-{ int stat, rv;
- struct slm *sip = &slm_info[device];
-
- stdma_lock( NULL, NULL );
-
- CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun );
- slmmselect_cmd[5] = default_flag ? 0x80 : 0;
- if (!acsicmd_nodma( slmmselect_cmd, 0 )) {
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
-
- if (!default_flag) {
- unsigned char c = len;
- if (!acsi_extcmd( &c, 1 )) {
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
- if (!acsi_extcmd( buffer, len )) {
- rv = SLMSTAT_ACSITO;
- goto the_end;
- }
- }
-
- stat = acsi_getstatus();
- rv = (stat < 0 ? SLMSTAT_ACSITO : stat);
-
- the_end:
- ENABLE_IRQ();
- stdma_release();
- return( rv );
-}
-#endif
-
-
-static int slm_get_pagesize( int device, int *w, int *h )
-
-{ char buf[256];
- int stat;
-
- stat = slm_mode_sense( device, buf, 0 );
- ENABLE_IRQ();
- stdma_release();
-
- if (stat != SLMSTAT_OK)
- return( -EIO );
-
- *w = (buf[3] << 8) | buf[4];
- *h = (buf[1] << 8) | buf[2];
- return( 0 );
-}
-
-
-/* ---------------------------------------------------------------------- */
-/* Initialization */
-
-
-int attach_slm( int target, int lun )
-
-{ static int did_register;
- int len;
-
- if (N_SLM_Printers >= MAX_SLM) {
- printk( KERN_WARNING "Too much SLMs\n" );
- return( 0 );
- }
-
- /* do an INQUIRY */
- udelay(100);
- CMDSET_TARG_LUN( slminquiry_cmd, target, lun );
- if (!acsicmd_nodma( slminquiry_cmd, 0 )) {
- inq_timeout:
- printk( KERN_ERR "SLM inquiry command timed out.\n" );
- inq_fail:
- acsi_end_extstatus();
- return( 0 );
- }
- /* read status and header of return data */
- if (!acsi_extstatus( SLMBuffer, 6 ))
- goto inq_timeout;
-
- if (SLMBuffer[1] != 2) { /* device type == printer? */
- printk( KERN_ERR "SLM inquiry returned device type != printer\n" );
- goto inq_fail;
- }
- len = SLMBuffer[5];
-
- /* read id string */
- if (!acsi_extstatus( SLMBuffer, len ))
- goto inq_timeout;
- acsi_end_extstatus();
- SLMBuffer[len] = 0;
-
- if (!did_register) {
- did_register = 1;
- }
-
- slm_info[N_SLM_Printers].target = target;
- slm_info[N_SLM_Printers].lun = lun;
- atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 );
- atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
-
- printk( KERN_INFO " Printer: %s\n", SLMBuffer );
- printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
- N_SLM_Printers, target, lun );
- N_SLM_Printers++;
- return( 1 );
-}
-
-int slm_init( void )
-
-{
- int i;
- if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) {
- printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR );
- return -EBUSY;
- }
-
- if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) {
- printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
- unregister_chrdev( ACSI_MAJOR, "slm" );
- return -ENOMEM;
- }
- BufferP = SLMBuffer;
- SLMState = IDLE;
-
- return 0;
-}
-
-#ifdef MODULE
-
-/* from acsi.c */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-int init_module(void)
-{
- int err;
-
- if ((err = slm_init()))
- return( err );
- /* This calls attach_slm() for every target/lun where acsi.c detected a
- * printer */
- acsi_attach_SLMs( attach_slm );
- return( 0 );
-}
-
-void cleanup_module(void)
-{
- if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0)
- printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
- atari_stram_free( SLMBuffer );
-}
-#endif
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 0fcad430474e..a2d6612b80d2 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1170,7 +1170,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
case SG_EMULATED_HOST:
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
- return scsi_cmd_ioctl(filep, disk, cmd, argp);
+ return scsi_cmd_ioctl(filep, disk->queue, disk, cmd, argp);
/* scsi_cmd_ioctl would normally handle these, below, but */
/* they aren't a good fit for cciss, as CD-ROMs are */
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 4503290da407..e425daa1eac3 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -68,6 +68,7 @@
#include <linux/loop.h>
#include <linux/compat.h>
#include <linux/suspend.h>
+#include <linux/freezer.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <linux/completion.h>
@@ -600,13 +601,6 @@ static int loop_thread(void *data)
struct loop_device *lo = data;
struct bio *bio;
- /*
- * loop can be used in an encrypted device,
- * hence, it mustn't be stopped at all
- * because it could be indirectly used during suspension
- */
- current->flags |= PF_NOFREEZE;
-
set_user_nice(current, -20);
while (!kthread_should_stop() || lo->lo_bio) {
@@ -1574,8 +1568,7 @@ static void __exit loop_exit(void)
loop_del_one(lo);
blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
- if (unregister_blkdev(LOOP_MAJOR, "loop"))
- printk(KERN_WARNING "loop: cannot unregister blkdev\n");
+ unregister_blkdev(LOOP_MAJOR, "loop");
}
module_init(loop_init);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index c575fb1d585f..c12951024090 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -122,17 +122,12 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
int result;
struct msghdr msg;
struct kvec iov;
- unsigned long flags;
- sigset_t oldset;
+ sigset_t blocked, oldset;
/* Allow interception of SIGKILL only
* Don't allow other signals to interrupt the transmission */
- spin_lock_irqsave(&current->sighand->siglock, flags);
- oldset = current->blocked;
- sigfillset(&current->blocked);
- sigdelsetmask(&current->blocked, sigmask(SIGKILL));
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ siginitsetinv(&blocked, sigmask(SIGKILL));
+ sigprocmask(SIG_SETMASK, &blocked, &oldset);
do {
sock->sk->sk_allocation = GFP_NOIO;
@@ -151,11 +146,9 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
if (signal_pending(current)) {
siginfo_t info;
- spin_lock_irqsave(&current->sighand->siglock, flags);
printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
- current->pid, current->comm,
- dequeue_signal(current, &current->blocked, &info));
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ current->pid, current->comm,
+ dequeue_signal_lock(current, &current->blocked, &info));
result = -EINTR;
break;
}
@@ -169,10 +162,7 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
buf += result;
} while (size > 0);
- spin_lock_irqsave(&current->sighand->siglock, flags);
- current->blocked = oldset;
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
return result;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ce64e86d6ffb..31be33e4f119 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1593,6 +1593,7 @@ static int kcdrwd(void *foobar)
long min_sleep_time, residue;
set_user_nice(current, -20);
+ set_freezable();
for (;;) {
DECLARE_WAITQUEUE(wait, current);
@@ -1652,9 +1653,6 @@ static int kcdrwd(void *foobar)
}
}
- if (signal_pending(current)) {
- flush_signals(current);
- }
if (kthread_should_stop())
break;
}
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
new file mode 100644
index 000000000000..0f5e3caf85d7
--- /dev/null
+++ b/drivers/block/sunvdc.c
@@ -0,0 +1,972 @@
+/* sunvdc.c: Sun LDOM Virtual Disk Client.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/list.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#define DRV_MODULE_NAME "sunvdc"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "June 25, 2007"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual disk client driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define VDC_TX_RING_SIZE 256
+
+#define WAITING_FOR_LINK_UP 0x01
+#define WAITING_FOR_TX_SPACE 0x02
+#define WAITING_FOR_GEN_CMD 0x04
+#define WAITING_FOR_ANY -1
+
+struct vdc_req_entry {
+ struct request *req;
+};
+
+struct vdc_port {
+ struct vio_driver_state vio;
+
+ struct vdc *vp;
+
+ struct gendisk *disk;
+
+ struct vdc_completion *cmp;
+
+ u64 req_id;
+ u64 seq;
+ struct vdc_req_entry rq_arr[VDC_TX_RING_SIZE];
+
+ unsigned long ring_cookies;
+
+ u64 max_xfer_size;
+ u32 vdisk_block_size;
+
+ /* The server fills these in for us in the disk attribute
+ * ACK packet.
+ */
+ u64 operations;
+ u32 vdisk_size;
+ u8 vdisk_type;
+ u8 dev_no;
+
+ char disk_name[32];
+
+ struct vio_disk_geom geom;
+ struct vio_disk_vtoc label;
+
+ struct list_head list;
+};
+
+static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
+{
+ return container_of(vio, struct vdc_port, vio);
+}
+
+struct vdc {
+ /* Protects prot_list. */
+ spinlock_t lock;
+
+ struct vio_dev *dev;
+
+ struct list_head port_list;
+};
+
+/* Ordered from largest major to lowest */
+static struct vio_version vdc_versions[] = {
+ { .major = 1, .minor = 0 },
+};
+
+#define VDCBLK_NAME "vdisk"
+static int vdc_major;
+#define PARTITION_SHIFT 3
+
+static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr)
+{
+ return vio_dring_avail(dr, VDC_TX_RING_SIZE);
+}
+
+static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ struct vdc_port *port = disk->private_data;
+
+ geo->heads = (u8) port->geom.num_hd;
+ geo->sectors = (u8) port->geom.num_sec;
+ geo->cylinders = port->geom.num_cyl;
+
+ return 0;
+}
+
+static struct block_device_operations vdc_fops = {
+ .owner = THIS_MODULE,
+ .getgeo = vdc_getgeo,
+};
+
+static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
+{
+ if (vio->cmp &&
+ (waiting_for == -1 ||
+ vio->cmp->waiting_for == waiting_for)) {
+ vio->cmp->err = err;
+ complete(&vio->cmp->com);
+ vio->cmp = NULL;
+ }
+}
+
+static void vdc_handshake_complete(struct vio_driver_state *vio)
+{
+ vdc_finish(vio, 0, WAITING_FOR_LINK_UP);
+}
+
+static int vdc_handle_unknown(struct vdc_port *port, void *arg)
+{
+ struct vio_msg_tag *pkt = arg;
+
+ printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+ pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+ printk(KERN_ERR PFX "Resetting connection.\n");
+
+ ldc_disconnect(port->vio.lp);
+
+ return -ECONNRESET;
+}
+
+static int vdc_send_attr(struct vio_driver_state *vio)
+{
+ struct vdc_port *port = to_vdc_port(vio);
+ struct vio_disk_attr_info pkt;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.tag.type = VIO_TYPE_CTRL;
+ pkt.tag.stype = VIO_SUBTYPE_INFO;
+ pkt.tag.stype_env = VIO_ATTR_INFO;
+ pkt.tag.sid = vio_send_sid(vio);
+
+ pkt.xfer_mode = VIO_DRING_MODE;
+ pkt.vdisk_block_size = port->vdisk_block_size;
+ pkt.max_xfer_size = port->max_xfer_size;
+
+ viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+ pkt.xfer_mode, pkt.vdisk_block_size, pkt.max_xfer_size);
+
+ return vio_ldc_send(&port->vio, &pkt, sizeof(pkt));
+}
+
+static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+ struct vdc_port *port = to_vdc_port(vio);
+ struct vio_disk_attr_info *pkt = arg;
+
+ viodbg(HS, "GOT ATTR stype[0x%x] ops[%lx] disk_size[%lu] disk_type[%x] "
+ "xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+ pkt->tag.stype, pkt->operations,
+ pkt->vdisk_size, pkt->vdisk_type,
+ pkt->xfer_mode, pkt->vdisk_block_size,
+ pkt->max_xfer_size);
+
+ if (pkt->tag.stype == VIO_SUBTYPE_ACK) {
+ switch (pkt->vdisk_type) {
+ case VD_DISK_TYPE_DISK:
+ case VD_DISK_TYPE_SLICE:
+ break;
+
+ default:
+ printk(KERN_ERR PFX "%s: Bogus vdisk_type 0x%x\n",
+ vio->name, pkt->vdisk_type);
+ return -ECONNRESET;
+ }
+
+ if (pkt->vdisk_block_size > port->vdisk_block_size) {
+ printk(KERN_ERR PFX "%s: BLOCK size increased "
+ "%u --> %u\n",
+ vio->name,
+ port->vdisk_block_size, pkt->vdisk_block_size);
+ return -ECONNRESET;
+ }
+
+ port->operations = pkt->operations;
+ port->vdisk_size = pkt->vdisk_size;
+ port->vdisk_type = pkt->vdisk_type;
+ if (pkt->max_xfer_size < port->max_xfer_size)
+ port->max_xfer_size = pkt->max_xfer_size;
+ port->vdisk_block_size = pkt->vdisk_block_size;
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "%s: Attribute NACK\n", vio->name);
+
+ return -ECONNRESET;
+ }
+}
+
+static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
+{
+ int err = desc->status;
+
+ vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
+}
+
+static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
+{
+ if (end_that_request_first(req, uptodate, num_sectors))
+ return;
+ add_disk_randomness(req->rq_disk);
+ end_that_request_last(req, uptodate);
+}
+
+static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
+ unsigned int index)
+{
+ struct vio_disk_desc *desc = vio_dring_entry(dr, index);
+ struct vdc_req_entry *rqe = &port->rq_arr[index];
+ struct request *req;
+
+ if (unlikely(desc->hdr.state != VIO_DESC_DONE))
+ return;
+
+ ldc_unmap(port->vio.lp, desc->cookies, desc->ncookies);
+ desc->hdr.state = VIO_DESC_FREE;
+ dr->cons = (index + 1) & (VDC_TX_RING_SIZE - 1);
+
+ req = rqe->req;
+ if (req == NULL) {
+ vdc_end_special(port, desc);
+ return;
+ }
+
+ rqe->req = NULL;
+
+ vdc_end_request(req, !desc->status, desc->size >> 9);
+
+ if (blk_queue_stopped(port->disk->queue))
+ blk_start_queue(port->disk->queue);
+}
+
+static int vdc_ack(struct vdc_port *port, void *msgbuf)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data *pkt = msgbuf;
+
+ if (unlikely(pkt->dring_ident != dr->ident ||
+ pkt->start_idx != pkt->end_idx ||
+ pkt->start_idx >= VDC_TX_RING_SIZE))
+ return 0;
+
+ vdc_end_one(port, dr, pkt->start_idx);
+
+ return 0;
+}
+
+static int vdc_nack(struct vdc_port *port, void *msgbuf)
+{
+ /* XXX Implement me XXX */
+ return 0;
+}
+
+static void vdc_event(void *arg, int event)
+{
+ struct vdc_port *port = arg;
+ struct vio_driver_state *vio = &port->vio;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&vio->lock, flags);
+
+ if (unlikely(event == LDC_EVENT_RESET ||
+ event == LDC_EVENT_UP)) {
+ vio_link_state_change(vio, event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+ return;
+ }
+
+ if (unlikely(event != LDC_EVENT_DATA_READY)) {
+ printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+ return;
+ }
+
+ err = 0;
+ while (1) {
+ union {
+ struct vio_msg_tag tag;
+ u64 raw[8];
+ } msgbuf;
+
+ err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+ if (unlikely(err < 0)) {
+ if (err == -ECONNRESET)
+ vio_conn_reset(vio);
+ break;
+ }
+ if (err == 0)
+ break;
+ viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+ msgbuf.tag.type,
+ msgbuf.tag.stype,
+ msgbuf.tag.stype_env,
+ msgbuf.tag.sid);
+ err = vio_validate_sid(vio, &msgbuf.tag);
+ if (err < 0)
+ break;
+
+ if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+ if (msgbuf.tag.stype == VIO_SUBTYPE_ACK)
+ err = vdc_ack(port, &msgbuf);
+ else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK)
+ err = vdc_nack(port, &msgbuf);
+ else
+ err = vdc_handle_unknown(port, &msgbuf);
+ } else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+ err = vio_control_pkt_engine(vio, &msgbuf);
+ } else {
+ err = vdc_handle_unknown(port, &msgbuf);
+ }
+ if (err < 0)
+ break;
+ }
+ if (err < 0)
+ vdc_finish(&port->vio, err, WAITING_FOR_ANY);
+ spin_unlock_irqrestore(&vio->lock, flags);
+}
+
+static int __vdc_tx_trigger(struct vdc_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data hdr = {
+ .tag = {
+ .type = VIO_TYPE_DATA,
+ .stype = VIO_SUBTYPE_INFO,
+ .stype_env = VIO_DRING_DATA,
+ .sid = vio_send_sid(&port->vio),
+ },
+ .dring_ident = dr->ident,
+ .start_idx = dr->prod,
+ .end_idx = dr->prod,
+ };
+ int err, delay;
+
+ hdr.seq = dr->snd_nxt;
+ delay = 1;
+ do {
+ err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+ if (err > 0) {
+ dr->snd_nxt++;
+ break;
+ }
+ udelay(delay);
+ if ((delay <<= 1) > 128)
+ delay = 128;
+ } while (err == -EAGAIN);
+
+ return err;
+}
+
+static int __send_request(struct request *req)
+{
+ struct vdc_port *port = req->rq_disk->private_data;
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct scatterlist sg[port->ring_cookies];
+ struct vdc_req_entry *rqe;
+ struct vio_disk_desc *desc;
+ unsigned int map_perm;
+ int nsg, err, i;
+ u64 len;
+ u8 op;
+
+ map_perm = LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+ if (rq_data_dir(req) == READ) {
+ map_perm |= LDC_MAP_W;
+ op = VD_OP_BREAD;
+ } else {
+ map_perm |= LDC_MAP_R;
+ op = VD_OP_BWRITE;
+ }
+
+ nsg = blk_rq_map_sg(req->q, req, sg);
+
+ len = 0;
+ for (i = 0; i < nsg; i++)
+ len += sg[i].length;
+
+ if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
+ blk_stop_queue(port->disk->queue);
+ err = -ENOMEM;
+ goto out;
+ }
+
+ desc = vio_dring_cur(dr);
+
+ err = ldc_map_sg(port->vio.lp, sg, nsg,
+ desc->cookies, port->ring_cookies,
+ map_perm);
+ if (err < 0) {
+ printk(KERN_ERR PFX "ldc_map_sg() failure, err=%d.\n", err);
+ return err;
+ }
+
+ rqe = &port->rq_arr[dr->prod];
+ rqe->req = req;
+
+ desc->hdr.ack = VIO_ACK_ENABLE;
+ desc->req_id = port->req_id;
+ desc->operation = op;
+ if (port->vdisk_type == VD_DISK_TYPE_DISK) {
+ desc->slice = 2;
+ } else {
+ desc->slice = 0;
+ }
+ desc->status = ~0;
+ desc->offset = (req->sector << 9) / port->vdisk_block_size;
+ desc->size = len;
+ desc->ncookies = err;
+
+ /* This has to be a non-SMP write barrier because we are writing
+ * to memory which is shared with the peer LDOM.
+ */
+ wmb();
+ desc->hdr.state = VIO_DESC_READY;
+
+ err = __vdc_tx_trigger(port);
+ if (err < 0) {
+ printk(KERN_ERR PFX "vdc_tx_trigger() failure, err=%d\n", err);
+ } else {
+ port->req_id++;
+ dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+ }
+out:
+
+ return err;
+}
+
+static void do_vdc_request(request_queue_t *q)
+{
+ while (1) {
+ struct request *req = elv_next_request(q);
+
+ if (!req)
+ break;
+
+ blkdev_dequeue_request(req);
+ if (__send_request(req) < 0)
+ vdc_end_request(req, 0, req->hard_nr_sectors);
+ }
+}
+
+static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
+{
+ struct vio_dring_state *dr;
+ struct vio_completion comp;
+ struct vio_disk_desc *desc;
+ unsigned int map_perm;
+ unsigned long flags;
+ int op_len, err;
+ void *req_buf;
+
+ if (!(((u64)1 << ((u64)op - 1)) & port->operations))
+ return -EOPNOTSUPP;
+
+ switch (op) {
+ case VD_OP_BREAD:
+ case VD_OP_BWRITE:
+ default:
+ return -EINVAL;
+
+ case VD_OP_FLUSH:
+ op_len = 0;
+ map_perm = 0;
+ break;
+
+ case VD_OP_GET_WCE:
+ op_len = sizeof(u32);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_SET_WCE:
+ op_len = sizeof(u32);
+ map_perm = LDC_MAP_R;
+ break;
+
+ case VD_OP_GET_VTOC:
+ op_len = sizeof(struct vio_disk_vtoc);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_SET_VTOC:
+ op_len = sizeof(struct vio_disk_vtoc);
+ map_perm = LDC_MAP_R;
+ break;
+
+ case VD_OP_GET_DISKGEOM:
+ op_len = sizeof(struct vio_disk_geom);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_SET_DISKGEOM:
+ op_len = sizeof(struct vio_disk_geom);
+ map_perm = LDC_MAP_R;
+ break;
+
+ case VD_OP_SCSICMD:
+ op_len = 16;
+ map_perm = LDC_MAP_RW;
+ break;
+
+ case VD_OP_GET_DEVID:
+ op_len = sizeof(struct vio_disk_devid);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_GET_EFI:
+ case VD_OP_SET_EFI:
+ return -EOPNOTSUPP;
+ break;
+ };
+
+ map_perm |= LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+ op_len = (op_len + 7) & ~7;
+ req_buf = kzalloc(op_len, GFP_KERNEL);
+ if (!req_buf)
+ return -ENOMEM;
+
+ if (len > op_len)
+ len = op_len;
+
+ if (map_perm & LDC_MAP_R)
+ memcpy(req_buf, buf, len);
+
+ spin_lock_irqsave(&port->vio.lock, flags);
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+ /* XXX If we want to use this code generically we have to
+ * XXX handle TX ring exhaustion etc.
+ */
+ desc = vio_dring_cur(dr);
+
+ err = ldc_map_single(port->vio.lp, req_buf, op_len,
+ desc->cookies, port->ring_cookies,
+ map_perm);
+ if (err < 0) {
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+ kfree(req_buf);
+ return err;
+ }
+
+ init_completion(&comp.com);
+ comp.waiting_for = WAITING_FOR_GEN_CMD;
+ port->vio.cmp = &comp;
+
+ desc->hdr.ack = VIO_ACK_ENABLE;
+ desc->req_id = port->req_id;
+ desc->operation = op;
+ desc->slice = 0;
+ desc->status = ~0;
+ desc->offset = 0;
+ desc->size = op_len;
+ desc->ncookies = err;
+
+ /* This has to be a non-SMP write barrier because we are writing
+ * to memory which is shared with the peer LDOM.
+ */
+ wmb();
+ desc->hdr.state = VIO_DESC_READY;
+
+ err = __vdc_tx_trigger(port);
+ if (err >= 0) {
+ port->req_id++;
+ dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+
+ wait_for_completion(&comp.com);
+ err = comp.err;
+ } else {
+ port->vio.cmp = NULL;
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+ }
+
+ if (map_perm & LDC_MAP_W)
+ memcpy(buf, req_buf, len);
+
+ kfree(req_buf);
+
+ return err;
+}
+
+static int __devinit vdc_alloc_tx_ring(struct vdc_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ unsigned long len, entry_size;
+ int ncookies;
+ void *dring;
+
+ entry_size = sizeof(struct vio_disk_desc) +
+ (sizeof(struct ldc_trans_cookie) * port->ring_cookies);
+ len = (VDC_TX_RING_SIZE * entry_size);
+
+ ncookies = VIO_MAX_RING_COOKIES;
+ dring = ldc_alloc_exp_dring(port->vio.lp, len,
+ dr->cookies, &ncookies,
+ (LDC_MAP_SHADOW |
+ LDC_MAP_DIRECT |
+ LDC_MAP_RW));
+ if (IS_ERR(dring))
+ return PTR_ERR(dring);
+
+ dr->base = dring;
+ dr->entry_size = entry_size;
+ dr->num_entries = VDC_TX_RING_SIZE;
+ dr->prod = dr->cons = 0;
+ dr->pending = VDC_TX_RING_SIZE;
+ dr->ncookies = ncookies;
+
+ return 0;
+}
+
+static void vdc_free_tx_ring(struct vdc_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+ if (dr->base) {
+ ldc_free_exp_dring(port->vio.lp, dr->base,
+ (dr->entry_size * dr->num_entries),
+ dr->cookies, dr->ncookies);
+ dr->base = NULL;
+ dr->entry_size = 0;
+ dr->num_entries = 0;
+ dr->pending = 0;
+ dr->ncookies = 0;
+ }
+}
+
+static int probe_disk(struct vdc_port *port)
+{
+ struct vio_completion comp;
+ struct request_queue *q;
+ struct gendisk *g;
+ int err;
+
+ init_completion(&comp.com);
+ comp.err = 0;
+ comp.waiting_for = WAITING_FOR_LINK_UP;
+ port->vio.cmp = &comp;
+
+ vio_port_up(&port->vio);
+
+ wait_for_completion(&comp.com);
+ if (comp.err)
+ return comp.err;
+
+ err = generic_request(port, VD_OP_GET_VTOC,
+ &port->label, sizeof(port->label));
+ if (err < 0) {
+ printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
+ return err;
+ }
+
+ err = generic_request(port, VD_OP_GET_DISKGEOM,
+ &port->geom, sizeof(port->geom));
+ if (err < 0) {
+ printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
+ "error %d\n", err);
+ return err;
+ }
+
+ port->vdisk_size = ((u64)port->geom.num_cyl *
+ (u64)port->geom.num_hd *
+ (u64)port->geom.num_sec);
+
+ q = blk_init_queue(do_vdc_request, &port->vio.lock);
+ if (!q) {
+ printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
+ port->vio.name);
+ return -ENOMEM;
+ }
+ g = alloc_disk(1 << PARTITION_SHIFT);
+ if (!g) {
+ printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
+ port->vio.name);
+ blk_cleanup_queue(q);
+ return -ENOMEM;
+ }
+
+ port->disk = g;
+
+ blk_queue_max_hw_segments(q, port->ring_cookies);
+ blk_queue_max_phys_segments(q, port->ring_cookies);
+ blk_queue_max_sectors(q, port->max_xfer_size);
+ g->major = vdc_major;
+ g->first_minor = port->dev_no << PARTITION_SHIFT;
+ strcpy(g->disk_name, port->disk_name);
+
+ g->fops = &vdc_fops;
+ g->queue = q;
+ g->private_data = port;
+ g->driverfs_dev = &port->vio.vdev->dev;
+
+ set_capacity(g, port->vdisk_size);
+
+ printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n",
+ g->disk_name,
+ port->vdisk_size, (port->vdisk_size >> (20 - 9)));
+
+ add_disk(g);
+
+ return 0;
+}
+
+static struct ldc_channel_config vdc_ldc_cfg = {
+ .event = vdc_event,
+ .mtu = 64,
+ .mode = LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vdc_vio_ops = {
+ .send_attr = vdc_send_attr,
+ .handle_attr = vdc_handle_attr,
+ .handshake_complete = vdc_handshake_complete,
+};
+
+static int __devinit vdc_port_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ struct mdesc_handle *hp;
+ struct vdc_port *port;
+ unsigned long flags;
+ struct vdc *vp;
+ const u64 *port_id;
+ int err;
+
+ vp = dev_get_drvdata(vdev->dev.parent);
+ if (!vp) {
+ printk(KERN_ERR PFX "Cannot find port parent vdc.\n");
+ return -ENODEV;
+ }
+
+ hp = mdesc_grab();
+
+ port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
+ err = -ENODEV;
+ if (!port_id) {
+ printk(KERN_ERR PFX "Port lacks id property.\n");
+ goto err_out_release_mdesc;
+ }
+ if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
+ printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
+ goto err_out_release_mdesc;
+ }
+
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!port) {
+ printk(KERN_ERR PFX "Cannot allocate vdc_port.\n");
+ goto err_out_release_mdesc;
+ }
+
+ port->vp = vp;
+ port->dev_no = *port_id;
+
+ if (port->dev_no >= 26)
+ snprintf(port->disk_name, sizeof(port->disk_name),
+ VDCBLK_NAME "%c%c",
+ 'a' + (port->dev_no / 26) - 1,
+ 'a' + (port->dev_no % 26));
+ else
+ snprintf(port->disk_name, sizeof(port->disk_name),
+ VDCBLK_NAME "%c", 'a' + (port->dev_no % 26));
+
+ err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
+ vdc_versions, ARRAY_SIZE(vdc_versions),
+ &vdc_vio_ops, port->disk_name);
+ if (err)
+ goto err_out_free_port;
+
+ port->vdisk_block_size = 512;
+ port->max_xfer_size = ((128 * 1024) / port->vdisk_block_size);
+ port->ring_cookies = ((port->max_xfer_size *
+ port->vdisk_block_size) / PAGE_SIZE) + 2;
+
+ err = vio_ldc_alloc(&port->vio, &vdc_ldc_cfg, port);
+ if (err)
+ goto err_out_free_port;
+
+ err = vdc_alloc_tx_ring(port);
+ if (err)
+ goto err_out_free_ldc;
+
+ err = probe_disk(port);
+ if (err)
+ goto err_out_free_tx_ring;
+
+ INIT_LIST_HEAD(&port->list);
+
+ spin_lock_irqsave(&vp->lock, flags);
+ list_add(&port->list, &vp->port_list);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ dev_set_drvdata(&vdev->dev, port);
+
+ mdesc_release(hp);
+
+ return 0;
+
+err_out_free_tx_ring:
+ vdc_free_tx_ring(port);
+
+err_out_free_ldc:
+ vio_ldc_free(&port->vio);
+
+err_out_free_port:
+ kfree(port);
+
+err_out_release_mdesc:
+ mdesc_release(hp);
+ return err;
+}
+
+static int vdc_port_remove(struct vio_dev *vdev)
+{
+ struct vdc_port *port = dev_get_drvdata(&vdev->dev);
+
+ if (port) {
+ del_timer_sync(&port->vio.timer);
+
+ vdc_free_tx_ring(port);
+ vio_ldc_free(&port->vio);
+
+ dev_set_drvdata(&vdev->dev, NULL);
+
+ kfree(port);
+ }
+ return 0;
+}
+
+static struct vio_device_id vdc_port_match[] = {
+ {
+ .type = "vdc-port",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_port_driver = {
+ .id_table = vdc_port_match,
+ .probe = vdc_port_probe,
+ .remove = vdc_port_remove,
+ .driver = {
+ .name = "vdc_port",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __devinit vdc_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ static int vdc_version_printed;
+ struct vdc *vp;
+
+ if (vdc_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ vp = kzalloc(sizeof(struct vdc), GFP_KERNEL);
+ if (!vp)
+ return -ENOMEM;
+
+ spin_lock_init(&vp->lock);
+ vp->dev = vdev;
+ INIT_LIST_HEAD(&vp->port_list);
+
+ dev_set_drvdata(&vdev->dev, vp);
+
+ return 0;
+}
+
+static int vdc_remove(struct vio_dev *vdev)
+{
+
+ struct vdc *vp = dev_get_drvdata(&vdev->dev);
+
+ if (vp) {
+ kfree(vp);
+ dev_set_drvdata(&vdev->dev, NULL);
+ }
+ return 0;
+}
+
+static struct vio_device_id vdc_match[] = {
+ {
+ .type = "block",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_driver = {
+ .id_table = vdc_match,
+ .probe = vdc_probe,
+ .remove = vdc_remove,
+ .driver = {
+ .name = "vdc",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init vdc_init(void)
+{
+ int err;
+
+ err = register_blkdev(0, VDCBLK_NAME);
+ if (err < 0)
+ goto out_err;
+
+ vdc_major = err;
+ err = vio_register_driver(&vdc_driver);
+ if (err)
+ goto out_unregister_blkdev;
+
+ err = vio_register_driver(&vdc_port_driver);
+ if (err)
+ goto out_unregister_vdc;
+
+ return 0;
+
+out_unregister_vdc:
+ vio_unregister_driver(&vdc_driver);
+
+out_unregister_blkdev:
+ unregister_blkdev(vdc_major, VDCBLK_NAME);
+ vdc_major = 0;
+
+out_err:
+ return err;
+}
+
+static void __exit vdc_exit(void)
+{
+ vio_unregister_driver(&vdc_port_driver);
+ vio_unregister_driver(&vdc_driver);
+ unregister_blkdev(vdc_major, VDCBLK_NAME);
+}
+
+module_init(vdc_init);
+module_exit(vdc_exit);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 18c8b6c0db20..8b13d7d2cb63 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1709,7 +1709,7 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
struct gendisk *disk = inode->i_bdev->bd_disk;
void __user *usermem = (void __user *) arg;
- return scsi_cmd_ioctl(filp, disk, cmd, usermem);
+ return scsi_cmd_ioctl(filp, disk->queue, disk, cmd, usermem);
}
/*
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 6f5d6203d725..dec74bd23496 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -105,12 +105,6 @@ struct cardinfo {
unsigned long csr_base;
unsigned char __iomem *csr_remap;
unsigned long csr_len;
-#ifdef CONFIG_MM_MAP_MEMORY
- unsigned long mem_base;
- unsigned char __iomem *mem_remap;
- unsigned long mem_len;
-#endif
-
unsigned int win_size; /* PCI window size */
unsigned int mm_size; /* size in kbytes */
@@ -872,10 +866,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
card->csr_base = pci_resource_start(dev, 0);
card->csr_len = pci_resource_len(dev, 0);
-#ifdef CONFIG_MM_MAP_MEMORY
- card->mem_base = pci_resource_start(dev, 1);
- card->mem_len = pci_resource_len(dev, 1);
-#endif
printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n",
card->card_number, dev->bus->number, dev->devfn);
@@ -903,27 +893,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number,
card->csr_base, card->csr_remap, card->csr_len);
-#ifdef CONFIG_MM_MAP_MEMORY
- if (!request_mem_region(card->mem_base, card->mem_len, "Micro Memory")) {
- printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number);
- ret = -ENOMEM;
-
- goto failed_req_mem;
- }
-
- if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) {
- printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number);
- ret = -ENOMEM;
-
- goto failed_remap_mem;
- }
-
- printk(KERN_INFO "MM%d: MEM 0x%8lx -> 0x%8lx (0x%lx)\n", card->card_number,
- card->mem_base, card->mem_remap, card->mem_len);
-#else
- printk(KERN_INFO "MM%d: MEM area not remapped (CONFIG_MM_MAP_MEMORY not set)\n",
- card->card_number);
-#endif
switch(card->dev->device) {
case 0x5415:
card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG;
@@ -1091,12 +1060,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
card->mm_pages[1].desc,
card->mm_pages[1].page_dma);
failed_magic:
-#ifdef CONFIG_MM_MAP_MEMORY
- iounmap(card->mem_remap);
- failed_remap_mem:
- release_mem_region(card->mem_base, card->mem_len);
- failed_req_mem:
-#endif
iounmap(card->csr_remap);
failed_remap_csr:
release_mem_region(card->csr_base, card->csr_len);
@@ -1116,10 +1079,6 @@ static void mm_pci_remove(struct pci_dev *dev)
tasklet_kill(&card->tasklet);
iounmap(card->csr_remap);
release_mem_region(card->csr_base, card->csr_len);
-#ifdef CONFIG_MM_MAP_MEMORY
- iounmap(card->mem_remap);
- release_mem_region(card->mem_base, card->mem_len);
-#endif
free_irq(card->irq, card);
if (card->mm_pages[0].desc)
@@ -1133,23 +1092,18 @@ static void mm_pci_remove(struct pci_dev *dev)
blk_cleanup_queue(card->queue);
}
-static const struct pci_device_id mm_pci_ids[] = { {
- .vendor = PCI_VENDOR_ID_MICRO_MEMORY,
- .device = PCI_DEVICE_ID_MICRO_MEMORY_5415CN,
- }, {
- .vendor = PCI_VENDOR_ID_MICRO_MEMORY,
- .device = PCI_DEVICE_ID_MICRO_MEMORY_5425CN,
- }, {
- .vendor = PCI_VENDOR_ID_MICRO_MEMORY,
- .device = PCI_DEVICE_ID_MICRO_MEMORY_6155,
- }, {
+static const struct pci_device_id mm_pci_ids[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5415CN)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5425CN)},
+ {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_6155)},
+ {
.vendor = 0x8086,
.device = 0xB555,
.subvendor= 0x1332,
.subdevice= 0x5460,
.class = 0x050000,
.class_mask= 0,
- }, { /* end: all zeroes */ }
+ }, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, mm_pci_ids);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 68592c336011..dae39911a11d 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -252,10 +252,10 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
struct gendisk *disk = bdev->bd_disk;
struct viodasd_device *d = disk->private_data;
- geo->sectors = d->sectors ? d->sectors : 0;
+ geo->sectors = d->sectors ? d->sectors : 32;
geo->heads = d->tracks ? d->tracks : 64;
geo->cylinders = d->cylinders ? d->cylinders :
- get_capacity(disk) / (geo->cylinders * geo->heads);
+ get_capacity(disk) / (geo->sectors * geo->heads);
return 0;
}
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
new file mode 100644
index 000000000000..732ec63b6e9c
--- /dev/null
+++ b/drivers/block/xsysace.c
@@ -0,0 +1,1164 @@
+/*
+ * Xilinx SystemACE device driver
+ *
+ * Copyright 2007 Secret Lab Technologies 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.
+ */
+
+/*
+ * The SystemACE chip is designed to configure FPGAs by loading an FPGA
+ * bitstream from a file on a CF card and squirting it into FPGAs connected
+ * to the SystemACE JTAG chain. It also has the advantage of providing an
+ * MPU interface which can be used to control the FPGA configuration process
+ * and to use the attached CF card for general purpose storage.
+ *
+ * This driver is a block device driver for the SystemACE.
+ *
+ * Initialization:
+ * The driver registers itself as a platform_device driver at module
+ * load time. The platform bus will take care of calling the
+ * ace_probe() method for all SystemACE instances in the system. Any
+ * number of SystemACE instances are supported. ace_probe() calls
+ * ace_setup() which initialized all data structures, reads the CF
+ * id structure and registers the device.
+ *
+ * Processing:
+ * Just about all of the heavy lifting in this driver is performed by
+ * a Finite State Machine (FSM). The driver needs to wait on a number
+ * of events; some raised by interrupts, some which need to be polled
+ * for. Describing all of the behaviour in a FSM seems to be the
+ * easiest way to keep the complexity low and make it easy to
+ * understand what the driver is doing. If the block ops or the
+ * request function need to interact with the hardware, then they
+ * simply need to flag the request and kick of FSM processing.
+ *
+ * The FSM itself is atomic-safe code which can be run from any
+ * context. The general process flow is:
+ * 1. obtain the ace->lock spinlock.
+ * 2. loop on ace_fsm_dostate() until the ace->fsm_continue flag is
+ * cleared.
+ * 3. release the lock.
+ *
+ * Individual states do not sleep in any way. If a condition needs to
+ * be waited for then the state much clear the fsm_continue flag and
+ * either schedule the FSM to be run again at a later time, or expect
+ * an interrupt to call the FSM when the desired condition is met.
+ *
+ * In normal operation, the FSM is processed at interrupt context
+ * either when the driver's tasklet is scheduled, or when an irq is
+ * raised by the hardware. The tasklet can be scheduled at any time.
+ * The request method in particular schedules the tasklet when a new
+ * request has been indicated by the block layer. Once started, the
+ * FSM proceeds as far as it can processing the request until it
+ * needs on a hardware event. At this point, it must yield execution.
+ *
+ * A state has two options when yielding execution:
+ * 1. ace_fsm_yield()
+ * - Call if need to poll for event.
+ * - clears the fsm_continue flag to exit the processing loop
+ * - reschedules the tasklet to run again as soon as possible
+ * 2. ace_fsm_yieldirq()
+ * - Call if an irq is expected from the HW
+ * - clears the fsm_continue flag to exit the processing loop
+ * - does not reschedule the tasklet so the FSM will not be processed
+ * again until an irq is received.
+ * After calling a yield function, the state must return control back
+ * to the FSM main loop.
+ *
+ * Additionally, the driver maintains a kernel timer which can process
+ * the FSM. If the FSM gets stalled, typically due to a missed
+ * interrupt, then the kernel timer will expire and the driver can
+ * continue where it left off.
+ *
+ * To Do:
+ * - Add FPGA configuration control interface.
+ * - Request major number from lanana
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/platform_device.h>
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("Xilinx SystemACE device driver");
+MODULE_LICENSE("GPL");
+
+/* SystemACE register definitions */
+#define ACE_BUSMODE (0x00)
+
+#define ACE_STATUS (0x04)
+#define ACE_STATUS_CFGLOCK (0x00000001)
+#define ACE_STATUS_MPULOCK (0x00000002)
+#define ACE_STATUS_CFGERROR (0x00000004) /* config controller error */
+#define ACE_STATUS_CFCERROR (0x00000008) /* CF controller error */
+#define ACE_STATUS_CFDETECT (0x00000010)
+#define ACE_STATUS_DATABUFRDY (0x00000020)
+#define ACE_STATUS_DATABUFMODE (0x00000040)
+#define ACE_STATUS_CFGDONE (0x00000080)
+#define ACE_STATUS_RDYFORCFCMD (0x00000100)
+#define ACE_STATUS_CFGMODEPIN (0x00000200)
+#define ACE_STATUS_CFGADDR_MASK (0x0000e000)
+#define ACE_STATUS_CFBSY (0x00020000)
+#define ACE_STATUS_CFRDY (0x00040000)
+#define ACE_STATUS_CFDWF (0x00080000)
+#define ACE_STATUS_CFDSC (0x00100000)
+#define ACE_STATUS_CFDRQ (0x00200000)
+#define ACE_STATUS_CFCORR (0x00400000)
+#define ACE_STATUS_CFERR (0x00800000)
+
+#define ACE_ERROR (0x08)
+#define ACE_CFGLBA (0x0c)
+#define ACE_MPULBA (0x10)
+
+#define ACE_SECCNTCMD (0x14)
+#define ACE_SECCNTCMD_RESET (0x0100)
+#define ACE_SECCNTCMD_IDENTIFY (0x0200)
+#define ACE_SECCNTCMD_READ_DATA (0x0300)
+#define ACE_SECCNTCMD_WRITE_DATA (0x0400)
+#define ACE_SECCNTCMD_ABORT (0x0600)
+
+#define ACE_VERSION (0x16)
+#define ACE_VERSION_REVISION_MASK (0x00FF)
+#define ACE_VERSION_MINOR_MASK (0x0F00)
+#define ACE_VERSION_MAJOR_MASK (0xF000)
+
+#define ACE_CTRL (0x18)
+#define ACE_CTRL_FORCELOCKREQ (0x0001)
+#define ACE_CTRL_LOCKREQ (0x0002)
+#define ACE_CTRL_FORCECFGADDR (0x0004)
+#define ACE_CTRL_FORCECFGMODE (0x0008)
+#define ACE_CTRL_CFGMODE (0x0010)
+#define ACE_CTRL_CFGSTART (0x0020)
+#define ACE_CTRL_CFGSEL (0x0040)
+#define ACE_CTRL_CFGRESET (0x0080)
+#define ACE_CTRL_DATABUFRDYIRQ (0x0100)
+#define ACE_CTRL_ERRORIRQ (0x0200)
+#define ACE_CTRL_CFGDONEIRQ (0x0400)
+#define ACE_CTRL_RESETIRQ (0x0800)
+#define ACE_CTRL_CFGPROG (0x1000)
+#define ACE_CTRL_CFGADDR_MASK (0xe000)
+
+#define ACE_FATSTAT (0x1c)
+
+#define ACE_NUM_MINORS 16
+#define ACE_SECTOR_SIZE (512)
+#define ACE_FIFO_SIZE (32)
+#define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE)
+
+struct ace_reg_ops;
+
+struct ace_device {
+ /* driver state data */
+ int id;
+ int media_change;
+ int users;
+ struct list_head list;
+
+ /* finite state machine data */
+ struct tasklet_struct fsm_tasklet;
+ uint fsm_task; /* Current activity (ACE_TASK_*) */
+ uint fsm_state; /* Current state (ACE_FSM_STATE_*) */
+ uint fsm_continue_flag; /* cleared to exit FSM mainloop */
+ uint fsm_iter_num;
+ struct timer_list stall_timer;
+
+ /* Transfer state/result, use for both id and block request */
+ struct request *req; /* request being processed */
+ void *data_ptr; /* pointer to I/O buffer */
+ int data_count; /* number of buffers remaining */
+ int data_result; /* Result of transfer; 0 := success */
+
+ int id_req_count; /* count of id requests */
+ int id_result;
+ struct completion id_completion; /* used when id req finishes */
+ int in_irq;
+
+ /* Details of hardware device */
+ unsigned long physaddr;
+ void *baseaddr;
+ int irq;
+ int bus_width; /* 0 := 8 bit; 1 := 16 bit */
+ struct ace_reg_ops *reg_ops;
+ int lock_count;
+
+ /* Block device data structures */
+ spinlock_t lock;
+ struct device *dev;
+ struct request_queue *queue;
+ struct gendisk *gd;
+
+ /* Inserted CF card parameters */
+ struct hd_driveid cf_id;
+};
+
+static int ace_major;
+
+/* ---------------------------------------------------------------------
+ * Low level register access
+ */
+
+struct ace_reg_ops {
+ u16(*in) (struct ace_device * ace, int reg);
+ void (*out) (struct ace_device * ace, int reg, u16 val);
+ void (*datain) (struct ace_device * ace);
+ void (*dataout) (struct ace_device * ace);
+};
+
+/* 8 Bit bus width */
+static u16 ace_in_8(struct ace_device *ace, int reg)
+{
+ void *r = ace->baseaddr + reg;
+ return in_8(r) | (in_8(r + 1) << 8);
+}
+
+static void ace_out_8(struct ace_device *ace, int reg, u16 val)
+{
+ void *r = ace->baseaddr + reg;
+ out_8(r, val);
+ out_8(r + 1, val >> 8);
+}
+
+static void ace_datain_8(struct ace_device *ace)
+{
+ void *r = ace->baseaddr + 0x40;
+ u8 *dst = ace->data_ptr;
+ int i = ACE_FIFO_SIZE;
+ while (i--)
+ *dst++ = in_8(r++);
+ ace->data_ptr = dst;
+}
+
+static void ace_dataout_8(struct ace_device *ace)
+{
+ void *r = ace->baseaddr + 0x40;
+ u8 *src = ace->data_ptr;
+ int i = ACE_FIFO_SIZE;
+ while (i--)
+ out_8(r++, *src++);
+ ace->data_ptr = src;
+}
+
+static struct ace_reg_ops ace_reg_8_ops = {
+ .in = ace_in_8,
+ .out = ace_out_8,
+ .datain = ace_datain_8,
+ .dataout = ace_dataout_8,
+};
+
+/* 16 bit big endian bus attachment */
+static u16 ace_in_be16(struct ace_device *ace, int reg)
+{
+ return in_be16(ace->baseaddr + reg);
+}
+
+static void ace_out_be16(struct ace_device *ace, int reg, u16 val)
+{
+ out_be16(ace->baseaddr + reg, val);
+}
+
+static void ace_datain_be16(struct ace_device *ace)
+{
+ int i = ACE_FIFO_SIZE / 2;
+ u16 *dst = ace->data_ptr;
+ while (i--)
+ *dst++ = in_le16(ace->baseaddr + 0x40);
+ ace->data_ptr = dst;
+}
+
+static void ace_dataout_be16(struct ace_device *ace)
+{
+ int i = ACE_FIFO_SIZE / 2;
+ u16 *src = ace->data_ptr;
+ while (i--)
+ out_le16(ace->baseaddr + 0x40, *src++);
+ ace->data_ptr = src;
+}
+
+/* 16 bit little endian bus attachment */
+static u16 ace_in_le16(struct ace_device *ace, int reg)
+{
+ return in_le16(ace->baseaddr + reg);
+}
+
+static void ace_out_le16(struct ace_device *ace, int reg, u16 val)
+{
+ out_le16(ace->baseaddr + reg, val);
+}
+
+static void ace_datain_le16(struct ace_device *ace)
+{
+ int i = ACE_FIFO_SIZE / 2;
+ u16 *dst = ace->data_ptr;
+ while (i--)
+ *dst++ = in_be16(ace->baseaddr + 0x40);
+ ace->data_ptr = dst;
+}
+
+static void ace_dataout_le16(struct ace_device *ace)
+{
+ int i = ACE_FIFO_SIZE / 2;
+ u16 *src = ace->data_ptr;
+ while (i--)
+ out_be16(ace->baseaddr + 0x40, *src++);
+ ace->data_ptr = src;
+}
+
+static struct ace_reg_ops ace_reg_be16_ops = {
+ .in = ace_in_be16,
+ .out = ace_out_be16,
+ .datain = ace_datain_be16,
+ .dataout = ace_dataout_be16,
+};
+
+static struct ace_reg_ops ace_reg_le16_ops = {
+ .in = ace_in_le16,
+ .out = ace_out_le16,
+ .datain = ace_datain_le16,
+ .dataout = ace_dataout_le16,
+};
+
+static inline u16 ace_in(struct ace_device *ace, int reg)
+{
+ return ace->reg_ops->in(ace, reg);
+}
+
+static inline u32 ace_in32(struct ace_device *ace, int reg)
+{
+ return ace_in(ace, reg) | (ace_in(ace, reg + 2) << 16);
+}
+
+static inline void ace_out(struct ace_device *ace, int reg, u16 val)
+{
+ ace->reg_ops->out(ace, reg, val);
+}
+
+static inline void ace_out32(struct ace_device *ace, int reg, u32 val)
+{
+ ace_out(ace, reg, val);
+ ace_out(ace, reg + 2, val >> 16);
+}
+
+/* ---------------------------------------------------------------------
+ * Debug support functions
+ */
+
+#if defined(DEBUG)
+static void ace_dump_mem(void *base, int len)
+{
+ const char *ptr = base;
+ int i, j;
+
+ for (i = 0; i < len; i += 16) {
+ printk(KERN_INFO "%.8x:", i);
+ for (j = 0; j < 16; j++) {
+ if (!(j % 4))
+ printk(" ");
+ printk("%.2x", ptr[i + j]);
+ }
+ printk(" ");
+ for (j = 0; j < 16; j++)
+ printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
+ printk("\n");
+ }
+}
+#else
+static inline void ace_dump_mem(void *base, int len)
+{
+}
+#endif
+
+static void ace_dump_regs(struct ace_device *ace)
+{
+ dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n"
+ " status:%.8x mpu_lba:%.8x busmode:%4x\n"
+ " error: %.8x cfg_lba:%.8x fatstat:%.4x\n",
+ ace_in32(ace, ACE_CTRL),
+ ace_in(ace, ACE_SECCNTCMD),
+ ace_in(ace, ACE_VERSION),
+ ace_in32(ace, ACE_STATUS),
+ ace_in32(ace, ACE_MPULBA),
+ ace_in(ace, ACE_BUSMODE),
+ ace_in32(ace, ACE_ERROR),
+ ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT));
+}
+
+void ace_fix_driveid(struct hd_driveid *id)
+{
+#if defined(__BIG_ENDIAN)
+ u16 *buf = (void *)id;
+ int i;
+
+ /* All half words have wrong byte order; swap the bytes */
+ for (i = 0; i < sizeof(struct hd_driveid); i += 2, buf++)
+ *buf = le16_to_cpu(*buf);
+
+ /* Some of the data values are 32bit; swap the half words */
+ id->lba_capacity = ((id->lba_capacity >> 16) & 0x0000FFFF) |
+ ((id->lba_capacity << 16) & 0xFFFF0000);
+ id->spg = ((id->spg >> 16) & 0x0000FFFF) |
+ ((id->spg << 16) & 0xFFFF0000);
+#endif
+}
+
+/* ---------------------------------------------------------------------
+ * Finite State Machine (FSM) implementation
+ */
+
+/* FSM tasks; used to direct state transitions */
+#define ACE_TASK_IDLE 0
+#define ACE_TASK_IDENTIFY 1
+#define ACE_TASK_READ 2
+#define ACE_TASK_WRITE 3
+#define ACE_FSM_NUM_TASKS 4
+
+/* FSM state definitions */
+#define ACE_FSM_STATE_IDLE 0
+#define ACE_FSM_STATE_REQ_LOCK 1
+#define ACE_FSM_STATE_WAIT_LOCK 2
+#define ACE_FSM_STATE_WAIT_CFREADY 3
+#define ACE_FSM_STATE_IDENTIFY_PREPARE 4
+#define ACE_FSM_STATE_IDENTIFY_TRANSFER 5
+#define ACE_FSM_STATE_IDENTIFY_COMPLETE 6
+#define ACE_FSM_STATE_REQ_PREPARE 7
+#define ACE_FSM_STATE_REQ_TRANSFER 8
+#define ACE_FSM_STATE_REQ_COMPLETE 9
+#define ACE_FSM_STATE_ERROR 10
+#define ACE_FSM_NUM_STATES 11
+
+/* Set flag to exit FSM loop and reschedule tasklet */
+static inline void ace_fsm_yield(struct ace_device *ace)
+{
+ dev_dbg(ace->dev, "ace_fsm_yield()\n");
+ tasklet_schedule(&ace->fsm_tasklet);
+ ace->fsm_continue_flag = 0;
+}
+
+/* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
+static inline void ace_fsm_yieldirq(struct ace_device *ace)
+{
+ dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
+
+ if (ace->irq == NO_IRQ)
+ /* No IRQ assigned, so need to poll */
+ tasklet_schedule(&ace->fsm_tasklet);
+ ace->fsm_continue_flag = 0;
+}
+
+/* Get the next read/write request; ending requests that we don't handle */
+struct request *ace_get_next_request(request_queue_t * q)
+{
+ struct request *req;
+
+ while ((req = elv_next_request(q)) != NULL) {
+ if (blk_fs_request(req))
+ break;
+ end_request(req, 0);
+ }
+ return req;
+}
+
+static void ace_fsm_dostate(struct ace_device *ace)
+{
+ struct request *req;
+ u32 status;
+ u16 val;
+ int count;
+ int i;
+
+#if defined(DEBUG)
+ dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
+ ace->fsm_state, ace->id_req_count);
+#endif
+
+ switch (ace->fsm_state) {
+ case ACE_FSM_STATE_IDLE:
+ /* See if there is anything to do */
+ if (ace->id_req_count || ace_get_next_request(ace->queue)) {
+ ace->fsm_iter_num++;
+ ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
+ mod_timer(&ace->stall_timer, jiffies + HZ);
+ if (!timer_pending(&ace->stall_timer))
+ add_timer(&ace->stall_timer);
+ break;
+ }
+ del_timer(&ace->stall_timer);
+ ace->fsm_continue_flag = 0;
+ break;
+
+ case ACE_FSM_STATE_REQ_LOCK:
+ if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
+ /* Already have the lock, jump to next state */
+ ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
+ break;
+ }
+
+ /* Request the lock */
+ val = ace_in(ace, ACE_CTRL);
+ ace_out(ace, ACE_CTRL, val | ACE_CTRL_LOCKREQ);
+ ace->fsm_state = ACE_FSM_STATE_WAIT_LOCK;
+ break;
+
+ case ACE_FSM_STATE_WAIT_LOCK:
+ if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
+ /* got the lock; move to next state */
+ ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
+ break;
+ }
+
+ /* wait a bit for the lock */
+ ace_fsm_yield(ace);
+ break;
+
+ case ACE_FSM_STATE_WAIT_CFREADY:
+ status = ace_in32(ace, ACE_STATUS);
+ if (!(status & ACE_STATUS_RDYFORCFCMD) ||
+ (status & ACE_STATUS_CFBSY)) {
+ /* CF card isn't ready; it needs to be polled */
+ ace_fsm_yield(ace);
+ break;
+ }
+
+ /* Device is ready for command; determine what to do next */
+ if (ace->id_req_count)
+ ace->fsm_state = ACE_FSM_STATE_IDENTIFY_PREPARE;
+ else
+ ace->fsm_state = ACE_FSM_STATE_REQ_PREPARE;
+ break;
+
+ case ACE_FSM_STATE_IDENTIFY_PREPARE:
+ /* Send identify command */
+ ace->fsm_task = ACE_TASK_IDENTIFY;
+ ace->data_ptr = &ace->cf_id;
+ ace->data_count = ACE_BUF_PER_SECTOR;
+ ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY);
+
+ /* As per datasheet, put config controller in reset */
+ val = ace_in(ace, ACE_CTRL);
+ ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
+
+ /* irq handler takes over from this point; wait for the
+ * transfer to complete */
+ ace->fsm_state = ACE_FSM_STATE_IDENTIFY_TRANSFER;
+ ace_fsm_yieldirq(ace);
+ break;
+
+ case ACE_FSM_STATE_IDENTIFY_TRANSFER:
+ /* Check that the sysace is ready to receive data */
+ status = ace_in32(ace, ACE_STATUS);
+ if (status & ACE_STATUS_CFBSY) {
+ dev_dbg(ace->dev, "CFBSY set; t=%i iter=%i dc=%i\n",
+ ace->fsm_task, ace->fsm_iter_num,
+ ace->data_count);
+ ace_fsm_yield(ace);
+ break;
+ }
+ if (!(status & ACE_STATUS_DATABUFRDY)) {
+ ace_fsm_yield(ace);
+ break;
+ }
+
+ /* Transfer the next buffer */
+ ace->reg_ops->datain(ace);
+ ace->data_count--;
+
+ /* If there are still buffers to be transfers; jump out here */
+ if (ace->data_count != 0) {
+ ace_fsm_yieldirq(ace);
+ break;
+ }
+
+ /* transfer finished; kick state machine */
+ dev_dbg(ace->dev, "identify finished\n");
+ ace->fsm_state = ACE_FSM_STATE_IDENTIFY_COMPLETE;
+ break;
+
+ case ACE_FSM_STATE_IDENTIFY_COMPLETE:
+ ace_fix_driveid(&ace->cf_id);
+ ace_dump_mem(&ace->cf_id, 512); /* Debug: Dump out disk ID */
+
+ if (ace->data_result) {
+ /* Error occured, disable the disk */
+ ace->media_change = 1;
+ set_capacity(ace->gd, 0);
+ dev_err(ace->dev, "error fetching CF id (%i)\n",
+ ace->data_result);
+ } else {
+ ace->media_change = 0;
+
+ /* Record disk parameters */
+ set_capacity(ace->gd, ace->cf_id.lba_capacity);
+ dev_info(ace->dev, "capacity: %i sectors\n",
+ ace->cf_id.lba_capacity);
+ }
+
+ /* We're done, drop to IDLE state and notify waiters */
+ ace->fsm_state = ACE_FSM_STATE_IDLE;
+ ace->id_result = ace->data_result;
+ while (ace->id_req_count) {
+ complete(&ace->id_completion);
+ ace->id_req_count--;
+ }
+ break;
+
+ case ACE_FSM_STATE_REQ_PREPARE:
+ req = ace_get_next_request(ace->queue);
+ if (!req) {
+ ace->fsm_state = ACE_FSM_STATE_IDLE;
+ break;
+ }
+
+ /* Okay, it's a data request, set it up for transfer */
+ dev_dbg(ace->dev,
+ "request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n",
+ req->sector, req->hard_nr_sectors,
+ req->current_nr_sectors, rq_data_dir(req));
+
+ ace->req = req;
+ ace->data_ptr = req->buffer;
+ ace->data_count = req->current_nr_sectors * ACE_BUF_PER_SECTOR;
+ ace_out32(ace, ACE_MPULBA, req->sector & 0x0FFFFFFF);
+
+ count = req->hard_nr_sectors;
+ if (rq_data_dir(req)) {
+ /* Kick off write request */
+ dev_dbg(ace->dev, "write data\n");
+ ace->fsm_task = ACE_TASK_WRITE;
+ ace_out(ace, ACE_SECCNTCMD,
+ count | ACE_SECCNTCMD_WRITE_DATA);
+ } else {
+ /* Kick off read request */
+ dev_dbg(ace->dev, "read data\n");
+ ace->fsm_task = ACE_TASK_READ;
+ ace_out(ace, ACE_SECCNTCMD,
+ count | ACE_SECCNTCMD_READ_DATA);
+ }
+
+ /* As per datasheet, put config controller in reset */
+ val = ace_in(ace, ACE_CTRL);
+ ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
+
+ /* Move to the transfer state. The systemace will raise
+ * an interrupt once there is something to do
+ */
+ ace->fsm_state = ACE_FSM_STATE_REQ_TRANSFER;
+ if (ace->fsm_task == ACE_TASK_READ)
+ ace_fsm_yieldirq(ace); /* wait for data ready */
+ break;
+
+ case ACE_FSM_STATE_REQ_TRANSFER:
+ /* Check that the sysace is ready to receive data */
+ status = ace_in32(ace, ACE_STATUS);
+ if (status & ACE_STATUS_CFBSY) {
+ dev_dbg(ace->dev,
+ "CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n",
+ ace->fsm_task, ace->fsm_iter_num,
+ ace->req->current_nr_sectors * 16,
+ ace->data_count, ace->in_irq);
+ ace_fsm_yield(ace); /* need to poll CFBSY bit */
+ break;
+ }
+ if (!(status & ACE_STATUS_DATABUFRDY)) {
+ dev_dbg(ace->dev,
+ "DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n",
+ ace->fsm_task, ace->fsm_iter_num,
+ ace->req->current_nr_sectors * 16,
+ ace->data_count, ace->in_irq);
+ ace_fsm_yieldirq(ace);
+ break;
+ }
+
+ /* Transfer the next buffer */
+ i = 16;
+ if (ace->fsm_task == ACE_TASK_WRITE)
+ ace->reg_ops->dataout(ace);
+ else
+ ace->reg_ops->datain(ace);
+ ace->data_count--;
+
+ /* If there are still buffers to be transfers; jump out here */
+ if (ace->data_count != 0) {
+ ace_fsm_yieldirq(ace);
+ break;
+ }
+
+ /* bio finished; is there another one? */
+ i = ace->req->current_nr_sectors;
+ if (end_that_request_first(ace->req, 1, i)) {
+ /* dev_dbg(ace->dev, "next block; h=%li c=%i\n",
+ * ace->req->hard_nr_sectors,
+ * ace->req->current_nr_sectors);
+ */
+ ace->data_ptr = ace->req->buffer;
+ ace->data_count = ace->req->current_nr_sectors * 16;
+ ace_fsm_yieldirq(ace);
+ break;
+ }
+
+ ace->fsm_state = ACE_FSM_STATE_REQ_COMPLETE;
+ break;
+
+ case ACE_FSM_STATE_REQ_COMPLETE:
+ /* Complete the block request */
+ blkdev_dequeue_request(ace->req);
+ end_that_request_last(ace->req, 1);
+ ace->req = NULL;
+
+ /* Finished request; go to idle state */
+ ace->fsm_state = ACE_FSM_STATE_IDLE;
+ break;
+
+ default:
+ ace->fsm_state = ACE_FSM_STATE_IDLE;
+ break;
+ }
+}
+
+static void ace_fsm_tasklet(unsigned long data)
+{
+ struct ace_device *ace = (void *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ace->lock, flags);
+
+ /* Loop over state machine until told to stop */
+ ace->fsm_continue_flag = 1;
+ while (ace->fsm_continue_flag)
+ ace_fsm_dostate(ace);
+
+ spin_unlock_irqrestore(&ace->lock, flags);
+}
+
+static void ace_stall_timer(unsigned long data)
+{
+ struct ace_device *ace = (void *)data;
+ unsigned long flags;
+
+ dev_warn(ace->dev,
+ "kicking stalled fsm; state=%i task=%i iter=%i dc=%i\n",
+ ace->fsm_state, ace->fsm_task, ace->fsm_iter_num,
+ ace->data_count);
+ spin_lock_irqsave(&ace->lock, flags);
+
+ /* Rearm the stall timer *before* entering FSM (which may then
+ * delete the timer) */
+ mod_timer(&ace->stall_timer, jiffies + HZ);
+
+ /* Loop over state machine until told to stop */
+ ace->fsm_continue_flag = 1;
+ while (ace->fsm_continue_flag)
+ ace_fsm_dostate(ace);
+
+ spin_unlock_irqrestore(&ace->lock, flags);
+}
+
+/* ---------------------------------------------------------------------
+ * Interrupt handling routines
+ */
+static int ace_interrupt_checkstate(struct ace_device *ace)
+{
+ u32 sreg = ace_in32(ace, ACE_STATUS);
+ u16 creg = ace_in(ace, ACE_CTRL);
+
+ /* Check for error occurance */
+ if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) &&
+ (creg & ACE_CTRL_ERRORIRQ)) {
+ dev_err(ace->dev, "transfer failure\n");
+ ace_dump_regs(ace);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static irqreturn_t ace_interrupt(int irq, void *dev_id)
+{
+ u16 creg;
+ struct ace_device *ace = dev_id;
+
+ /* be safe and get the lock */
+ spin_lock(&ace->lock);
+ ace->in_irq = 1;
+
+ /* clear the interrupt */
+ creg = ace_in(ace, ACE_CTRL);
+ ace_out(ace, ACE_CTRL, creg | ACE_CTRL_RESETIRQ);
+ ace_out(ace, ACE_CTRL, creg);
+
+ /* check for IO failures */
+ if (ace_interrupt_checkstate(ace))
+ ace->data_result = -EIO;
+
+ if (ace->fsm_task == 0) {
+ dev_err(ace->dev,
+ "spurious irq; stat=%.8x ctrl=%.8x cmd=%.4x\n",
+ ace_in32(ace, ACE_STATUS), ace_in32(ace, ACE_CTRL),
+ ace_in(ace, ACE_SECCNTCMD));
+ dev_err(ace->dev, "fsm_task=%i fsm_state=%i data_count=%i\n",
+ ace->fsm_task, ace->fsm_state, ace->data_count);
+ }
+
+ /* Loop over state machine until told to stop */
+ ace->fsm_continue_flag = 1;
+ while (ace->fsm_continue_flag)
+ ace_fsm_dostate(ace);
+
+ /* done with interrupt; drop the lock */
+ ace->in_irq = 0;
+ spin_unlock(&ace->lock);
+
+ return IRQ_HANDLED;
+}
+
+/* ---------------------------------------------------------------------
+ * Block ops
+ */
+static void ace_request(request_queue_t * q)
+{
+ struct request *req;
+ struct ace_device *ace;
+
+ req = ace_get_next_request(q);
+
+ if (req) {
+ ace = req->rq_disk->private_data;
+ tasklet_schedule(&ace->fsm_tasklet);
+ }
+}
+
+static int ace_media_changed(struct gendisk *gd)
+{
+ struct ace_device *ace = gd->private_data;
+ dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change);
+
+ return ace->media_change;
+}
+
+static int ace_revalidate_disk(struct gendisk *gd)
+{
+ struct ace_device *ace = gd->private_data;
+ unsigned long flags;
+
+ dev_dbg(ace->dev, "ace_revalidate_disk()\n");
+
+ if (ace->media_change) {
+ dev_dbg(ace->dev, "requesting cf id and scheduling tasklet\n");
+
+ spin_lock_irqsave(&ace->lock, flags);
+ ace->id_req_count++;
+ spin_unlock_irqrestore(&ace->lock, flags);
+
+ tasklet_schedule(&ace->fsm_tasklet);
+ wait_for_completion(&ace->id_completion);
+ }
+
+ dev_dbg(ace->dev, "revalidate complete\n");
+ return ace->id_result;
+}
+
+static int ace_open(struct inode *inode, struct file *filp)
+{
+ struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+ unsigned long flags;
+
+ dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
+
+ filp->private_data = ace;
+ spin_lock_irqsave(&ace->lock, flags);
+ ace->users++;
+ spin_unlock_irqrestore(&ace->lock, flags);
+
+ check_disk_change(inode->i_bdev);
+ return 0;
+}
+
+static int ace_release(struct inode *inode, struct file *filp)
+{
+ struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+ unsigned long flags;
+ u16 val;
+
+ dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
+
+ spin_lock_irqsave(&ace->lock, flags);
+ ace->users--;
+ if (ace->users == 0) {
+ val = ace_in(ace, ACE_CTRL);
+ ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
+ }
+ spin_unlock_irqrestore(&ace->lock, flags);
+ return 0;
+}
+
+static int ace_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ace_device *ace = inode->i_bdev->bd_disk->private_data;
+ struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
+ struct hd_geometry g;
+ dev_dbg(ace->dev, "ace_ioctl()\n");
+
+ switch (cmd) {
+ case HDIO_GETGEO:
+ g.heads = ace->cf_id.heads;
+ g.sectors = ace->cf_id.sectors;
+ g.cylinders = ace->cf_id.cyls;
+ g.start = 0;
+ return copy_to_user(geo, &g, sizeof(g)) ? -EFAULT : 0;
+
+ default:
+ return -ENOTTY;
+ }
+ return -ENOTTY;
+}
+
+static struct block_device_operations ace_fops = {
+ .owner = THIS_MODULE,
+ .open = ace_open,
+ .release = ace_release,
+ .media_changed = ace_media_changed,
+ .revalidate_disk = ace_revalidate_disk,
+ .ioctl = ace_ioctl,
+};
+
+/* --------------------------------------------------------------------
+ * SystemACE device setup/teardown code
+ */
+static int __devinit ace_setup(struct ace_device *ace)
+{
+ u16 version;
+ u16 val;
+
+ int rc;
+
+ spin_lock_init(&ace->lock);
+ init_completion(&ace->id_completion);
+
+ /*
+ * Map the device
+ */
+ ace->baseaddr = ioremap(ace->physaddr, 0x80);
+ if (!ace->baseaddr)
+ goto err_ioremap;
+
+ if (ace->irq != NO_IRQ) {
+ rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
+ if (rc) {
+ /* Failure - fall back to polled mode */
+ dev_err(ace->dev, "request_irq failed\n");
+ ace->irq = NO_IRQ;
+ }
+ }
+
+ /*
+ * Initialize the state machine tasklet and stall timer
+ */
+ tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace);
+ setup_timer(&ace->stall_timer, ace_stall_timer, (unsigned long)ace);
+
+ /*
+ * Initialize the request queue
+ */
+ ace->queue = blk_init_queue(ace_request, &ace->lock);
+ if (ace->queue == NULL)
+ goto err_blk_initq;
+ blk_queue_hardsect_size(ace->queue, 512);
+
+ /*
+ * Allocate and initialize GD structure
+ */
+ ace->gd = alloc_disk(ACE_NUM_MINORS);
+ if (!ace->gd)
+ goto err_alloc_disk;
+
+ ace->gd->major = ace_major;
+ ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
+ ace->gd->fops = &ace_fops;
+ ace->gd->queue = ace->queue;
+ ace->gd->private_data = ace;
+ snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
+
+ /* set bus width */
+ if (ace->bus_width == 1) {
+ /* 0x0101 should work regardless of endianess */
+ ace_out_le16(ace, ACE_BUSMODE, 0x0101);
+
+ /* read it back to determine endianess */
+ if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001)
+ ace->reg_ops = &ace_reg_le16_ops;
+ else
+ ace->reg_ops = &ace_reg_be16_ops;
+ } else {
+ ace_out_8(ace, ACE_BUSMODE, 0x00);
+ ace->reg_ops = &ace_reg_8_ops;
+ }
+
+ /* Make sure version register is sane */
+ version = ace_in(ace, ACE_VERSION);
+ if ((version == 0) || (version == 0xFFFF))
+ goto err_read;
+
+ /* Put sysace in a sane state by clearing most control reg bits */
+ ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE |
+ ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
+
+ /* Enable interrupts */
+ val = ace_in(ace, ACE_CTRL);
+ val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
+ ace_out(ace, ACE_CTRL, val);
+
+ /* Print the identification */
+ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
+ (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
+ dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n",
+ ace->physaddr, ace->baseaddr, ace->irq);
+
+ ace->media_change = 1;
+ ace_revalidate_disk(ace->gd);
+
+ /* Make the sysace device 'live' */
+ add_disk(ace->gd);
+
+ return 0;
+
+ err_read:
+ put_disk(ace->gd);
+ err_alloc_disk:
+ blk_cleanup_queue(ace->queue);
+ err_blk_initq:
+ iounmap(ace->baseaddr);
+ if (ace->irq != NO_IRQ)
+ free_irq(ace->irq, ace);
+ err_ioremap:
+ printk(KERN_INFO "xsysace: error initializing device at 0x%lx\n",
+ ace->physaddr);
+ return -ENOMEM;
+}
+
+static void __devexit ace_teardown(struct ace_device *ace)
+{
+ if (ace->gd) {
+ del_gendisk(ace->gd);
+ put_disk(ace->gd);
+ }
+
+ if (ace->queue)
+ blk_cleanup_queue(ace->queue);
+
+ tasklet_kill(&ace->fsm_tasklet);
+
+ if (ace->irq != NO_IRQ)
+ free_irq(ace->irq, ace);
+
+ iounmap(ace->baseaddr);
+}
+
+/* ---------------------------------------------------------------------
+ * Platform Bus Support
+ */
+
+static int __devinit ace_probe(struct device *device)
+{
+ struct platform_device *dev = to_platform_device(device);
+ struct ace_device *ace;
+ int i;
+
+ dev_dbg(device, "ace_probe(%p)\n", device);
+
+ /*
+ * Allocate the ace device structure
+ */
+ ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
+ if (!ace)
+ goto err_alloc;
+
+ ace->dev = device;
+ ace->id = dev->id;
+ ace->irq = NO_IRQ;
+
+ for (i = 0; i < dev->num_resources; i++) {
+ if (dev->resource[i].flags & IORESOURCE_MEM)
+ ace->physaddr = dev->resource[i].start;
+ if (dev->resource[i].flags & IORESOURCE_IRQ)
+ ace->irq = dev->resource[i].start;
+ }
+
+ /* FIXME: Should get bus_width from the platform_device struct */
+ ace->bus_width = 1;
+
+ dev_set_drvdata(&dev->dev, ace);
+
+ /* Call the bus-independant setup code */
+ if (ace_setup(ace) != 0)
+ goto err_setup;
+
+ return 0;
+
+ err_setup:
+ dev_set_drvdata(&dev->dev, NULL);
+ kfree(ace);
+ err_alloc:
+ printk(KERN_ERR "xsysace: could not initialize device\n");
+ return -ENOMEM;
+}
+
+/*
+ * Platform bus remove() method
+ */
+static int __devexit ace_remove(struct device *device)
+{
+ struct ace_device *ace = dev_get_drvdata(device);
+
+ dev_dbg(device, "ace_remove(%p)\n", device);
+
+ if (ace) {
+ ace_teardown(ace);
+ kfree(ace);
+ }
+
+ return 0;
+}
+
+static struct device_driver ace_driver = {
+ .name = "xsysace",
+ .bus = &platform_bus_type,
+ .probe = ace_probe,
+ .remove = __devexit_p(ace_remove),
+};
+
+/* ---------------------------------------------------------------------
+ * Module init/exit routines
+ */
+static int __init ace_init(void)
+{
+ ace_major = register_blkdev(ace_major, "xsysace");
+ if (ace_major <= 0) {
+ printk(KERN_WARNING "xsysace: register_blkdev() failed\n");
+ return ace_major;
+ }
+
+ pr_debug("Registering Xilinx SystemACE driver, major=%i\n", ace_major);
+ return driver_register(&ace_driver);
+}
+
+static void __exit ace_exit(void)
+{
+ pr_debug("Unregistering Xilinx SystemACE driver\n");
+ driver_unregister(&ace_driver);
+ unregister_blkdev(ace_major, "xsysace");
+}
+
+module_init(ace_init);
+module_exit(ace_exit);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 7cc2685ca84a..e40fa98842e5 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -44,9 +44,6 @@
extern int m68k_realnum_memory;
extern struct mem_info m68k_memory[NUM_MEMINFO];
-#define TRUE (1)
-#define FALSE (0)
-
#define Z2MINOR_COMBINED (0)
#define Z2MINOR_Z2ONLY (1)
#define Z2MINOR_CHIPONLY (2)
@@ -374,9 +371,7 @@ static void __exit z2_exit(void)
{
int i, j;
blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
- if ( unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME ) != 0 )
- printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
-
+ unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
del_gendisk(z2ram_gendisk);
put_disk(z2ram_gendisk);
blk_cleanup_queue(z2_queue);
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index aa5468f487ba..499019bf8f40 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2695,11 +2695,12 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
{
void __user *argp = (void __user *)arg;
int ret;
+ struct gendisk *disk = ip->i_bdev->bd_disk;
/*
* Try the generic SCSI command ioctl's first.
*/
- ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
+ ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
if (ret != -ENOTTY)
return ret;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index f6648682b43a..d8d7125529c4 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -114,7 +114,7 @@ config COMPUTONE
config ROCKETPORT
tristate "Comtrol RocketPort support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
help
This driver supports Comtrol RocketPort and RocketModem PCI boards.
These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
@@ -157,7 +157,7 @@ config CYZ_INTR
config DIGIEPCA
tristate "Digiboard Intelligent Async Support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
---help---
This is a driver for Digi International's Xx, Xeve, and Xem series
of cards which provide multiple serial ports. You would need
@@ -213,8 +213,6 @@ config MOXA_SMARTIO_NEW
This is upgraded (1.9.1) driver from original Moxa drivers with
changes finally resulting in PCI probing.
- Use at your own risk.
-
This driver can also be built as a module. The module will be called
mxser_new. If you want to do that, say M here.
@@ -354,7 +352,7 @@ config STALDRV
config STALLION
tristate "Stallion EasyIO or EC8/32 support"
- depends on STALDRV && BROKEN_ON_SMP
+ depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
help
If you have an EasyIO or EasyConnection 8/32 multiport Stallion
card, then this is for you; say Y. Make sure to read
@@ -365,7 +363,7 @@ config STALLION
config ISTALLION
tristate "Stallion EC8/64, ONboard, Brumby support"
- depends on STALDRV && BROKEN_ON_SMP
+ depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
help
If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
serial multiport card, say Y here. Make sure to read
@@ -979,15 +977,14 @@ config GPIO_VR41XX
depends on CPU_VR41XX
config RAW_DRIVER
- tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+ tristate "RAW driver (/dev/raw/rawN)"
depends on BLOCK
help
- The raw driver permits block devices to be bound to /dev/raw/rawN.
- Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
+ The raw driver permits block devices to be bound to /dev/raw/rawN.
+ Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
See the raw(8) manpage for more details.
- The raw driver is deprecated and will be removed soon.
- Applications should simply open the device (eg /dev/hda1)
+ Applications should preferably open the device (eg /dev/hda1)
with the O_DIRECT flag.
config MAX_RAW_DEVS
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 2f56ecc035aa..f2996a95eb07 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -15,6 +15,7 @@ obj-y += misc.o
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \
consolemap_deftbl.o selection.o keyboard.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
+obj-$(CONFIG_AUDIT) += tty_audit.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_ESPSERIAL) += esp.o
obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 4eaceabd8cea..7b02bf1289a2 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -738,6 +738,7 @@ static void change_speed(struct async_struct *info,
}
/* If the quotient is zero refuse the change */
if (!quot && old_termios) {
+ /* FIXME: Will need updating for new tty in the end */
info->tty->termios->c_cflag &= ~CBAUD;
info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
baud = tty_get_baud_rate(info->tty);
@@ -783,7 +784,6 @@ static void change_speed(struct async_struct *info,
/*
* Set up parity check flag
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
if (I_INPCK(info->tty))
@@ -1367,11 +1367,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
unsigned long flags;
unsigned int cflag = tty->termios->c_cflag;
- if ( (cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_speed(info, old_termios);
/* Handle transition to B0 status */
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 179c7a3b6e75..ec116df919d9 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/apm-emulation.h>
+#include <linux/freezer.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -329,13 +330,8 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
/*
* Wait for the suspend/resume to complete. If there
* are pending acknowledges, we wait here for them.
- *
- * Note: we need to ensure that the PM subsystem does
- * not kick us out of the wait when it suspends the
- * threads.
*/
flags = current->flags;
- current->flags |= PF_NOFREEZE;
wait_event(apm_suspend_waitqueue,
as->suspend_state == SUSPEND_DONE);
@@ -365,13 +361,8 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
/*
* Wait for the suspend/resume to complete. If there
* are pending acknowledges, we wait here for them.
- *
- * Note: we need to ensure that the PM subsystem does
- * not kick us out of the wait when it suspends the
- * threads.
*/
flags = current->flags;
- current->flags |= PF_NOFREEZE;
wait_event_interruptible(apm_suspend_waitqueue,
as->suspend_state == SUSPEND_DONE);
@@ -598,7 +589,6 @@ static int __init apm_init(void)
kapmd_tsk = NULL;
return ret;
}
- kapmd_tsk->flags |= PF_NOFREEZE;
wake_up_process(kapmd_tsk);
#ifdef CONFIG_PROC_FS
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index ed53f541d9e8..b6f2639f903d 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -91,11 +91,6 @@ static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count
unsigned short c;
unsigned char cp;
-#if 0 /* Can't seek (pread) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
-#endif
-
if (!vfd_is_open)
return -ENODEV;
@@ -139,11 +134,6 @@ static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_
size_t indx = len;
int i, esc = 0;
-#if 0 /* Can't seek (pwrite) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
-#endif
-
if (!vfd_is_open)
return -EBUSY;
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index fd40b959afdd..4b3916f54909 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -177,6 +177,7 @@ struct uni_pagedir {
unsigned long refcount;
unsigned long sum;
unsigned char *inverse_translations[4];
+ u16 *inverse_trans_unicode;
int readonly;
};
@@ -207,6 +208,41 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
}
}
+static void set_inverse_trans_unicode(struct vc_data *conp,
+ struct uni_pagedir *p)
+{
+ int i, j, k, glyph;
+ u16 **p1, *p2;
+ u16 *q;
+
+ if (!p) return;
+ q = p->inverse_trans_unicode;
+ if (!q) {
+ q = p->inverse_trans_unicode =
+ kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
+ if (!q)
+ return;
+ }
+ memset(q, 0, MAX_GLYPH * sizeof(u16));
+
+ for (i = 0; i < 32; i++) {
+ p1 = p->uni_pgdir[i];
+ if (!p1)
+ continue;
+ for (j = 0; j < 32; j++) {
+ p2 = p1[j];
+ if (!p2)
+ continue;
+ for (k = 0; k < 64; k++) {
+ glyph = p2[k];
+ if (glyph >= 0 && glyph < MAX_GLYPH
+ && q[glyph] < 32)
+ q[glyph] = (i << 11) + (j << 6) + k;
+ }
+ }
+ }
+}
+
unsigned short *set_translate(int m, struct vc_data *vc)
{
inv_translate[vc->vc_num] = m;
@@ -217,19 +253,29 @@ unsigned short *set_translate(int m, struct vc_data *vc)
* Inverse translation is impossible for several reasons:
* 1. The font<->character maps are not 1-1.
* 2. The text may have been written while a different translation map
- * was active, or using Unicode.
+ * was active.
* Still, it is now possible to a certain extent to cut and paste non-ASCII.
*/
-unsigned char inverse_translate(struct vc_data *conp, int glyph)
+u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
{
struct uni_pagedir *p;
+ int m;
if (glyph < 0 || glyph >= MAX_GLYPH)
return 0;
- else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
- !p->inverse_translations[inv_translate[conp->vc_num]])
+ else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
return glyph;
- else
- return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
+ else if (use_unicode) {
+ if (!p->inverse_trans_unicode)
+ return glyph;
+ else
+ return p->inverse_trans_unicode[glyph];
+ } else {
+ m = inv_translate[conp->vc_num];
+ if (!p->inverse_translations[m])
+ return glyph;
+ else
+ return p->inverse_translations[m][glyph];
+ }
}
static void update_user_maps(void)
@@ -243,6 +289,7 @@ static void update_user_maps(void)
p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
if (p && p != q) {
set_inverse_transl(vc_cons[i].d, p, USER_MAP);
+ set_inverse_trans_unicode(vc_cons[i].d, p);
q = p;
}
}
@@ -353,6 +400,10 @@ static void con_release_unimap(struct uni_pagedir *p)
kfree(p->inverse_translations[i]);
p->inverse_translations[i] = NULL;
}
+ if (p->inverse_trans_unicode) {
+ kfree(p->inverse_trans_unicode);
+ p->inverse_trans_unicode = NULL;
+ }
}
void con_free_unimap(struct vc_data *vc)
@@ -511,6 +562,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
for (i = 0; i <= 3; i++)
set_inverse_transl(vc, p, i); /* Update all inverse translations */
+ set_inverse_trans_unicode(vc, p);
return err;
}
@@ -561,6 +613,7 @@ int con_set_default_unimap(struct vc_data *vc)
for (i = 0; i <= 3; i++)
set_inverse_transl(vc, p, i); /* Update all inverse translations */
+ set_inverse_trans_unicode(vc, p);
dflt = p;
return err;
}
@@ -617,6 +670,19 @@ void con_protect_unimap(struct vc_data *vc, int rdonly)
p->readonly = rdonly;
}
+/* may be called during an interrupt */
+u32 conv_8bit_to_uni(unsigned char c)
+{
+ /*
+ * Always use USER_MAP. This function is used by the keyboard,
+ * which shouldn't be affected by G0/G1 switching, etc.
+ * If the user map still contains default values, i.e. the
+ * direct-to-font mapping, then assume user is using Latin1.
+ */
+ unsigned short uni = translations[USER_MAP][c];
+ return uni == (0xf000 | c) ? c : uni;
+}
+
int
conv_uni_to_pc(struct vc_data *conp, long ucs)
{
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index ca376b92162c..9e0adfe27c12 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -646,6 +646,7 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
+#include <linux/firmware.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -680,6 +681,44 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
#define STD_COM_FLAGS (0)
+/* firmware stuff */
+#define ZL_MAX_BLOCKS 16
+#define DRIVER_VERSION 0x02010203
+#define RAM_SIZE 0x80000
+
+#define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0)
+
+enum zblock_type {
+ ZBLOCK_PRG = 0,
+ ZBLOCK_FPGA = 1
+};
+
+struct zfile_header {
+ char name[64];
+ char date[32];
+ char aux[32];
+ u32 n_config;
+ u32 config_offset;
+ u32 n_blocks;
+ u32 block_offset;
+ u32 reserved[9];
+} __attribute__ ((packed));
+
+struct zfile_config {
+ char name[64];
+ u32 mailbox;
+ u32 function;
+ u32 n_blocks;
+ u32 block_list[ZL_MAX_BLOCKS];
+} __attribute__ ((packed));
+
+struct zfile_block {
+ u32 type;
+ u32 file_offset;
+ u32 ram_offset;
+ u32 size;
+} __attribute__ ((packed));
+
static struct tty_driver *cy_serial_driver;
#ifdef CONFIG_ISA
@@ -1851,11 +1890,11 @@ static void cyz_poll(unsigned long arg)
struct cyclades_card *cinfo;
struct cyclades_port *info;
struct tty_struct *tty;
- static struct FIRM_ID *firm_id;
- static struct ZFW_CTRL *zfw_ctrl;
- static struct BOARD_CTRL *board_ctrl;
- static struct CH_CTRL *ch_ctrl;
- static struct BUF_CTRL *buf_ctrl;
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+ struct BUF_CTRL __iomem *buf_ctrl;
unsigned long expires = jiffies + HZ;
int card, port;
@@ -1999,7 +2038,6 @@ static int startup(struct cyclades_port *info)
struct ZFW_CTRL __iomem *zfw_ctrl;
struct BOARD_CTRL __iomem *board_ctrl;
struct CH_CTRL __iomem *ch_ctrl;
- int retval;
base_addr = card->base_addr;
@@ -2371,7 +2409,6 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
struct ZFW_CTRL __iomem *zfw_ctrl;
struct BOARD_CTRL __iomem *board_ctrl;
struct CH_CTRL __iomem *ch_ctrl;
- int retval;
base_addr = cinfo->base_addr;
firm_id = base_addr + ID_ADDRESS;
@@ -4127,10 +4164,6 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
#endif
- if (tty->termios->c_cflag == old_termios->c_cflag &&
- (tty->termios->c_iflag & (IXON | IXANY)) ==
- (old_termios->c_iflag & (IXON | IXANY)))
- return;
set_line_char(info);
if ((old_termios->c_cflag & CRTSCTS) &&
@@ -4433,10 +4466,10 @@ static void cy_hangup(struct tty_struct *tty)
static int __devinit cy_init_card(struct cyclades_card *cinfo)
{
struct cyclades_port *info;
- u32 mailbox;
+ u32 uninitialized_var(mailbox);
unsigned int nports;
unsigned short chip_number;
- int index, port;
+ int uninitialized_var(index), port;
spin_lock_init(&cinfo->card_lock);
@@ -4739,17 +4772,295 @@ static int __init cy_detect_isa(void)
} /* cy_detect_isa */
#ifdef CONFIG_PCI
-static void __devinit plx_init(void __iomem * addr, __u32 initctl)
+static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
+{
+ unsigned int a;
+
+ for (a = 0; a < size && *str; a++, str++)
+ if (*str & 0x80)
+ return -EINVAL;
+
+ for (; a < size; a++, str++)
+ if (*str)
+ return -EINVAL;
+
+ return 0;
+}
+
+static inline void __devinit cyz_fpga_copy(void __iomem *fpga, u8 *data,
+ unsigned int size)
+{
+ for (; size > 0; size--) {
+ cy_writel(fpga, *data++);
+ udelay(10);
+ }
+}
+
+static void __devinit plx_init(struct pci_dev *pdev, int irq,
+ struct RUNTIME_9060 __iomem *addr)
{
/* Reset PLX */
- cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000);
+ cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
udelay(100L);
- cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000);
+ cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
/* Reload Config. Registers from EEPROM */
- cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000);
+ cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
udelay(100L);
- cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000);
+ cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
+
+ /* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
+ * the IRQ is lost and, thus, we have to re-write it to the PCI config.
+ * registers. This will remain here until we find a permanent fix.
+ */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+}
+
+static int __devinit __cyz_load_fw(const struct firmware *fw,
+ const char *name, const u32 mailbox, void __iomem *base,
+ void __iomem *fpga)
+{
+ void *ptr = fw->data;
+ struct zfile_header *h = ptr;
+ struct zfile_config *c, *cs;
+ struct zfile_block *b, *bs;
+ unsigned int a, tmp, len = fw->size;
+#define BAD_FW KERN_ERR "Bad firmware: "
+ if (len < sizeof(*h)) {
+ printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
+ return -EINVAL;
+ }
+
+ cs = ptr + h->config_offset;
+ bs = ptr + h->block_offset;
+
+ if ((void *)(cs + h->n_config) > ptr + len ||
+ (void *)(bs + h->n_blocks) > ptr + len) {
+ printk(BAD_FW "too short");
+ return -EINVAL;
+ }
+
+ if (cyc_isfwstr(h->name, sizeof(h->name)) ||
+ cyc_isfwstr(h->date, sizeof(h->date))) {
+ printk(BAD_FW "bad formatted header string\n");
+ return -EINVAL;
+ }
+
+ if (strncmp(name, h->name, sizeof(h->name))) {
+ printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
+ return -EINVAL;
+ }
+
+ tmp = 0;
+ for (c = cs; c < cs + h->n_config; c++) {
+ for (a = 0; a < c->n_blocks; a++)
+ if (c->block_list[a] > h->n_blocks) {
+ printk(BAD_FW "bad block ref number in cfgs\n");
+ return -EINVAL;
+ }
+ if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
+ tmp++;
+ }
+ if (!tmp) {
+ printk(BAD_FW "nothing appropriate\n");
+ return -EINVAL;
+ }
+
+ for (b = bs; b < bs + h->n_blocks; b++)
+ if (b->file_offset + b->size > len) {
+ printk(BAD_FW "bad block data offset\n");
+ return -EINVAL;
+ }
+
+ /* everything is OK, let's seek'n'load it */
+ for (c = cs; c < cs + h->n_config; c++)
+ if (c->mailbox == mailbox && c->function == 0)
+ break;
+
+ for (a = 0; a < c->n_blocks; a++) {
+ b = &bs[c->block_list[a]];
+ if (b->type == ZBLOCK_FPGA) {
+ if (fpga != NULL)
+ cyz_fpga_copy(fpga, ptr + b->file_offset,
+ b->size);
+ } else {
+ if (base != NULL)
+ memcpy_toio(base + b->ram_offset,
+ ptr + b->file_offset, b->size);
+ }
+ }
+#undef BAD_FW
+ return 0;
+}
+
+static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+ struct RUNTIME_9060 __iomem *ctl_addr, int irq)
+{
+ const struct firmware *fw;
+ struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
+ struct CUSTOM_REG __iomem *cust = base_addr;
+ struct ZFW_CTRL __iomem *pt_zfwctrl;
+ void __iomem *tmp;
+ u32 mailbox, status;
+ unsigned int i;
+ int retval;
+
+ retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
+ if (retval) {
+ dev_err(&pdev->dev, "can't get firmware\n");
+ goto err;
+ }
+
+ /* Check whether the firmware is already loaded and running. If
+ positive, skip this board */
+ if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+ u32 cntval = readl(base_addr + 0x190);
+
+ udelay(100);
+ if (cntval != readl(base_addr + 0x190)) {
+ /* FW counter is working, FW is running */
+ dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
+ "Skipping board.\n");
+ retval = 0;
+ goto err_rel;
+ }
+ }
+
+ /* start boot */
+ cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
+ ~0x00030800UL);
+
+ mailbox = readl(&ctl_addr->mail_box_0);
+
+ if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
+ /* stops CPU and set window to beginning of RAM */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+ cy_writel(&cust->cpu_stop, 0);
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+ udelay(100);
+ }
+
+ plx_init(pdev, irq, ctl_addr);
+
+ if (mailbox != 0) {
+ /* load FPGA */
+ retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
+ base_addr);
+ if (retval)
+ goto err_rel;
+ if (!Z_FPGA_LOADED(ctl_addr)) {
+ dev_err(&pdev->dev, "fw upload successful, but fw is "
+ "not loaded\n");
+ goto err_rel;
+ }
+ }
+
+ /* stops CPU and set window to beginning of RAM */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+ cy_writel(&cust->cpu_stop, 0);
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+ udelay(100);
+
+ /* clear memory */
+ for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+ cy_writeb(tmp, 255);
+ if (mailbox != 0) {
+ /* set window to last 512K of RAM */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
+ //sleep(1);
+ for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+ cy_writeb(tmp, 255);
+ /* set window to beginning of RAM */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+ //sleep(1);
+ }
+
+ retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
+ release_firmware(fw);
+ if (retval)
+ goto err;
+
+ /* finish boot and start boards */
+ cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+ cy_writel(&cust->cpu_start, 0);
+ cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+ i = 0;
+ while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
+ msleep(100);
+ if (status != ZFIRM_ID) {
+ if (status == ZFIRM_HLT) {
+ dev_err(&pdev->dev, "you need an external power supply "
+ "for this number of ports. Firmware halted and "
+ "board reset.\n");
+ retval = -EIO;
+ goto err;
+ }
+ dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
+ "some more time\n", status);
+ while ((status = readl(&fid->signature)) != ZFIRM_ID &&
+ i++ < 200)
+ msleep(100);
+ if (status != ZFIRM_ID) {
+ dev_err(&pdev->dev, "Board not started in 20 seconds! "
+ "Giving up. (fid->signature = 0x%x)\n",
+ status);
+ dev_info(&pdev->dev, "*** Warning ***: if you are "
+ "upgrading the FW, please power cycle the "
+ "system before loading the new FW to the "
+ "Cyclades-Z.\n");
+
+ if (Z_FPGA_LOADED(ctl_addr))
+ plx_init(pdev, irq, ctl_addr);
+
+ retval = -EIO;
+ goto err;
+ }
+ dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
+ i / 10);
+ }
+ pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
+
+ dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
+ base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
+ base_addr + readl(&fid->zfwctrl_addr));
+
+ dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
+ readl(&pt_zfwctrl->board_ctrl.fw_version),
+ readl(&pt_zfwctrl->board_ctrl.n_channel));
+
+ if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
+ dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
+ "check the connection between the Z host card and the "
+ "serial expanders.\n");
+
+ if (Z_FPGA_LOADED(ctl_addr))
+ plx_init(pdev, irq, ctl_addr);
+
+ dev_info(&pdev->dev, "Null number of ports detected. Board "
+ "reset.\n");
+ retval = 0;
+ goto err;
+ }
+
+ cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
+ cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
+
+ /*
+ Early firmware failed to start looking for commands.
+ This enables firmware interrupts for those commands.
+ */
+ cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+ (1 << 17));
+ cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+ 0x00030800UL);
+
+ plx_init(pdev, irq, ctl_addr);
+
+ return 0;
+err_rel:
+ release_firmware(fw);
+err:
+ return retval;
}
static int __devinit cy_pci_probe(struct pci_dev *pdev,
@@ -4831,16 +5142,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
}
/* Disable interrupts on the PLX before resetting it */
- cy_writew(addr0 + 0x68,
- readw(addr0 + 0x68) & ~0x0900);
+ cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
- plx_init(addr0, 0x6c);
- /* For some yet unknown reason, once the PLX9060 reloads
- the EEPROM, the IRQ is lost and, thus, we have to
- re-write it to the PCI config. registers.
- This will remain here until we find a permanent
- fix. */
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+ plx_init(pdev, irq, addr0);
mailbox = (u32)readl(&ctl_addr->mail_box_0);
@@ -4881,6 +5185,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
cy_writel(addr2 + ID_ADDRESS, 0L);
+ retval = cyz_load_fw(pdev, addr2, addr0, irq);
+ if (retval)
+ goto err_unmap;
/* This must be a Cyclades-8Zo/PCI. The extendable
version will have a different device_id and will
be allocated its maximum number of ports. */
@@ -4957,15 +5264,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
case PLX_9060:
case PLX_9080:
default: /* Old boards, use PLX_9060 */
-
- plx_init(addr0, 0x6c);
- /* For some yet unknown reason, once the PLX9060 reloads
- the EEPROM, the IRQ is lost and, thus, we have to
- re-write it to the PCI config. registers.
- This will remain here until we find a permanent
- fix. */
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
-
+ plx_init(pdev, irq, addr0);
cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
break;
}
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 5b91bc04ea4e..3345641ff904 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -73,9 +73,9 @@ static void drm_ati_free_pcigart_table(void *address, int order)
free_pages((unsigned long)address, order);
}
-int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
{
- drm_sg_mem_t *entry = dev->sg;
+ struct drm_sg_mem *entry = dev->sg;
unsigned long pages;
int i;
int order;
@@ -122,9 +122,9 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
}
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
{
- drm_sg_mem_t *entry = dev->sg;
+ struct drm_sg_mem *entry = dev->sg;
void *address = NULL;
unsigned long pages;
u32 *pci_gart, page_base, bus_address = 0;
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 089198491f16..2d6f2d0bd02b 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -109,31 +109,31 @@ typedef unsigned int drm_magic_t;
* \note KW: Actually it's illegal to change either for
* backwards-compatibility reasons.
*/
-typedef struct drm_clip_rect {
+struct drm_clip_rect {
unsigned short x1;
unsigned short y1;
unsigned short x2;
unsigned short y2;
-} drm_clip_rect_t;
+};
/**
* Drawable information.
*/
-typedef struct drm_drawable_info {
+struct drm_drawable_info {
unsigned int num_rects;
- drm_clip_rect_t *rects;
-} drm_drawable_info_t;
+ struct drm_clip_rect *rects;
+};
/**
* Texture region,
*/
-typedef struct drm_tex_region {
+struct drm_tex_region {
unsigned char next;
unsigned char prev;
unsigned char in_use;
unsigned char padding;
unsigned int age;
-} drm_tex_region_t;
+};
/**
* Hardware lock.
@@ -142,17 +142,17 @@ typedef struct drm_tex_region {
* processor bus contention on a multiprocessor system, there should not be any
* other data stored in the same cache line.
*/
-typedef struct drm_hw_lock {
+struct drm_hw_lock {
__volatile__ unsigned int lock; /**< lock variable */
char padding[60]; /**< Pad to cache line */
-} drm_hw_lock_t;
+};
/**
* DRM_IOCTL_VERSION ioctl argument type.
*
* \sa drmGetVersion().
*/
-typedef struct drm_version {
+struct drm_version {
int version_major; /**< Major version */
int version_minor; /**< Minor version */
int version_patchlevel; /**< Patch level */
@@ -162,33 +162,33 @@ typedef struct drm_version {
char __user *date; /**< User-space buffer to hold date */
size_t desc_len; /**< Length of desc buffer */
char __user *desc; /**< User-space buffer to hold desc */
-} drm_version_t;
+};
/**
* DRM_IOCTL_GET_UNIQUE ioctl argument type.
*
* \sa drmGetBusid() and drmSetBusId().
*/
-typedef struct drm_unique {
+struct drm_unique {
size_t unique_len; /**< Length of unique */
char __user *unique; /**< Unique name for driver instantiation */
-} drm_unique_t;
+};
-typedef struct drm_list {
+struct drm_list {
int count; /**< Length of user-space structures */
- drm_version_t __user *version;
-} drm_list_t;
+ struct drm_version __user *version;
+};
-typedef struct drm_block {
+struct drm_block {
int unused;
-} drm_block_t;
+};
/**
* DRM_IOCTL_CONTROL ioctl argument type.
*
* \sa drmCtlInstHandler() and drmCtlUninstHandler().
*/
-typedef struct drm_control {
+struct drm_control {
enum {
DRM_ADD_COMMAND,
DRM_RM_COMMAND,
@@ -196,24 +196,24 @@ typedef struct drm_control {
DRM_UNINST_HANDLER
} func;
int irq;
-} drm_control_t;
+};
/**
* Type of memory to map.
*/
-typedef enum drm_map_type {
+enum drm_map_type {
_DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
_DRM_REGISTERS = 1, /**< no caching, no core dump */
_DRM_SHM = 2, /**< shared, cached */
_DRM_AGP = 3, /**< AGP/GART */
_DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
_DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
-} drm_map_type_t;
+};
/**
* Memory mapping flags.
*/
-typedef enum drm_map_flags {
+enum drm_map_flags {
_DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
_DRM_READ_ONLY = 0x02,
_DRM_LOCKED = 0x04, /**< shared, cached, locked */
@@ -221,12 +221,12 @@ typedef enum drm_map_flags {
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
_DRM_REMOVABLE = 0x40 /**< Removable mapping */
-} drm_map_flags_t;
+};
-typedef struct drm_ctx_priv_map {
+struct drm_ctx_priv_map {
unsigned int ctx_id; /**< Context requesting private mapping */
void *handle; /**< Handle of map */
-} drm_ctx_priv_map_t;
+};
/**
* DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
@@ -234,30 +234,30 @@ typedef struct drm_ctx_priv_map {
*
* \sa drmAddMap().
*/
-typedef struct drm_map {
+struct drm_map {
unsigned long offset; /**< Requested physical address (0 for SAREA)*/
unsigned long size; /**< Requested physical size (bytes) */
- drm_map_type_t type; /**< Type of memory to map */
- drm_map_flags_t flags; /**< Flags */
+ enum drm_map_type type; /**< Type of memory to map */
+ enum drm_map_flags flags; /**< Flags */
void *handle; /**< User-space: "Handle" to pass to mmap() */
/**< Kernel-space: kernel-virtual address */
int mtrr; /**< MTRR slot used */
/* Private data */
-} drm_map_t;
+};
/**
* DRM_IOCTL_GET_CLIENT ioctl argument type.
*/
-typedef struct drm_client {
+struct drm_client {
int idx; /**< Which client desired? */
int auth; /**< Is client authenticated? */
unsigned long pid; /**< Process ID */
unsigned long uid; /**< User ID */
unsigned long magic; /**< Magic */
unsigned long iocs; /**< Ioctl count */
-} drm_client_t;
+};
-typedef enum {
+enum drm_stat_type {
_DRM_STAT_LOCK,
_DRM_STAT_OPENS,
_DRM_STAT_CLOSES,
@@ -275,23 +275,23 @@ typedef enum {
_DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
_DRM_STAT_MISSED /**< Missed DMA opportunity */
/* Add to the *END* of the list */
-} drm_stat_type_t;
+};
/**
* DRM_IOCTL_GET_STATS ioctl argument type.
*/
-typedef struct drm_stats {
+struct drm_stats {
unsigned long count;
struct {
unsigned long value;
- drm_stat_type_t type;
+ enum drm_stat_type type;
} data[15];
-} drm_stats_t;
+};
/**
* Hardware locking flags.
*/
-typedef enum drm_lock_flags {
+enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
_DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
@@ -301,17 +301,17 @@ typedef enum drm_lock_flags {
full-screen DGA-like mode. */
_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
_DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
-} drm_lock_flags_t;
+};
/**
* DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
*
* \sa drmGetLock() and drmUnlock().
*/
-typedef struct drm_lock {
+struct drm_lock {
int context;
- drm_lock_flags_t flags;
-} drm_lock_t;
+ enum drm_lock_flags flags;
+};
/**
* DMA flags
@@ -321,7 +321,7 @@ typedef struct drm_lock {
*
* \sa drm_dma.
*/
-typedef enum drm_dma_flags {
+enum drm_dma_flags {
/* Flags for DMA buffer dispatch */
_DRM_DMA_BLOCK = 0x01, /**<
* Block until buffer dispatched.
@@ -340,14 +340,14 @@ typedef enum drm_dma_flags {
_DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
_DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
_DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
-} drm_dma_flags_t;
+};
/**
* DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
*
* \sa drmAddBufs().
*/
-typedef struct drm_buf_desc {
+struct drm_buf_desc {
int count; /**< Number of buffers of this size */
int size; /**< Size in bytes */
int low_mark; /**< Low water mark */
@@ -363,44 +363,44 @@ typedef struct drm_buf_desc {
* Start address of where the AGP buffers are
* in the AGP aperture
*/
-} drm_buf_desc_t;
+};
/**
* DRM_IOCTL_INFO_BUFS ioctl argument type.
*/
-typedef struct drm_buf_info {
+struct drm_buf_info {
int count; /**< Entries in list */
- drm_buf_desc_t __user *list;
-} drm_buf_info_t;
+ struct drm_buf_desc __user *list;
+};
/**
* DRM_IOCTL_FREE_BUFS ioctl argument type.
*/
-typedef struct drm_buf_free {
+struct drm_buf_free {
int count;
int __user *list;
-} drm_buf_free_t;
+};
/**
* Buffer information
*
* \sa drm_buf_map.
*/
-typedef struct drm_buf_pub {
+struct drm_buf_pub {
int idx; /**< Index into the master buffer list */
int total; /**< Buffer size */
int used; /**< Amount of buffer in use (for DMA) */
void __user *address; /**< Address of buffer */
-} drm_buf_pub_t;
+};
/**
* DRM_IOCTL_MAP_BUFS ioctl argument type.
*/
-typedef struct drm_buf_map {
+struct drm_buf_map {
int count; /**< Length of the buffer list */
void __user *virtual; /**< Mmap'd area in user-virtual */
- drm_buf_pub_t __user *list; /**< Buffer information */
-} drm_buf_map_t;
+ struct drm_buf_pub __user *list; /**< Buffer information */
+};
/**
* DRM_IOCTL_DMA ioctl argument type.
@@ -409,48 +409,48 @@ typedef struct drm_buf_map {
*
* \sa drmDMA().
*/
-typedef struct drm_dma {
+struct drm_dma {
int context; /**< Context handle */
int send_count; /**< Number of buffers to send */
int __user *send_indices; /**< List of handles to buffers */
int __user *send_sizes; /**< Lengths of data to send */
- drm_dma_flags_t flags; /**< Flags */
+ enum drm_dma_flags flags; /**< Flags */
int request_count; /**< Number of buffers requested */
int request_size; /**< Desired size for buffers */
int __user *request_indices; /**< Buffer information */
int __user *request_sizes;
int granted_count; /**< Number of buffers granted */
-} drm_dma_t;
+};
-typedef enum {
+enum drm_ctx_flags {
_DRM_CONTEXT_PRESERVED = 0x01,
_DRM_CONTEXT_2DONLY = 0x02
-} drm_ctx_flags_t;
+};
/**
* DRM_IOCTL_ADD_CTX ioctl argument type.
*
* \sa drmCreateContext() and drmDestroyContext().
*/
-typedef struct drm_ctx {
+struct drm_ctx {
drm_context_t handle;
- drm_ctx_flags_t flags;
-} drm_ctx_t;
+ enum drm_ctx_flags flags;
+};
/**
* DRM_IOCTL_RES_CTX ioctl argument type.
*/
-typedef struct drm_ctx_res {
+struct drm_ctx_res {
int count;
- drm_ctx_t __user *contexts;
-} drm_ctx_res_t;
+ struct drm_ctx __user *contexts;
+};
/**
* DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
*/
-typedef struct drm_draw {
+struct drm_draw {
drm_drawable_t handle;
-} drm_draw_t;
+};
/**
* DRM_IOCTL_UPDATE_DRAW ioctl argument type.
@@ -459,52 +459,52 @@ typedef enum {
DRM_DRAWABLE_CLIPRECTS,
} drm_drawable_info_type_t;
-typedef struct drm_update_draw {
+struct drm_update_draw {
drm_drawable_t handle;
unsigned int type;
unsigned int num;
unsigned long long data;
-} drm_update_draw_t;
+};
/**
* DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
*/
-typedef struct drm_auth {
+struct drm_auth {
drm_magic_t magic;
-} drm_auth_t;
+};
/**
* DRM_IOCTL_IRQ_BUSID ioctl argument type.
*
* \sa drmGetInterruptFromBusID().
*/
-typedef struct drm_irq_busid {
+struct drm_irq_busid {
int irq; /**< IRQ number */
int busnum; /**< bus number */
int devnum; /**< device number */
int funcnum; /**< function number */
-} drm_irq_busid_t;
+};
-typedef enum {
+enum drm_vblank_seq_type {
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
_DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
_DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
-} drm_vblank_seq_type_t;
+};
#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
_DRM_VBLANK_NEXTONMISS)
struct drm_wait_vblank_request {
- drm_vblank_seq_type_t type;
+ enum drm_vblank_seq_type type;
unsigned int sequence;
unsigned long signal;
};
struct drm_wait_vblank_reply {
- drm_vblank_seq_type_t type;
+ enum drm_vblank_seq_type type;
unsigned int sequence;
long tval_sec;
long tval_usec;
@@ -515,41 +515,41 @@ struct drm_wait_vblank_reply {
*
* \sa drmWaitVBlank().
*/
-typedef union drm_wait_vblank {
+union drm_wait_vblank {
struct drm_wait_vblank_request request;
struct drm_wait_vblank_reply reply;
-} drm_wait_vblank_t;
+};
/**
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
*
* \sa drmAgpEnable().
*/
-typedef struct drm_agp_mode {
+struct drm_agp_mode {
unsigned long mode; /**< AGP mode */
-} drm_agp_mode_t;
+};
/**
* DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
*
* \sa drmAgpAlloc() and drmAgpFree().
*/
-typedef struct drm_agp_buffer {
+struct drm_agp_buffer {
unsigned long size; /**< In bytes -- will round to page boundary */
unsigned long handle; /**< Used for binding / unbinding */
unsigned long type; /**< Type of memory to allocate */
unsigned long physical; /**< Physical used by i810 */
-} drm_agp_buffer_t;
+};
/**
* DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
*
* \sa drmAgpBind() and drmAgpUnbind().
*/
-typedef struct drm_agp_binding {
+struct drm_agp_binding {
unsigned long handle; /**< From drm_agp_buffer */
unsigned long offset; /**< In bytes -- will round to page boundary */
-} drm_agp_binding_t;
+};
/**
* DRM_IOCTL_AGP_INFO ioctl argument type.
@@ -558,7 +558,7 @@ typedef struct drm_agp_binding {
* drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
* drmAgpVendorId() and drmAgpDeviceId().
*/
-typedef struct drm_agp_info {
+struct drm_agp_info {
int agp_version_major;
int agp_version_minor;
unsigned long mode;
@@ -570,25 +570,25 @@ typedef struct drm_agp_info {
/* PCI information */
unsigned short id_vendor;
unsigned short id_device;
-} drm_agp_info_t;
+};
/**
* DRM_IOCTL_SG_ALLOC ioctl argument type.
*/
-typedef struct drm_scatter_gather {
+struct drm_scatter_gather {
unsigned long size; /**< In bytes -- will round to page boundary */
unsigned long handle; /**< Used for mapping / unmapping */
-} drm_scatter_gather_t;
+};
/**
* DRM_IOCTL_SET_VERSION ioctl argument type.
*/
-typedef struct drm_set_version {
+struct drm_set_version {
int drm_di_major;
int drm_di_minor;
int drm_dd_major;
int drm_dd_minor;
-} drm_set_version_t;
+};
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
@@ -596,61 +596,61 @@ typedef struct drm_set_version {
#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
-#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t)
-#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
-#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
-#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
-#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
-#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
-#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
-#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t)
-
-#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
-#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
-#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t)
-#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t)
-#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t)
-#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t)
-#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t)
-#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t)
-#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t)
-#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t)
-#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t)
-
-#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, drm_map_t)
-
-#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, drm_ctx_priv_map_t)
-#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, drm_ctx_priv_map_t)
-
-#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t)
-#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t)
-#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t)
-#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t)
-#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
-#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t)
-#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t)
-#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t)
-#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t)
-#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t)
-#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t)
-#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t)
-#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t)
+#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version)
+#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique)
+#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth)
+#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid)
+#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map)
+#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
+#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
+#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
+
+#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
+#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
+#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block)
+#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block)
+#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control)
+#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map)
+#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc)
+#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc)
+#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info)
+#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map)
+#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free)
+
+#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map)
+
+#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
+#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
+
+#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
+#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
+#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
+#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx)
+#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx)
+#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx)
+#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res)
+#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw)
+#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw)
+#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma)
+#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock)
+#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
+#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
-#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t)
-#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t)
-#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
-#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode)
+#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info)
+#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding)
+#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding)
-#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
-#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather)
-#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
+#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
-#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t)
+#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
/**
* Device specific ioctls should only be in their respective headers
@@ -663,4 +663,49 @@ typedef struct drm_set_version {
#define DRM_COMMAND_BASE 0x40
#define DRM_COMMAND_END 0xA0
+/* typedef area */
+#ifndef __KERNEL__
+typedef struct drm_clip_rect drm_clip_rect_t;
+typedef struct drm_drawable_info drm_drawable_info_t;
+typedef struct drm_tex_region drm_tex_region_t;
+typedef struct drm_hw_lock drm_hw_lock_t;
+typedef struct drm_version drm_version_t;
+typedef struct drm_unique drm_unique_t;
+typedef struct drm_list drm_list_t;
+typedef struct drm_block drm_block_t;
+typedef struct drm_control drm_control_t;
+typedef enum drm_map_type drm_map_type_t;
+typedef enum drm_map_flags drm_map_flags_t;
+typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
+typedef struct drm_map drm_map_t;
+typedef struct drm_client drm_client_t;
+typedef enum drm_stat_type drm_stat_type_t;
+typedef struct drm_stats drm_stats_t;
+typedef enum drm_lock_flags drm_lock_flags_t;
+typedef struct drm_lock drm_lock_t;
+typedef enum drm_dma_flags drm_dma_flags_t;
+typedef struct drm_buf_desc drm_buf_desc_t;
+typedef struct drm_buf_info drm_buf_info_t;
+typedef struct drm_buf_free drm_buf_free_t;
+typedef struct drm_buf_pub drm_buf_pub_t;
+typedef struct drm_buf_map drm_buf_map_t;
+typedef struct drm_dma drm_dma_t;
+typedef union drm_wait_vblank drm_wait_vblank_t;
+typedef struct drm_agp_mode drm_agp_mode_t;
+typedef enum drm_ctx_flags drm_ctx_flags_t;
+typedef struct drm_ctx drm_ctx_t;
+typedef struct drm_ctx_res drm_ctx_res_t;
+typedef struct drm_draw drm_draw_t;
+typedef struct drm_update_draw drm_update_draw_t;
+typedef struct drm_auth drm_auth_t;
+typedef struct drm_irq_busid drm_irq_busid_t;
+typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
+
+typedef struct drm_agp_buffer drm_agp_buffer_t;
+typedef struct drm_agp_binding drm_agp_binding_t;
+typedef struct drm_agp_info drm_agp_info_t;
+typedef struct drm_scatter_gather drm_scatter_gather_t;
+typedef struct drm_set_version drm_set_version_t;
+#endif
+
#endif
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index d494315752a2..0df87fc3dcb2 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -75,6 +75,8 @@
#include <asm/pgalloc.h>
#include "drm.h"
+#include <linux/idr.h>
+
#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
@@ -274,32 +276,23 @@ typedef struct drm_ioctl_desc {
int flags;
} drm_ioctl_desc_t;
-typedef struct drm_devstate {
- pid_t owner; /**< X server pid holding x_lock */
-} drm_devstate_t;
-
-typedef struct drm_magic_entry {
- drm_hash_item_t hash_item;
+struct drm_magic_entry {
struct list_head head;
+ struct drm_hash_item hash_item;
struct drm_file *priv;
struct drm_magic_entry *next;
-} drm_magic_entry_t;
-
-typedef struct drm_magic_head {
- struct drm_magic_entry *head;
- struct drm_magic_entry *tail;
-} drm_magic_head_t;
+};
-typedef struct drm_vma_entry {
+struct drm_vma_entry {
+ struct list_head head;
struct vm_area_struct *vma;
- struct drm_vma_entry *next;
pid_t pid;
-} drm_vma_entry_t;
+};
/**
* DMA buffer.
*/
-typedef struct drm_buf {
+struct drm_buf {
int idx; /**< Index into master buflist */
int total; /**< Buffer size */
int order; /**< log-base-2(total) */
@@ -325,30 +318,30 @@ typedef struct drm_buf {
int dev_priv_size; /**< Size of buffer private storage */
void *dev_private; /**< Per-buffer private storage */
-} drm_buf_t;
+};
/** bufs is one longer than it has to be */
-typedef struct drm_waitlist {
+struct drm_waitlist {
int count; /**< Number of possible buffers */
- drm_buf_t **bufs; /**< List of pointers to buffers */
- drm_buf_t **rp; /**< Read pointer */
- drm_buf_t **wp; /**< Write pointer */
- drm_buf_t **end; /**< End pointer */
+ struct drm_buf **bufs; /**< List of pointers to buffers */
+ struct drm_buf **rp; /**< Read pointer */
+ struct drm_buf **wp; /**< Write pointer */
+ struct drm_buf **end; /**< End pointer */
spinlock_t read_lock;
spinlock_t write_lock;
-} drm_waitlist_t;
+};
-typedef struct drm_freelist {
+struct drm_freelist {
int initialized; /**< Freelist in use */
atomic_t count; /**< Number of free buffers */
- drm_buf_t *next; /**< End pointer */
+ struct drm_buf *next; /**< End pointer */
wait_queue_head_t waiting; /**< Processes waiting on free bufs */
int low_mark; /**< Low water mark */
int high_mark; /**< High water mark */
atomic_t wfh; /**< If waiting for high mark */
spinlock_t lock;
-} drm_freelist_t;
+};
typedef struct drm_dma_handle {
dma_addr_t busaddr;
@@ -359,19 +352,19 @@ typedef struct drm_dma_handle {
/**
* Buffer entry. There is one of this for each buffer size order.
*/
-typedef struct drm_buf_entry {
+struct drm_buf_entry {
int buf_size; /**< size */
int buf_count; /**< number of buffers */
- drm_buf_t *buflist; /**< buffer list */
+ struct drm_buf *buflist; /**< buffer list */
int seg_count;
int page_order;
- drm_dma_handle_t **seglist;
+ struct drm_dma_handle **seglist;
- drm_freelist_t freelist;
-} drm_buf_entry_t;
+ struct drm_freelist freelist;
+};
/** File private data */
-typedef struct drm_file {
+struct drm_file {
int authenticated;
int master;
int minor;
@@ -379,16 +372,15 @@ typedef struct drm_file {
uid_t uid;
drm_magic_t magic;
unsigned long ioctl_count;
- struct drm_file *next;
- struct drm_file *prev;
+ struct list_head lhead;
struct drm_head *head;
int remove_auth_on_close;
unsigned long lock_count;
void *driver_priv;
-} drm_file_t;
+};
/** Wait queue */
-typedef struct drm_queue {
+struct drm_queue {
atomic_t use_count; /**< Outstanding uses (+1) */
atomic_t finalization; /**< Finalization in progress */
atomic_t block_count; /**< Count of processes waiting */
@@ -401,16 +393,16 @@ typedef struct drm_queue {
atomic_t total_flushed; /**< Total flushes statistic */
atomic_t total_locks; /**< Total locks statistics */
#endif
- drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
- drm_waitlist_t waitlist; /**< Pending buffers */
+ enum drm_ctx_flags flags; /**< Context preserving and 2D-only */
+ struct drm_waitlist waitlist; /**< Pending buffers */
wait_queue_head_t flush_queue; /**< Processes waiting until flush */
-} drm_queue_t;
+};
/**
* Lock data.
*/
-typedef struct drm_lock_data {
- drm_hw_lock_t *hw_lock; /**< Hardware lock */
+struct drm_lock_data {
+ struct drm_hw_lock *hw_lock; /**< Hardware lock */
struct file *filp; /**< File descr of lock holder (0=kernel) */
wait_queue_head_t lock_queue; /**< Queue of blocked processes */
unsigned long lock_time; /**< Time of last lock in jiffies */
@@ -418,16 +410,16 @@ typedef struct drm_lock_data {
uint32_t kernel_waiters;
uint32_t user_waiters;
int idle_has_lock;
-} drm_lock_data_t;
+};
/**
* DMA data.
*/
-typedef struct drm_device_dma {
+struct drm_device_dma {
- drm_buf_entry_t bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
+ struct drm_buf_entry bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
int buf_count; /**< total number of buffers */
- drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
+ struct drm_buf **buflist; /**< Vector of pointers into drm_device_dma::bufs */
int seg_count;
int page_count; /**< number of pages */
unsigned long *pagelist; /**< page list */
@@ -439,28 +431,27 @@ typedef struct drm_device_dma {
_DRM_DMA_USE_PCI_RO = 0x08
} flags;
-} drm_device_dma_t;
+};
/**
* AGP memory entry. Stored as a doubly linked list.
*/
-typedef struct drm_agp_mem {
+struct drm_agp_mem {
unsigned long handle; /**< handle */
DRM_AGP_MEM *memory;
unsigned long bound; /**< address */
int pages;
- struct drm_agp_mem *prev; /**< previous entry */
- struct drm_agp_mem *next; /**< next entry */
-} drm_agp_mem_t;
+ struct list_head head;
+};
/**
* AGP data.
*
* \sa drm_agp_init() and drm_device::agp.
*/
-typedef struct drm_agp_head {
+struct drm_agp_head {
DRM_AGP_KERN agp_info; /**< AGP device information */
- drm_agp_mem_t *memory; /**< memory entries */
+ struct list_head memory;
unsigned long mode; /**< AGP mode */
struct agp_bridge_data *bridge;
int enabled; /**< whether the AGP bus as been enabled */
@@ -469,51 +460,51 @@ typedef struct drm_agp_head {
int agp_mtrr;
int cant_use_aperture;
unsigned long page_mask;
-} drm_agp_head_t;
+};
/**
* Scatter-gather memory.
*/
-typedef struct drm_sg_mem {
+struct drm_sg_mem {
unsigned long handle;
void *virtual;
int pages;
struct page **pagelist;
dma_addr_t *busaddr;
-} drm_sg_mem_t;
+};
-typedef struct drm_sigdata {
+struct drm_sigdata {
int context;
- drm_hw_lock_t *lock;
-} drm_sigdata_t;
+ struct drm_hw_lock *lock;
+};
/**
* Mappings list
*/
-typedef struct drm_map_list {
+struct drm_map_list {
struct list_head head; /**< list head */
- drm_hash_item_t hash;
- drm_map_t *map; /**< mapping */
+ struct drm_hash_item hash;
+ struct drm_map *map; /**< mapping */
unsigned int user_token;
-} drm_map_list_t;
+};
-typedef drm_map_t drm_local_map_t;
+typedef struct drm_map drm_local_map_t;
/**
* Context handle list
*/
-typedef struct drm_ctx_list {
+struct drm_ctx_list {
struct list_head head; /**< list head */
drm_context_t handle; /**< context handle */
- drm_file_t *tag; /**< associated fd private data */
-} drm_ctx_list_t;
+ struct drm_file *tag; /**< associated fd private data */
+};
-typedef struct drm_vbl_sig {
+struct drm_vbl_sig {
struct list_head head;
unsigned int sequence;
struct siginfo info;
struct task_struct *task;
-} drm_vbl_sig_t;
+};
/* location of GART table */
#define DRM_ATI_GART_MAIN 1
@@ -523,19 +514,19 @@ typedef struct drm_vbl_sig {
#define DRM_ATI_GART_PCIE 2
#define DRM_ATI_GART_IGP 3
-typedef struct ati_pcigart_info {
+struct drm_ati_pcigart_info {
int gart_table_location;
int gart_reg_if;
void *addr;
dma_addr_t bus_addr;
drm_local_map_t mapping;
int table_size;
-} drm_ati_pcigart_info;
+};
/*
* Generic memory manager structs
*/
-typedef struct drm_mm_node {
+struct drm_mm_node {
struct list_head fl_entry;
struct list_head ml_entry;
int free;
@@ -543,12 +534,12 @@ typedef struct drm_mm_node {
unsigned long size;
struct drm_mm *mm;
void *private;
-} drm_mm_node_t;
+};
-typedef struct drm_mm {
+struct drm_mm {
struct list_head fl_entry;
struct list_head ml_entry;
-} drm_mm_t;
+};
/**
* DRM driver structure. This structure represent the common code for
@@ -560,21 +551,21 @@ struct drm_device;
struct drm_driver {
int (*load) (struct drm_device *, unsigned long flags);
int (*firstopen) (struct drm_device *);
- int (*open) (struct drm_device *, drm_file_t *);
+ int (*open) (struct drm_device *, struct drm_file *);
void (*preclose) (struct drm_device *, struct file * filp);
- void (*postclose) (struct drm_device *, drm_file_t *);
+ void (*postclose) (struct drm_device *, struct drm_file *);
void (*lastclose) (struct drm_device *);
int (*unload) (struct drm_device *);
int (*dma_ioctl) (DRM_IOCTL_ARGS);
void (*dma_ready) (struct drm_device *);
int (*dma_quiescent) (struct drm_device *);
- int (*context_ctor) (struct drm_device * dev, int context);
- int (*context_dtor) (struct drm_device * dev, int context);
- int (*kernel_context_switch) (struct drm_device * dev, int old,
+ int (*context_ctor) (struct drm_device *dev, int context);
+ int (*context_dtor) (struct drm_device *dev, int context);
+ int (*kernel_context_switch) (struct drm_device *dev, int old,
int new);
- void (*kernel_context_switch_unlock) (struct drm_device * dev);
- int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
- int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
+ void (*kernel_context_switch_unlock) (struct drm_device *dev);
+ int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
+ int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
int (*dri_library_name) (struct drm_device *dev, char *buf);
/**
@@ -588,22 +579,23 @@ struct drm_driver {
* card is absolutely \b not AGP (return of 0), absolutely \b is AGP
* (return of 1), or may or may not be AGP (return of 2).
*/
- int (*device_is_agp) (struct drm_device * dev);
+ int (*device_is_agp) (struct drm_device *dev);
/* these have to be filled in */
irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
- void (*irq_preinstall) (struct drm_device * dev);
- void (*irq_postinstall) (struct drm_device * dev);
- void (*irq_uninstall) (struct drm_device * dev);
- void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
+ void (*irq_preinstall) (struct drm_device *dev);
+ void (*irq_postinstall) (struct drm_device *dev);
+ void (*irq_uninstall) (struct drm_device *dev);
+ void (*reclaim_buffers) (struct drm_device *dev, struct file * filp);
void (*reclaim_buffers_locked) (struct drm_device *dev,
struct file *filp);
void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
struct file * filp);
- unsigned long (*get_map_ofs) (drm_map_t * map);
- unsigned long (*get_reg_ofs) (struct drm_device * dev);
- void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
+ unsigned long (*get_map_ofs) (struct drm_map * map);
+ unsigned long (*get_reg_ofs) (struct drm_device *dev);
+ void (*set_version) (struct drm_device *dev,
+ struct drm_set_version *sv);
int major;
int minor;
@@ -625,19 +617,19 @@ struct drm_driver {
* that may contain multiple heads. Embed one per head of these in the
* private drm_device structure.
*/
-typedef struct drm_head {
+struct drm_head {
int minor; /**< Minor device number */
struct drm_device *dev;
struct proc_dir_entry *dev_root; /**< proc directory entry */
dev_t device; /**< Device number for mknod */
struct class_device *dev_class;
-} drm_head_t;
+};
/**
* DRM device structure. This structure represent a complete card that
* may contain multiple heads.
*/
-typedef struct drm_device {
+struct drm_device {
char *unique; /**< Unique identifier: e.g., busid */
int unique_len; /**< Length of unique field */
char *devname; /**< For /proc/interrupts */
@@ -663,35 +655,33 @@ typedef struct drm_device {
/** \name Performance counters */
/*@{ */
unsigned long counters;
- drm_stat_type_t types[15];
+ enum drm_stat_type types[15];
atomic_t counts[15];
/*@} */
/** \name Authentication */
/*@{ */
- drm_file_t *file_first; /**< file list head */
- drm_file_t *file_last; /**< file list tail */
- drm_open_hash_t magiclist; /**< magic hash table */
+ struct list_head filelist;
+ struct drm_open_hash magiclist; /**< magic hash table */
struct list_head magicfree;
/*@} */
/** \name Memory management */
/*@{ */
- drm_map_list_t *maplist; /**< Linked list of regions */
+ struct list_head maplist; /**< Linked list of regions */
int map_count; /**< Number of mappable regions */
- drm_open_hash_t map_hash; /**< User token hash table for maps */
+ struct drm_open_hash map_hash; /**< User token hash table for maps */
/** \name Context handle management */
/*@{ */
- drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
+ struct list_head ctxlist; /**< Linked list of context handles */
int ctx_count; /**< Number of context handles */
struct mutex ctxlist_mutex; /**< For ctxlist */
- drm_map_t **context_sareas; /**< per-context SAREA's */
- int max_context;
+ struct idr ctx_idr;
- drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
- drm_lock_data_t lock; /**< Information on hardware lock */
+ struct list_head vmalist; /**< List of vmas (for debugging) */
+ struct drm_lock_data lock; /**< Information on hardware lock */
/*@} */
/** \name DMA queues (contexts) */
@@ -699,8 +689,8 @@ typedef struct drm_device {
int queue_count; /**< Number of active DMA queues */
int queue_reserved; /**< Number of reserved DMA queues */
int queue_slots; /**< Actual length of queuelist */
- drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
- drm_device_dma_t *dma; /**< Optional pointer for DMA support */
+ struct drm_queue **queuelist; /**< Vector of pointers to DMA queues */
+ struct drm_device_dma *dma; /**< Optional pointer for DMA support */
/*@} */
/** \name Context support */
@@ -725,8 +715,8 @@ typedef struct drm_device {
atomic_t vbl_received;
atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
spinlock_t vbl_lock;
- drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
- drm_vbl_sig_t vbl_sigs2; /**< signals to send on secondary VBLANK */
+ struct list_head vbl_sigs; /**< signal list to send on VBLANK */
+ struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
unsigned int vbl_pending;
spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
void (*locked_tasklet_func)(struct drm_device *dev);
@@ -739,7 +729,7 @@ typedef struct drm_device {
wait_queue_head_t buf_readers; /**< Processes waiting to read */
wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
- drm_agp_head_t *agp; /**< AGP data */
+ struct drm_agp_head *agp; /**< AGP data */
struct pci_dev *pdev; /**< PCI device structure */
int pci_vendor; /**< PCI vendor id */
@@ -747,26 +737,23 @@ typedef struct drm_device {
#ifdef __alpha__
struct pci_controller *hose;
#endif
- drm_sg_mem_t *sg; /**< Scatter gather memory */
+ struct drm_sg_mem *sg; /**< Scatter gather memory */
unsigned long *ctx_bitmap; /**< context bitmap */
void *dev_private; /**< device private data */
- drm_sigdata_t sigdata; /**< For block_all_signals */
+ struct drm_sigdata sigdata; /**< For block_all_signals */
sigset_t sigmask;
struct drm_driver *driver;
drm_local_map_t *agp_buffer_map;
unsigned int agp_buffer_token;
- drm_head_t primary; /**< primary screen head */
+ struct drm_head primary; /**< primary screen head */
/** \name Drawable information */
/*@{ */
spinlock_t drw_lock;
- unsigned int drw_bitfield_length;
- u32 *drw_bitfield;
- unsigned int drw_info_length;
- drm_drawable_info_t **drw_info;
+ struct idr drw_idr;
/*@} */
-} drm_device_t;
+};
static __inline__ int drm_core_check_feature(struct drm_device *dev,
int feature)
@@ -838,7 +825,7 @@ extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern long drm_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_lastclose(drm_device_t *dev);
+extern int drm_lastclose(struct drm_device *dev);
/* Device support (drm_fops.h) */
extern int drm_open(struct inode *inode, struct file *filp);
@@ -857,7 +844,7 @@ extern int drm_mem_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
-extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
+extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
extern int drm_unbind_agp(DRM_AGP_MEM * handle);
@@ -896,9 +883,9 @@ extern int drm_newctx(struct inode *inode, struct file *filp,
extern int drm_rmctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_ctxbitmap_init(drm_device_t * dev);
-extern void drm_ctxbitmap_cleanup(drm_device_t * dev);
-extern void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle);
+extern int drm_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
extern int drm_setsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -912,8 +899,9 @@ extern int drm_rmdraw(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
+extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
drm_drawable_t id);
+extern void drm_drawable_free_all(struct drm_device *dev);
/* Authentication IOCTL support (drm_auth.h) */
extern int drm_getmagic(struct inode *inode, struct file *filp,
@@ -926,10 +914,10 @@ extern int drm_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_unlock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_lock_take(drm_lock_data_t *lock_data, unsigned int context);
-extern int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context);
-extern void drm_idlelock_take(drm_lock_data_t *lock_data);
-extern void drm_idlelock_release(drm_lock_data_t *lock_data);
+extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
+extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
+extern void drm_idlelock_take(struct drm_lock_data *lock_data);
+extern void drm_idlelock_release(struct drm_lock_data *lock_data);
/*
* These are exported to drivers so that they can implement fencing using
@@ -940,15 +928,15 @@ extern int drm_i_have_hw_lock(struct file *filp);
extern int drm_kernel_take_hw_lock(struct file *filp);
/* Buffer management support (drm_bufs.h) */
-extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addmap(drm_device_t * dev, unsigned int offset,
- unsigned int size, drm_map_type_t type,
- drm_map_flags_t flags, drm_local_map_t ** map_ptr);
+extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addmap(struct drm_device *dev, unsigned int offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags, drm_local_map_t ** map_ptr);
extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_rmmap(drm_device_t * dev, drm_local_map_t * map);
-extern int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map);
+extern int drm_rmmap(struct drm_device *dev, drm_local_map_t * map);
+extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t * map);
extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -963,56 +951,56 @@ extern int drm_freebufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern unsigned long drm_get_resource_start(drm_device_t * dev,
+extern unsigned long drm_get_resource_start(struct drm_device *dev,
unsigned int resource);
-extern unsigned long drm_get_resource_len(drm_device_t * dev,
+extern unsigned long drm_get_resource_len(struct drm_device *dev,
unsigned int resource);
/* DMA support (drm_dma.h) */
-extern int drm_dma_setup(drm_device_t * dev);
-extern void drm_dma_takedown(drm_device_t * dev);
-extern void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf);
-extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp);
+extern int drm_dma_setup(struct drm_device *dev);
+extern void drm_dma_takedown(struct drm_device *dev);
+extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
+extern void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp);
/* IRQ support (drm_irq.h) */
extern int drm_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-extern int drm_irq_uninstall(drm_device_t * dev);
-extern void drm_driver_irq_preinstall(drm_device_t * dev);
-extern void drm_driver_irq_postinstall(drm_device_t * dev);
-extern void drm_driver_irq_uninstall(drm_device_t * dev);
+extern int drm_irq_uninstall(struct drm_device *dev);
+extern void drm_driver_irq_preinstall(struct drm_device *dev);
+extern void drm_driver_irq_postinstall(struct drm_device *dev);
+extern void drm_driver_irq_uninstall(struct drm_device *dev);
extern int drm_wait_vblank(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(drm_device_t * dev);
-extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*));
+extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+extern void drm_vbl_send_signals(struct drm_device *dev);
+extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
/* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
-extern int drm_agp_acquire(drm_device_t * dev);
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *dev);
extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_release(drm_device_t * dev);
+extern int drm_agp_release(struct drm_device *dev);
extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info * info);
extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,
@@ -1024,16 +1012,18 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
/* Stub support (drm_stub.h) */
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver);
-extern int drm_put_dev(drm_device_t * dev);
-extern int drm_put_head(drm_head_t * head);
+extern int drm_put_dev(struct drm_device *dev);
+extern int drm_put_head(struct drm_head *head);
extern unsigned int drm_debug;
extern unsigned int drm_cards_limit;
-extern drm_head_t **drm_heads;
+extern struct drm_head **drm_heads;
extern struct class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
+extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+
/* Proc support (drm_proc.h) */
-extern int drm_proc_init(drm_device_t * dev,
+extern int drm_proc_init(struct drm_device *dev,
int minor,
struct proc_dir_entry *root,
struct proc_dir_entry **dev_root);
@@ -1042,45 +1032,45 @@ extern int drm_proc_cleanup(int minor,
struct proc_dir_entry *dev_root);
/* Scatter Gather Support (drm_scatter.h) */
-extern void drm_sg_cleanup(drm_sg_mem_t * entry);
+extern void drm_sg_cleanup(struct drm_sg_mem * entry);
extern int drm_sg_alloc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_sg_free(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* ATI PCIGART support (ati_pcigart.h) */
-extern int drm_ati_pcigart_init(drm_device_t * dev,
- drm_ati_pcigart_info * gart_info);
-extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
- drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_init(struct drm_device *dev,
+ struct drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
+ struct drm_ati_pcigart_info * gart_info);
-extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
size_t align, dma_addr_t maxaddr);
-extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
-extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
+extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
/* sysfs support (drm_sysfs.c) */
extern struct class *drm_sysfs_create(struct module *owner, char *name);
extern void drm_sysfs_destroy(struct class *cs);
extern struct class_device *drm_sysfs_device_add(struct class *cs,
- drm_head_t *head);
+ struct drm_head *head);
extern void drm_sysfs_device_remove(struct class_device *class_dev);
/*
* Basic memory manager support (drm_mm.c)
*/
-extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
unsigned long size,
unsigned alignment);
-void drm_mm_put_block(drm_mm_node_t * cur);
-extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
+void drm_mm_put_block(struct drm_mm_node * cur);
+extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
unsigned alignment, int best_match);
-extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
-extern void drm_mm_takedown(drm_mm_t *mm);
-extern int drm_mm_clean(drm_mm_t *mm);
-extern unsigned long drm_mm_tail_space(drm_mm_t *mm);
-extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size);
-extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size);
+extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
+extern void drm_mm_takedown(struct drm_mm *mm);
+extern int drm_mm_clean(struct drm_mm *mm);
+extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
+extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
+extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
@@ -1088,14 +1078,14 @@ extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
unsigned int token)
{
- drm_map_list_t *_entry;
- list_for_each_entry(_entry, &dev->maplist->head, head)
+ struct drm_map_list *_entry;
+ list_for_each_entry(_entry, &dev->maplist, head)
if (_entry->user_token == token)
return _entry->map;
return NULL;
}
-static __inline__ int drm_device_is_agp(drm_device_t * dev)
+static __inline__ int drm_device_is_agp(struct drm_device *dev)
{
if (dev->driver->device_is_agp != NULL) {
int err = (*dev->driver->device_is_agp) (dev);
@@ -1108,7 +1098,7 @@ static __inline__ int drm_device_is_agp(drm_device_t * dev)
return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
}
-static __inline__ int drm_device_is_pcie(drm_device_t * dev)
+static __inline__ int drm_device_is_pcie(struct drm_device *dev)
{
return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
}
@@ -1143,7 +1133,7 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area);
/*@}*/
-extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
+extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
#endif /* __KERNEL__ */
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 40bfd9b01e39..354f0e3674bf 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -48,7 +48,7 @@
* Verifies the AGP device has been initialized and acquired and fills in the
* drm_agp_info structure with the information in drm_agp_head::agp_info.
*/
-int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info)
+int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
{
DRM_AGP_KERN *kern;
@@ -74,16 +74,16 @@ EXPORT_SYMBOL(drm_agp_info);
int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_info_t info;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_agp_info info;
int err;
err = drm_agp_info(dev, &info);
if (err)
return err;
- if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
+ if (copy_to_user((struct drm_agp_info __user *) arg, &info, sizeof(info)))
return -EFAULT;
return 0;
}
@@ -97,7 +97,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device hasn't been acquired before and calls
* \c agp_backend_acquire.
*/
-int drm_agp_acquire(drm_device_t * dev)
+int drm_agp_acquire(struct drm_device * dev)
{
if (!dev->agp)
return -ENODEV;
@@ -126,9 +126,9 @@ EXPORT_SYMBOL(drm_agp_acquire);
int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
+ struct drm_file *priv = filp->private_data;
- return drm_agp_acquire((drm_device_t *) priv->head->dev);
+ return drm_agp_acquire((struct drm_device *) priv->head->dev);
}
/**
@@ -139,7 +139,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
*
* Verifies the AGP device has been acquired and calls \c agp_backend_release.
*/
-int drm_agp_release(drm_device_t * dev)
+int drm_agp_release(struct drm_device * dev)
{
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
@@ -152,8 +152,8 @@ EXPORT_SYMBOL(drm_agp_release);
int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
return drm_agp_release(dev);
}
@@ -168,7 +168,7 @@ int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device has been acquired but not enabled, and calls
* \c agp_enable.
*/
-int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode)
+int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
{
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
@@ -185,11 +185,11 @@ EXPORT_SYMBOL(drm_agp_enable);
int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_mode_t mode;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_agp_mode mode;
- if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+ if (copy_from_user(&mode, (struct drm_agp_mode __user *) arg, sizeof(mode)))
return -EFAULT;
return drm_agp_enable(dev, mode);
@@ -207,9 +207,9 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device is present and has been acquired, allocates the
* memory via alloc_agp() and creates a drm_agp_mem entry for it.
*/
-int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
{
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
DRM_AGP_MEM *memory;
unsigned long pages;
u32 type;
@@ -232,11 +232,7 @@ int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
entry->memory = memory;
entry->bound = 0;
entry->pages = pages;
- entry->prev = NULL;
- entry->next = dev->agp->memory;
- if (dev->agp->memory)
- dev->agp->memory->prev = entry;
- dev->agp->memory = entry;
+ list_add(&entry->head, &dev->agp->memory);
request->handle = entry->handle;
request->physical = memory->physical;
@@ -248,10 +244,10 @@ EXPORT_SYMBOL(drm_agp_alloc);
int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_buffer_t request;
- drm_agp_buffer_t __user *argp = (void __user *)arg;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_agp_buffer request;
+ struct drm_agp_buffer __user *argp = (void __user *)arg;
int err;
if (copy_from_user(&request, argp, sizeof(request)))
@@ -262,10 +258,12 @@ int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
return err;
if (copy_to_user(argp, &request, sizeof(request))) {
- drm_agp_mem_t *entry = dev->agp->memory;
-
- dev->agp->memory = entry->next;
- dev->agp->memory->prev = NULL;
+ struct drm_agp_mem *entry;
+ list_for_each_entry(entry, &dev->agp->memory, head) {
+ if (entry->handle == request.handle)
+ break;
+ }
+ list_del(&entry->head);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -EFAULT;
@@ -283,12 +281,12 @@ int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
*
* Walks through drm_agp_head::memory until finding a matching handle.
*/
-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
+static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
unsigned long handle)
{
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
- for (entry = dev->agp->memory; entry; entry = entry->next) {
+ list_for_each_entry(entry, &dev->agp->memory, head) {
if (entry->handle == handle)
return entry;
}
@@ -307,9 +305,9 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
* Verifies the AGP device is present and acquired, looks-up the AGP memory
* entry and passes it to the unbind_agp() function.
*/
-int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
{
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
int ret;
if (!dev->agp || !dev->agp->acquired)
@@ -328,12 +326,12 @@ EXPORT_SYMBOL(drm_agp_unbind);
int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_binding_t request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_agp_binding request;
if (copy_from_user
- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ (&request, (struct drm_agp_binding __user *) arg, sizeof(request)))
return -EFAULT;
return drm_agp_unbind(dev, &request);
@@ -352,9 +350,9 @@ int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
* is currently bound into the GATT. Looks-up the AGP memory entry and passes
* it to bind_agp() function.
*/
-int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
{
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
int retcode;
int page;
@@ -377,12 +375,12 @@ EXPORT_SYMBOL(drm_agp_bind);
int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_binding_t request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_agp_binding request;
if (copy_from_user
- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ (&request, (struct drm_agp_binding __user *) arg, sizeof(request)))
return -EFAULT;
return drm_agp_bind(dev, &request);
@@ -402,9 +400,9 @@ int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
* unbind_agp(). Frees it via free_agp() as well as the entry itself
* and unlinks from the doubly linked list it's inserted in.
*/
-int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
{
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
@@ -413,13 +411,7 @@ int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
if (entry->bound)
drm_unbind_agp(entry->memory);
- if (entry->prev)
- entry->prev->next = entry->next;
- else
- dev->agp->memory = entry->next;
-
- if (entry->next)
- entry->next->prev = entry->prev;
+ list_del(&entry->head);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
@@ -430,12 +422,12 @@ EXPORT_SYMBOL(drm_agp_free);
int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_buffer_t request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_agp_buffer request;
if (copy_from_user
- (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
+ (&request, (struct drm_agp_buffer __user *) arg, sizeof(request)))
return -EFAULT;
return drm_agp_free(dev, &request);
@@ -450,9 +442,9 @@ int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
* via the inter_module_* functions. Creates and initializes a drm_agp_head
* structure.
*/
-drm_agp_head_t *drm_agp_init(drm_device_t * dev)
+struct drm_agp_head *drm_agp_init(struct drm_device *dev)
{
- drm_agp_head_t *head = NULL;
+ struct drm_agp_head *head = NULL;
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
return NULL;
@@ -472,7 +464,7 @@ drm_agp_head_t *drm_agp_init(drm_device_t * dev)
drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
return NULL;
}
- head->memory = NULL;
+ INIT_LIST_HEAD(&head->memory);
head->cant_use_aperture = head->agp_info.cant_use_aperture;
head->page_mask = head->agp_info.page_mask;
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index c7b19d35bcd6..7f777da872cd 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -45,15 +45,15 @@
* the one with matching magic number, while holding the drm_device::struct_mutex
* lock.
*/
-static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
{
- drm_file_t *retval = NULL;
- drm_magic_entry_t *pt;
- drm_hash_item_t *hash;
+ struct drm_file *retval = NULL;
+ struct drm_magic_entry *pt;
+ struct drm_hash_item *hash;
mutex_lock(&dev->struct_mutex);
if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
- pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+ pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
retval = pt->priv;
}
mutex_unlock(&dev->struct_mutex);
@@ -71,10 +71,10 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
* associated the magic number hash key in drm_device::magiclist, while holding
* the drm_device::struct_mutex lock.
*/
-static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
+static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
drm_magic_t magic)
{
- drm_magic_entry_t *entry;
+ struct drm_magic_entry *entry;
DRM_DEBUG("%d\n", magic);
@@ -102,10 +102,10 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock.
*/
-static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
+static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
{
- drm_magic_entry_t *pt;
- drm_hash_item_t *hash;
+ struct drm_magic_entry *pt;
+ struct drm_hash_item *hash;
DRM_DEBUG("%d\n", magic);
@@ -114,7 +114,7 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
- pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+ pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
drm_ht_remove_item(&dev->magiclist, hash);
list_del(&pt->head);
mutex_unlock(&dev->struct_mutex);
@@ -142,9 +142,9 @@ int drm_getmagic(struct inode *inode, struct file *filp,
{
static drm_magic_t sequence = 0;
static DEFINE_SPINLOCK(lock);
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_auth_t auth;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_auth auth;
/* Find unique magic */
if (priv->magic) {
@@ -162,7 +162,7 @@ int drm_getmagic(struct inode *inode, struct file *filp,
}
DRM_DEBUG("%u\n", auth.magic);
- if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
+ if (copy_to_user((struct drm_auth __user *) arg, &auth, sizeof(auth)))
return -EFAULT;
return 0;
}
@@ -181,12 +181,12 @@ int drm_getmagic(struct inode *inode, struct file *filp,
int drm_authmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_auth_t auth;
- drm_file_t *file;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_auth auth;
+ struct drm_file *file;
- if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
+ if (copy_from_user(&auth, (struct drm_auth __user *) arg, sizeof(auth)))
return -EFAULT;
DRM_DEBUG("%u\n", auth.magic);
if ((file = drm_find_file(dev, auth.magic))) {
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index c11345856ffe..923174c54a1c 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -36,26 +36,24 @@
#include <linux/vmalloc.h>
#include "drmP.h"
-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource)
{
return pci_resource_start(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_start);
-unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource)
{
return pci_resource_len(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_len);
-static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
+static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
drm_local_map_t *map)
{
- struct list_head *list;
-
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+ struct drm_map_list *entry;
+ list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && map->type == entry->map->type &&
((entry->map->offset == map->offset) ||
(map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
@@ -66,7 +64,7 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
return NULL;
}
-static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
+static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
unsigned long user_token, int hashed_handle)
{
int use_hashed_handle;
@@ -103,12 +101,13 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel.
*/
-static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
- unsigned int size, drm_map_type_t type,
- drm_map_flags_t flags, drm_map_list_t ** maplist)
+static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags,
+ struct drm_map_list ** maplist)
{
- drm_map_t *map;
- drm_map_list_t *list;
+ struct drm_map *map;
+ struct drm_map_list *list;
drm_dma_handle_t *dmah;
unsigned long user_token;
int ret;
@@ -214,7 +213,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
}
break;
case _DRM_AGP: {
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
int valid = 0;
if (!drm_core_has_AGP(dev)) {
@@ -237,14 +236,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
* skipped and we double check that dev->agp->memory is
* actually set as well as being invalid before EPERM'ing
*/
- for (entry = dev->agp->memory; entry; entry = entry->next) {
+ list_for_each_entry(entry, &dev->agp->memory, head) {
if ((map->offset >= entry->bound) &&
(map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
valid = 1;
break;
}
}
- if (dev->agp->memory && !valid) {
+ if (!list_empty(&dev->agp->memory) && !valid) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EPERM;
}
@@ -289,7 +288,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
list->map = map;
mutex_lock(&dev->struct_mutex);
- list_add(&list->head, &dev->maplist->head);
+ list_add(&list->head, &dev->maplist);
/* Assign a 32-bit handle */
/* We do it here so that dev->struct_mutex protects the increment */
@@ -312,11 +311,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
return 0;
}
-int drm_addmap(drm_device_t * dev, unsigned int offset,
- unsigned int size, drm_map_type_t type,
- drm_map_flags_t flags, drm_local_map_t ** map_ptr)
+int drm_addmap(struct drm_device * dev, unsigned int offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags, drm_local_map_t ** map_ptr)
{
- drm_map_list_t *list;
+ struct drm_map_list *list;
int rc;
rc = drm_addmap_core(dev, offset, size, type, flags, &list);
@@ -330,11 +329,11 @@ EXPORT_SYMBOL(drm_addmap);
int drm_addmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t map;
- drm_map_list_t *maplist;
- drm_map_t __user *argp = (void __user *)arg;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_map map;
+ struct drm_map_list *maplist;
+ struct drm_map __user *argp = (void __user *)arg;
int err;
if (!(filp->f_mode & 3))
@@ -353,7 +352,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
if (err)
return err;
- if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
+ if (copy_to_user(argp, maplist->map, sizeof(struct drm_map)))
return -EFAULT;
/* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
@@ -369,7 +368,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
- * \param arg pointer to a drm_map_t structure.
+ * \param arg pointer to a struct drm_map structure.
* \return zero on success or a negative value on error.
*
* Searches the map on drm_device::maplist, removes it from the list, see if
@@ -378,31 +377,26 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
*
* \sa drm_addmap
*/
-int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
{
- struct list_head *list;
- drm_map_list_t *r_list = NULL;
+ struct drm_map_list *r_list = NULL, *list_t;
drm_dma_handle_t dmah;
+ int found = 0;
/* Find the list entry for the map and remove it */
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
-
+ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
if (r_list->map == map) {
- list_del(list);
+ list_del(&r_list->head);
drm_ht_remove_key(&dev->map_hash,
r_list->user_token >> PAGE_SHIFT);
- drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+ drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ found = 1;
break;
}
}
- /* List has wrapped around to the head pointer, or it's empty and we
- * didn't find anything.
- */
- if (list == (&dev->maplist->head)) {
+ if (!found)
return -EINVAL;
- }
switch (map->type) {
case _DRM_REGISTERS:
@@ -433,7 +427,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
return 0;
}
-int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
{
int ret;
@@ -456,21 +450,19 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_map request;
drm_local_map_t *map = NULL;
- struct list_head *list;
+ struct drm_map_list *r_list;
int ret;
- if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
+ if (copy_from_user(&request, (struct drm_map __user *) arg, sizeof(request))) {
return -EFAULT;
}
mutex_lock(&dev->struct_mutex);
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
-
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
r_list->user_token == (unsigned long)request.handle &&
r_list->map->flags & _DRM_REMOVABLE) {
@@ -482,7 +474,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
/* List has wrapped around to the head pointer, or its empty we didn't
* find anything.
*/
- if (list == (&dev->maplist->head)) {
+ if (list_empty(&dev->maplist) || !map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -513,7 +505,8 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
*
* Frees any pages and buffers associated with the given entry.
*/
-static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
+static void drm_cleanup_buf_error(struct drm_device * dev,
+ struct drm_buf_entry * entry)
{
int i;
@@ -550,20 +543,20 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
/**
* Add AGP buffers for DMA transfers.
*
- * \param dev drm_device_t to which the buffers are to be added.
- * \param request pointer to a drm_buf_desc_t describing the request.
+ * \param dev struct drm_device to which the buffers are to be added.
+ * \param request pointer to a struct drm_buf_desc describing the request.
* \return zero on success or a negative number on failure.
*
* After some sanity checks creates a drm_buf structure for each buffer and
* reallocates the buffer list of the same size order to accommodate the new
* buffers.
*/
-int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_entry_t *entry;
- drm_agp_mem_t *agp_entry;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_entry *entry;
+ struct drm_agp_mem *agp_entry;
+ struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@@ -574,7 +567,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int byte_count;
int i, valid;
- drm_buf_t **temp_buflist;
+ struct drm_buf **temp_buflist;
if (!dma)
return -EINVAL;
@@ -606,14 +599,14 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
/* Make sure buffers are located in AGP memory that we own */
valid = 0;
- for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) {
+ list_for_each_entry(agp_entry, &dev->agp->memory, head) {
if ((agp_offset >= agp_entry->bound) &&
(agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
valid = 1;
break;
}
}
- if (dev->agp->memory && !valid) {
+ if (!list_empty(&dev->agp->memory) && !valid) {
DRM_DEBUG("zone invalid\n");
return -EINVAL;
}
@@ -728,24 +721,24 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */
-int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int count;
int order;
int size;
int total;
int page_order;
- drm_buf_entry_t *entry;
+ struct drm_buf_entry *entry;
drm_dma_handle_t *dmah;
- drm_buf_t *buf;
+ struct drm_buf *buf;
int alignment;
unsigned long offset;
int i;
int byte_count;
int page_count;
unsigned long *temp_pagelist;
- drm_buf_t **temp_buflist;
+ struct drm_buf **temp_buflist;
if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
return -EINVAL;
@@ -954,11 +947,11 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
}
EXPORT_SYMBOL(drm_addbufs_pci);
-static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_entry_t *entry;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_entry *entry;
+ struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@@ -969,7 +962,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int byte_count;
int i;
- drm_buf_t **temp_buflist;
+ struct drm_buf **temp_buflist;
if (!drm_core_check_feature(dev, DRIVER_SG))
return -EINVAL;
@@ -1116,11 +1109,11 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_entry_t *entry;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_entry *entry;
+ struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@@ -1131,7 +1124,7 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int byte_count;
int i;
- drm_buf_t **temp_buflist;
+ struct drm_buf **temp_buflist;
if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
return -EINVAL;
@@ -1283,7 +1276,7 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
* \param inode device inode.
* \param filp file pointer.
* \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \param arg pointer to a struct drm_buf_desc request.
* \return zero on success or a negative number on failure.
*
* According with the memory type specified in drm_buf_desc::flags and the
@@ -1294,15 +1287,15 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
int drm_addbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_buf_desc_t request;
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_buf_desc request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
int ret;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
- if (copy_from_user(&request, (drm_buf_desc_t __user *) arg,
+ if (copy_from_user(&request, (struct drm_buf_desc __user *) arg,
sizeof(request)))
return -EFAULT;
@@ -1346,11 +1339,11 @@ int drm_addbufs(struct inode *inode, struct file *filp,
int drm_infobufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_info_t request;
- drm_buf_info_t __user *argp = (void __user *)arg;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_info request;
+ struct drm_buf_info __user *argp = (void __user *)arg;
int i;
int count;
@@ -1381,10 +1374,10 @@ int drm_infobufs(struct inode *inode, struct file *filp,
if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
if (dma->bufs[i].buf_count) {
- drm_buf_desc_t __user *to =
+ struct drm_buf_desc __user *to =
&request.list[count];
- drm_buf_entry_t *from = &dma->bufs[i];
- drm_freelist_t *list = &dma->bufs[i].freelist;
+ struct drm_buf_entry *from = &dma->bufs[i];
+ struct drm_freelist *list = &dma->bufs[i].freelist;
if (copy_to_user(&to->count,
&from->buf_count,
sizeof(from->buf_count)) ||
@@ -1434,12 +1427,12 @@ int drm_infobufs(struct inode *inode, struct file *filp,
int drm_markbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_desc_t request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_desc request;
int order;
- drm_buf_entry_t *entry;
+ struct drm_buf_entry *entry;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
@@ -1448,7 +1441,7 @@ int drm_markbufs(struct inode *inode, struct file *filp,
return -EINVAL;
if (copy_from_user(&request,
- (drm_buf_desc_t __user *) arg, sizeof(request)))
+ (struct drm_buf_desc __user *) arg, sizeof(request)))
return -EFAULT;
DRM_DEBUG("%d, %d, %d\n",
@@ -1484,13 +1477,13 @@ int drm_markbufs(struct inode *inode, struct file *filp,
int drm_freebufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_free_t request;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_free request;
int i;
int idx;
- drm_buf_t *buf;
+ struct drm_buf *buf;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
@@ -1499,7 +1492,7 @@ int drm_freebufs(struct inode *inode, struct file *filp,
return -EINVAL;
if (copy_from_user(&request,
- (drm_buf_free_t __user *) arg, sizeof(request)))
+ (struct drm_buf_free __user *) arg, sizeof(request)))
return -EFAULT;
DRM_DEBUG("%d\n", request.count);
@@ -1540,15 +1533,15 @@ int drm_freebufs(struct inode *inode, struct file *filp,
int drm_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_map_t __user *argp = (void __user *)arg;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_map __user *argp = (void __user *)arg;
int retcode = 0;
const int zero = 0;
unsigned long virtual;
unsigned long address;
- drm_buf_map_t request;
+ struct drm_buf_map request;
int i;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
@@ -1574,7 +1567,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
&& (dma->flags & _DRM_DMA_USE_SG))
|| (drm_core_check_feature(dev, DRIVER_FB_DMA)
&& (dma->flags & _DRM_DMA_USE_FB))) {
- drm_map_t *map = dev->agp_buffer_map;
+ struct drm_map *map = dev->agp_buffer_map;
unsigned long token = dev->agp_buffer_token;
if (!map) {
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index 83094c73da67..61ad986baa8d 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,26 +53,14 @@
* \param ctx_handle context handle.
*
* Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_mutex
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock.
*/
-void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
{
- if (ctx_handle < 0)
- goto failed;
- if (!dev->ctx_bitmap)
- goto failed;
-
- if (ctx_handle < DRM_MAX_CTXBITMAP) {
- mutex_lock(&dev->struct_mutex);
- clear_bit(ctx_handle, dev->ctx_bitmap);
- dev->context_sareas[ctx_handle] = NULL;
- mutex_unlock(&dev->struct_mutex);
- return;
- }
- failed:
- DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
- return;
+ mutex_lock(&dev->struct_mutex);
+ idr_remove(&dev->ctx_idr, ctx_handle);
+ mutex_unlock(&dev->struct_mutex);
}
/**
@@ -81,62 +69,28 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
* \param dev DRM device.
* \return (non-negative) context handle on success or a negative number on failure.
*
- * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
- * drm_device::context_sareas to accommodate the new entry while holding the
+ * Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock.
*/
-static int drm_ctxbitmap_next(drm_device_t * dev)
+static int drm_ctxbitmap_next(struct drm_device * dev)
{
- int bit;
-
- if (!dev->ctx_bitmap)
- return -1;
+ int new_id;
+ int ret;
+again:
+ if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ return -ENOMEM;
+ }
mutex_lock(&dev->struct_mutex);
- bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
- if (bit < DRM_MAX_CTXBITMAP) {
- set_bit(bit, dev->ctx_bitmap);
- DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
- if ((bit + 1) > dev->max_context) {
- dev->max_context = (bit + 1);
- if (dev->context_sareas) {
- drm_map_t **ctx_sareas;
-
- ctx_sareas = drm_realloc(dev->context_sareas,
- (dev->max_context -
- 1) *
- sizeof(*dev->
- context_sareas),
- dev->max_context *
- sizeof(*dev->
- context_sareas),
- DRM_MEM_MAPS);
- if (!ctx_sareas) {
- clear_bit(bit, dev->ctx_bitmap);
- mutex_unlock(&dev->struct_mutex);
- return -1;
- }
- dev->context_sareas = ctx_sareas;
- dev->context_sareas[bit] = NULL;
- } else {
- /* max_context == 1 at this point */
- dev->context_sareas =
- drm_alloc(dev->max_context *
- sizeof(*dev->context_sareas),
- DRM_MEM_MAPS);
- if (!dev->context_sareas) {
- clear_bit(bit, dev->ctx_bitmap);
- mutex_unlock(&dev->struct_mutex);
- return -1;
- }
- dev->context_sareas[bit] = NULL;
- }
- }
+ ret = idr_get_new_above(&dev->ctx_idr, NULL,
+ DRM_RESERVED_CONTEXTS, &new_id);
+ if (ret == -EAGAIN) {
mutex_unlock(&dev->struct_mutex);
- return bit;
+ goto again;
}
mutex_unlock(&dev->struct_mutex);
- return -1;
+ return new_id;
}
/**
@@ -144,31 +98,11 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
*
* \param dev DRM device.
*
- * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Initialise the drm_device::ctx_idr
*/
-int drm_ctxbitmap_init(drm_device_t * dev)
+int drm_ctxbitmap_init(struct drm_device * dev)
{
- int i;
- int temp;
-
- mutex_lock(&dev->struct_mutex);
- dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
- DRM_MEM_CTXBITMAP);
- if (dev->ctx_bitmap == NULL) {
- mutex_unlock(&dev->struct_mutex);
- return -ENOMEM;
- }
- memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
- dev->context_sareas = NULL;
- dev->max_context = -1;
- mutex_unlock(&dev->struct_mutex);
-
- for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
- temp = drm_ctxbitmap_next(dev);
- DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
- }
-
+ idr_init(&dev->ctx_idr);
return 0;
}
@@ -177,17 +111,13 @@ int drm_ctxbitmap_init(drm_device_t * dev)
*
* \param dev DRM device.
*
- * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
*/
-void drm_ctxbitmap_cleanup(drm_device_t * dev)
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
{
mutex_lock(&dev->struct_mutex);
- if (dev->context_sareas)
- drm_free(dev->context_sareas,
- sizeof(*dev->context_sareas) *
- dev->max_context, DRM_MEM_MAPS);
- drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
+ idr_remove_all(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex);
}
@@ -206,34 +136,34 @@ void drm_ctxbitmap_cleanup(drm_device_t * dev)
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
*
- * Gets the map from drm_device::context_sareas with the handle specified and
+ * Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle.
*/
int drm_getsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_priv_map_t __user *argp = (void __user *)arg;
- drm_ctx_priv_map_t request;
- drm_map_t *map;
- drm_map_list_t *_entry;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx_priv_map __user *argp = (void __user *)arg;
+ struct drm_ctx_priv_map request;
+ struct drm_map *map;
+ struct drm_map_list *_entry;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
mutex_lock(&dev->struct_mutex);
- if (dev->max_context < 0
- || request.ctx_id >= (unsigned)dev->max_context) {
+
+ map = idr_find(&dev->ctx_idr, request.ctx_id);
+ if (!map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
- map = dev->context_sareas[request.ctx_id];
mutex_unlock(&dev->struct_mutex);
request.handle = NULL;
- list_for_each_entry(_entry, &dev->maplist->head, head) {
+ list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == map) {
request.handle =
(void *)(unsigned long)_entry->user_token;
@@ -258,25 +188,24 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
* \return zero on success or a negative number on failure.
*
* Searches the mapping specified in \p arg and update the entry in
- * drm_device::context_sareas with it.
+ * drm_device::ctx_idr with it.
*/
int drm_setsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_priv_map_t request;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list = NULL;
- struct list_head *list;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx_priv_map request;
+ struct drm_map *map = NULL;
+ struct drm_map_list *r_list = NULL;
if (copy_from_user(&request,
- (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
+ (struct drm_ctx_priv_map __user *) arg,
+ sizeof(request)))
return -EFAULT;
mutex_lock(&dev->struct_mutex);
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map
&& r_list->user_token == (unsigned long)request.handle)
goto found;
@@ -289,11 +218,10 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
map = r_list->map;
if (!map)
goto bad;
- if (dev->max_context < 0)
- goto bad;
- if (request.ctx_id >= (unsigned)dev->max_context)
+
+ if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id)))
goto bad;
- dev->context_sareas[request.ctx_id] = map;
+
mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -314,7 +242,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
*
* Attempt to set drm_device::context_flag.
*/
-static int drm_context_switch(drm_device_t * dev, int old, int new)
+static int drm_context_switch(struct drm_device * dev, int old, int new)
{
if (test_and_set_bit(0, &dev->context_flag)) {
DRM_ERROR("Reentering -- FIXME\n");
@@ -342,7 +270,7 @@ static int drm_context_switch(drm_device_t * dev, int old, int new)
* hardware lock is held, clears the drm_device::context_flag and wakes up
* drm_device::context_wait.
*/
-static int drm_context_switch_complete(drm_device_t * dev, int new)
+static int drm_context_switch_complete(struct drm_device * dev, int new)
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
dev->last_switch = jiffies;
@@ -372,9 +300,9 @@ static int drm_context_switch_complete(drm_device_t * dev, int new)
int drm_resctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_ctx_res_t res;
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
+ struct drm_ctx_res res;
+ struct drm_ctx_res __user *argp = (void __user *)arg;
+ struct drm_ctx ctx;
int i;
if (copy_from_user(&res, argp, sizeof(res)))
@@ -409,11 +337,11 @@ int drm_resctx(struct inode *inode, struct file *filp,
int drm_addctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_list_t *ctx_entry;
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx_list *ctx_entry;
+ struct drm_ctx __user *argp = (void __user *)arg;
+ struct drm_ctx ctx;
if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
@@ -449,7 +377,7 @@ int drm_addctx(struct inode *inode, struct file *filp,
ctx_entry->tag = priv;
mutex_lock(&dev->ctxlist_mutex);
- list_add(&ctx_entry->head, &dev->ctxlist->head);
+ list_add(&ctx_entry->head, &dev->ctxlist);
++dev->ctx_count;
mutex_unlock(&dev->ctxlist_mutex);
@@ -477,8 +405,8 @@ int drm_modctx(struct inode *inode, struct file *filp,
int drm_getctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_ctx_t __user *argp = (void __user *)arg;
- drm_ctx_t ctx;
+ struct drm_ctx __user *argp = (void __user *)arg;
+ struct drm_ctx ctx;
if (copy_from_user(&ctx, argp, sizeof(ctx)))
return -EFAULT;
@@ -505,11 +433,11 @@ int drm_getctx(struct inode *inode, struct file *filp,
int drm_switchctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -530,11 +458,11 @@ int drm_switchctx(struct inode *inode, struct file *filp,
int drm_newctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -557,11 +485,11 @@ int drm_newctx(struct inode *inode, struct file *filp,
int drm_rmctx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_ctx_t ctx;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_ctx ctx;
- if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -575,10 +503,10 @@ int drm_rmctx(struct inode *inode, struct file *filp,
}
mutex_lock(&dev->ctxlist_mutex);
- if (!list_empty(&dev->ctxlist->head)) {
- drm_ctx_list_t *pos, *n;
+ if (!list_empty(&dev->ctxlist)) {
+ struct drm_ctx_list *pos, *n;
- list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->handle == ctx.handle) {
list_del(&pos->head);
drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 32ed19c9ec1c..802fbdbfe1b3 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -43,7 +43,7 @@
*
* Allocate and initialize a drm_device_dma structure.
*/
-int drm_dma_setup(drm_device_t * dev)
+int drm_dma_setup(struct drm_device *dev)
{
int i;
@@ -67,9 +67,9 @@ int drm_dma_setup(drm_device_t * dev)
* Free all pages associated with DMA buffers, the buffers and pages lists, and
* finally the drm_device::dma structure itself.
*/
-void drm_dma_takedown(drm_device_t * dev)
+void drm_dma_takedown(struct drm_device *dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i, j;
if (!dma)
@@ -129,7 +129,7 @@ void drm_dma_takedown(drm_device_t * dev)
*
* Resets the fields of \p buf.
*/
-void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
+void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
{
if (!buf)
return;
@@ -152,9 +152,9 @@ void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
*
* Frees each buffer associated with \p filp not already on the hardware.
*/
-void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp)
+void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
if (!dma)
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
index b33313be2547..d6cdba5644e2 100644
--- a/drivers/char/drm/drm_drawable.c
+++ b/drivers/char/drm/drm_drawable.c
@@ -44,83 +44,30 @@ int drm_adddraw(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
unsigned long irqflags;
- int i, j;
- u32 *bitfield = dev->drw_bitfield;
- unsigned int bitfield_length = dev->drw_bitfield_length;
- drm_drawable_info_t **info = dev->drw_info;
- unsigned int info_length = dev->drw_info_length;
- drm_draw_t draw;
-
- for (i = 0, j = 0; i < bitfield_length; i++) {
- if (bitfield[i] == ~0)
- continue;
-
- for (; j < 8 * sizeof(*bitfield); j++)
- if (!(bitfield[i] & (1 << j)))
- goto done;
+ struct drm_draw draw;
+ int new_id = 0;
+ int ret;
+
+again:
+ if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ return -ENOMEM;
}
-done:
-
- if (i == bitfield_length) {
- bitfield_length++;
-
- bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
- DRM_MEM_BUFS);
-
- if (!bitfield) {
- DRM_ERROR("Failed to allocate new drawable bitfield\n");
- return DRM_ERR(ENOMEM);
- }
-
- if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
- info_length += 8 * sizeof(*bitfield);
-
- info = drm_alloc(info_length * sizeof(*info),
- DRM_MEM_BUFS);
-
- if (!info) {
- DRM_ERROR("Failed to allocate new drawable info"
- " array\n");
-
- drm_free(bitfield,
- bitfield_length * sizeof(*bitfield),
- DRM_MEM_BUFS);
- return DRM_ERR(ENOMEM);
- }
- }
-
- bitfield[i] = 0;
- }
-
- draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
- DRM_DEBUG("%d\n", draw.handle);
spin_lock_irqsave(&dev->drw_lock, irqflags);
-
- bitfield[i] |= 1 << j;
- info[draw.handle - 1] = NULL;
-
- if (bitfield != dev->drw_bitfield) {
- memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
- sizeof(*bitfield));
- drm_free(dev->drw_bitfield, sizeof(*bitfield) *
- dev->drw_bitfield_length, DRM_MEM_BUFS);
- dev->drw_bitfield = bitfield;
- dev->drw_bitfield_length = bitfield_length;
- }
-
- if (info != dev->drw_info) {
- memcpy(info, dev->drw_info, dev->drw_info_length *
- sizeof(*info));
- drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
- DRM_MEM_BUFS);
- dev->drw_info = info;
- dev->drw_info_length = info_length;
+ ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
+ if (ret == -EAGAIN) {
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ goto again;
}
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+ draw.handle = new_id;
+
+ DRM_DEBUG("%d\n", draw.handle);
+
+ DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw));
return 0;
}
@@ -131,141 +78,52 @@ done:
int drm_rmdraw(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_draw_t draw;
- int id, idx;
- unsigned int shift;
+ struct drm_draw draw;
unsigned long irqflags;
- u32 *bitfield = dev->drw_bitfield;
- unsigned int bitfield_length = dev->drw_bitfield_length;
- drm_drawable_info_t **info = dev->drw_info;
- unsigned int info_length = dev->drw_info_length;
- DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
+ DRM_COPY_FROM_USER_IOCTL(draw, (struct drm_draw __user *) data,
sizeof(draw));
- id = draw.handle - 1;
- idx = id / (8 * sizeof(*bitfield));
- shift = id % (8 * sizeof(*bitfield));
-
- if (idx < 0 || idx >= bitfield_length ||
- !(bitfield[idx] & (1 << shift))) {
- DRM_DEBUG("No such drawable %d\n", draw.handle);
- return 0;
- }
-
spin_lock_irqsave(&dev->drw_lock, irqflags);
- bitfield[idx] &= ~(1 << shift);
-
- spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
- if (info[id]) {
- drm_free(info[id]->rects, info[id]->num_rects *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
- drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
- }
-
- /* Can we shrink the arrays? */
- if (idx == bitfield_length - 1) {
- while (idx >= 0 && !bitfield[idx])
- --idx;
-
- bitfield_length = idx + 1;
-
- bitfield = NULL;
-
- if (bitfield_length) {
- if (bitfield_length != dev->drw_bitfield_length)
- bitfield = drm_alloc(bitfield_length *
- sizeof(*bitfield),
- DRM_MEM_BUFS);
-
- if (!bitfield) {
- bitfield = dev->drw_bitfield;
- bitfield_length = dev->drw_bitfield_length;
- }
- }
- }
-
- if (bitfield != dev->drw_bitfield) {
- info_length = 8 * sizeof(*bitfield) * bitfield_length;
-
- if (info_length) {
- info = drm_alloc(info_length * sizeof(*info),
- DRM_MEM_BUFS);
-
- if (!info) {
- info = dev->drw_info;
- info_length = dev->drw_info_length;
- }
- } else
- info = NULL;
-
- spin_lock_irqsave(&dev->drw_lock, irqflags);
+ drm_free(drm_get_drawable_info(dev, draw.handle),
+ sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
- if (bitfield)
- memcpy(bitfield, dev->drw_bitfield, bitfield_length *
- sizeof(*bitfield));
- drm_free(dev->drw_bitfield, sizeof(*bitfield) *
- dev->drw_bitfield_length, DRM_MEM_BUFS);
- dev->drw_bitfield = bitfield;
- dev->drw_bitfield_length = bitfield_length;
-
- if (info != dev->drw_info) {
- if (info)
- memcpy(info, dev->drw_info, info_length *
- sizeof(*info));
- drm_free(dev->drw_info, sizeof(*info) *
- dev->drw_info_length, DRM_MEM_BUFS);
- dev->drw_info = info;
- dev->drw_info_length = info_length;
- }
-
- spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- }
+ idr_remove(&dev->drw_idr, draw.handle);
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
DRM_DEBUG("%d\n", draw.handle);
return 0;
}
-int drm_update_drawable_info(DRM_IOCTL_ARGS) {
+int drm_update_drawable_info(DRM_IOCTL_ARGS)
+{
DRM_DEVICE;
- drm_update_draw_t update;
- unsigned int id, idx, shift;
- u32 *bitfield = dev->drw_bitfield;
- unsigned long irqflags, bitfield_length = dev->drw_bitfield_length;
- drm_drawable_info_t *info;
- drm_clip_rect_t *rects;
+ struct drm_update_draw update;
+ unsigned long irqflags;
+ struct drm_clip_rect *rects;
+ struct drm_drawable_info *info;
int err;
- DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
+ DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data,
sizeof(update));
- id = update.handle - 1;
- idx = id / (8 * sizeof(*bitfield));
- shift = id % (8 * sizeof(*bitfield));
-
- if (idx < 0 || idx >= bitfield_length ||
- !(bitfield[idx] & (1 << shift))) {
- DRM_ERROR("No such drawable %d\n", update.handle);
- return DRM_ERR(EINVAL);
- }
-
- info = dev->drw_info[id];
-
+ info = idr_find(&dev->drw_idr, update.handle);
if (!info) {
- info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
-
- if (!info) {
- DRM_ERROR("Failed to allocate drawable info memory\n");
- return DRM_ERR(ENOMEM);
+ info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+ if (!info)
+ return -ENOMEM;
+ if (IS_ERR(idr_replace(&dev->drw_idr, info, update.handle))) {
+ DRM_ERROR("No such drawable %d\n", update.handle);
+ drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+ return -EINVAL;
}
}
switch (update.type) {
case DRM_DRAWABLE_CLIPRECTS:
if (update.num != info->num_rects) {
- rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+ rects = drm_alloc(update.num * sizeof(struct drm_clip_rect),
DRM_MEM_BUFS);
} else
rects = info->rects;
@@ -277,7 +135,7 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
}
if (update.num && DRM_COPY_FROM_USER(rects,
- (drm_clip_rect_t __user *)
+ (struct drm_clip_rect __user *)
(unsigned long)update.data,
update.num *
sizeof(*rects))) {
@@ -290,17 +148,16 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
if (rects != info->rects) {
drm_free(info->rects, info->num_rects *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
}
info->rects = rects;
info->num_rects = update.num;
- dev->drw_info[id] = info;
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
DRM_DEBUG("Updated %d cliprects for drawable %d\n",
- info->num_rects, id);
+ info->num_rects, update.handle);
break;
default:
DRM_ERROR("Invalid update type %d\n", update.type);
@@ -310,11 +167,9 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
return 0;
error:
- if (!dev->drw_info[id])
- drm_free(info, sizeof(*info), DRM_MEM_BUFS);
- else if (rects != dev->drw_info[id]->rects)
- drm_free(rects, update.num *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ if (rects != info->rects)
+ drm_free(rects, update.num * sizeof(struct drm_clip_rect),
+ DRM_MEM_BUFS);
return err;
}
@@ -322,20 +177,27 @@ error:
/**
* Caller must hold the drawable spinlock!
*/
-drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
- u32 *bitfield = dev->drw_bitfield;
- unsigned int idx, shift;
-
- id--;
- idx = id / (8 * sizeof(*bitfield));
- shift = id % (8 * sizeof(*bitfield));
-
- if (idx < 0 || idx >= dev->drw_bitfield_length ||
- !(bitfield[idx] & (1 << shift))) {
- DRM_DEBUG("No such drawable %d\n", id);
- return NULL;
+struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
+{
+ return idr_find(&dev->drw_idr, id);
+}
+EXPORT_SYMBOL(drm_get_drawable_info);
+
+static int drm_drawable_free(int idr, void *p, void *data)
+{
+ struct drm_drawable_info *info = p;
+
+ if (info) {
+ drm_free(info->rects, info->num_rects *
+ sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+ drm_free(info, sizeof(*info), DRM_MEM_BUFS);
}
- return dev->drw_info[id];
+ return 0;
+}
+
+void drm_drawable_free_all(struct drm_device *dev)
+{
+ idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
+ idr_remove_all(&dev->drw_idr);
}
-EXPORT_SYMBOL(drm_get_drawable_info);
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 8e77b7ed0f44..19994cd865de 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -129,11 +129,11 @@ static drm_ioctl_desc_t drm_ioctls[] = {
*
* \sa drm_device
*/
-int drm_lastclose(drm_device_t * dev)
+int drm_lastclose(struct drm_device * dev)
{
- drm_magic_entry_t *pt, *next;
- drm_map_list_t *r_list;
- drm_vma_entry_t *vma, *vma_next;
+ struct drm_magic_entry *pt, *next;
+ struct drm_map_list *r_list, *list_t;
+ struct drm_vma_entry *vma, *vma_temp;
int i;
DRM_DEBUG("\n");
@@ -151,19 +151,10 @@ int drm_lastclose(drm_device_t * dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
- /* Free drawable information memory */
- for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
- i++) {
- drm_drawable_info_t *info = drm_get_drawable_info(dev, i);
-
- if (info) {
- drm_free(info->rects, info->num_rects *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
- drm_free(info, sizeof(*info), DRM_MEM_BUFS);
- }
- }
-
mutex_lock(&dev->struct_mutex);
+
+ /* Free drawable information memory */
+ drm_drawable_free_all(dev);
del_timer(&dev->timer);
/* Clear pid list */
@@ -178,19 +169,17 @@ int drm_lastclose(drm_device_t * dev)
/* Clear AGP information */
if (drm_core_has_AGP(dev) && dev->agp) {
- drm_agp_mem_t *entry;
- drm_agp_mem_t *nexte;
+ struct drm_agp_mem *entry, *tempe;
/* Remove AGP resources, but leave dev->agp
intact until drv_cleanup is called. */
- for (entry = dev->agp->memory; entry; entry = nexte) {
- nexte = entry->next;
+ list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
if (entry->bound)
drm_unbind_agp(entry->memory);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
}
- dev->agp->memory = NULL;
+ INIT_LIST_HEAD(&dev->agp->memory);
if (dev->agp->acquired)
drm_agp_release(dev);
@@ -204,20 +193,14 @@ int drm_lastclose(drm_device_t * dev)
}
/* Clear vma list (only built for debugging) */
- if (dev->vmalist) {
- for (vma = dev->vmalist; vma; vma = vma_next) {
- vma_next = vma->next;
- drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
- }
- dev->vmalist = NULL;
+ list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+ list_del(&vma->head);
+ drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
}
- if (dev->maplist) {
- while (!list_empty(&dev->maplist->head)) {
- struct list_head *list = dev->maplist->head.next;
- r_list = list_entry(list, drm_map_list_t, head);
- drm_rmmap_locked(dev, r_list->map);
- }
+ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+ drm_rmmap_locked(dev, r_list->map);
+ r_list = NULL;
}
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
@@ -298,7 +281,7 @@ EXPORT_SYMBOL(drm_init);
*
* \sa drm_init
*/
-static void drm_cleanup(drm_device_t * dev)
+static void drm_cleanup(struct drm_device * dev)
{
DRM_DEBUG("\n");
@@ -309,11 +292,7 @@ static void drm_cleanup(drm_device_t * dev)
drm_lastclose(dev);
- if (dev->maplist) {
- drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
- dev->maplist = NULL;
- drm_ht_remove(&dev->map_hash);
- }
+ drm_ht_remove(&dev->map_hash);
drm_ctxbitmap_cleanup(dev);
@@ -342,8 +321,8 @@ static void drm_cleanup(drm_device_t * dev)
void drm_exit(struct drm_driver *driver)
{
int i;
- drm_device_t *dev = NULL;
- drm_head_t *head;
+ struct drm_device *dev = NULL;
+ struct drm_head *head;
DRM_DEBUG("\n");
@@ -442,10 +421,10 @@ module_exit(drm_core_exit);
static int drm_version(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_version_t __user *argp = (void __user *)arg;
- drm_version_t version;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_version __user *argp = (void __user *)arg;
+ struct drm_version version;
int len;
if (copy_from_user(&version, argp, sizeof(version)))
@@ -478,8 +457,8 @@ static int drm_version(struct inode *inode, struct file *filp,
int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_ioctl_desc_t *ioctl;
drm_ioctl_t *func;
unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -529,3 +508,17 @@ int drm_ioctl(struct inode *inode, struct file *filp,
}
EXPORT_SYMBOL(drm_ioctl);
+
+drm_local_map_t *drm_getsarea(struct drm_device *dev)
+{
+ struct drm_map_list *entry;
+
+ list_for_each_entry(entry, &dev->maplist, head) {
+ if (entry->map && entry->map->type == _DRM_SHM &&
+ (entry->map->flags & _DRM_CONTAINS_LOCK)) {
+ return entry->map;
+ }
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 3b159cab3bc8..7bc51bac450d 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -39,9 +39,9 @@
#include <linux/poll.h>
static int drm_open_helper(struct inode *inode, struct file *filp,
- drm_device_t * dev);
+ struct drm_device * dev);
-static int drm_setup(drm_device_t * dev)
+static int drm_setup(struct drm_device * dev)
{
drm_local_map_t *map;
int i;
@@ -79,13 +79,6 @@ static int drm_setup(drm_device_t * dev)
drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
INIT_LIST_HEAD(&dev->magicfree);
- dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
- if (dev->ctxlist == NULL)
- return -ENOMEM;
- memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
- INIT_LIST_HEAD(&dev->ctxlist->head);
-
- dev->vmalist = NULL;
dev->sigdata.lock = NULL;
init_waitqueue_head(&dev->lock.lock_queue);
dev->queue_count = 0;
@@ -135,7 +128,7 @@ static int drm_setup(drm_device_t * dev)
*/
int drm_open(struct inode *inode, struct file *filp)
{
- drm_device_t *dev = NULL;
+ struct drm_device *dev = NULL;
int minor = iminor(inode);
int retcode = 0;
@@ -174,7 +167,7 @@ EXPORT_SYMBOL(drm_open);
*/
int drm_stub_open(struct inode *inode, struct file *filp)
{
- drm_device_t *dev = NULL;
+ struct drm_device *dev = NULL;
int minor = iminor(inode);
int err = -ENODEV;
const struct file_operations *old_fops;
@@ -230,10 +223,10 @@ static int drm_cpu_valid(void)
* filp and add it into the double linked list in \p dev.
*/
static int drm_open_helper(struct inode *inode, struct file *filp,
- drm_device_t * dev)
+ struct drm_device * dev)
{
int minor = iminor(inode);
- drm_file_t *priv;
+ struct drm_file *priv;
int ret;
if (filp->f_flags & O_EXCL)
@@ -258,6 +251,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
+ INIT_LIST_HEAD(&priv->lhead);
+
if (dev->driver->open) {
ret = dev->driver->open(dev, priv);
if (ret < 0)
@@ -265,19 +260,10 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
}
mutex_lock(&dev->struct_mutex);
- if (!dev->file_last) {
- priv->next = NULL;
- priv->prev = NULL;
- dev->file_first = priv;
- dev->file_last = priv;
- /* first opener automatically becomes master */
+ if (list_empty(&dev->filelist))
priv->master = 1;
- } else {
- priv->next = NULL;
- priv->prev = dev->file_last;
- dev->file_last->next = priv;
- dev->file_last = priv;
- }
+
+ list_add(&priv->lhead, &dev->filelist);
mutex_unlock(&dev->struct_mutex);
#ifdef __alpha__
@@ -309,8 +295,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
/** No-op. */
int drm_fasync(int fd, struct file *filp, int on)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
int retcode;
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
@@ -336,8 +322,8 @@ EXPORT_SYMBOL(drm_fasync);
*/
int drm_release(struct inode *inode, struct file *filp)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev;
int retcode = 0;
lock_kernel();
@@ -414,10 +400,10 @@ int drm_release(struct inode *inode, struct file *filp)
drm_fasync(-1, filp, 0);
mutex_lock(&dev->ctxlist_mutex);
- if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
- drm_ctx_list_t *pos, *n;
+ if (!list_empty(&dev->ctxlist)) {
+ struct drm_ctx_list *pos, *n;
- list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->tag == priv &&
pos->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
@@ -436,22 +422,12 @@ int drm_release(struct inode *inode, struct file *filp)
mutex_lock(&dev->struct_mutex);
if (priv->remove_auth_on_close == 1) {
- drm_file_t *temp = dev->file_first;
- while (temp) {
+ struct drm_file *temp;
+
+ list_for_each_entry(temp, &dev->filelist, lhead)
temp->authenticated = 0;
- temp = temp->next;
- }
- }
- if (priv->prev) {
- priv->prev->next = priv->next;
- } else {
- dev->file_first = priv->next;
- }
- if (priv->next) {
- priv->next->prev = priv->prev;
- } else {
- dev->file_last = priv->prev;
}
+ list_del(&priv->lhead);
mutex_unlock(&dev->struct_mutex);
if (dev->driver->postclose)
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
index 31acb621dcce..3ad319070704 100644
--- a/drivers/char/drm/drm_hashtab.c
+++ b/drivers/char/drm/drm_hashtab.c
@@ -36,7 +36,7 @@
#include "drm_hashtab.h"
#include <linux/hash.h>
-int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
+int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
{
unsigned int i;
@@ -63,9 +63,9 @@ int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
return 0;
}
-void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
+void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
{
- drm_hash_item_t *entry;
+ struct drm_hash_item *entry;
struct hlist_head *h_list;
struct hlist_node *list;
unsigned int hashed_key;
@@ -75,15 +75,15 @@ void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
h_list = &ht->table[hashed_key];
hlist_for_each(list, h_list) {
- entry = hlist_entry(list, drm_hash_item_t, head);
+ entry = hlist_entry(list, struct drm_hash_item, head);
DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
}
}
-static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht,
+static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
unsigned long key)
{
- drm_hash_item_t *entry;
+ struct drm_hash_item *entry;
struct hlist_head *h_list;
struct hlist_node *list;
unsigned int hashed_key;
@@ -91,7 +91,7 @@ static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht,
hashed_key = hash_long(key, ht->order);
h_list = &ht->table[hashed_key];
hlist_for_each(list, h_list) {
- entry = hlist_entry(list, drm_hash_item_t, head);
+ entry = hlist_entry(list, struct drm_hash_item, head);
if (entry->key == key)
return list;
if (entry->key > key)
@@ -101,9 +101,9 @@ static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht,
}
-int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
{
- drm_hash_item_t *entry;
+ struct drm_hash_item *entry;
struct hlist_head *h_list;
struct hlist_node *list, *parent;
unsigned int hashed_key;
@@ -113,7 +113,7 @@ int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
h_list = &ht->table[hashed_key];
parent = NULL;
hlist_for_each(list, h_list) {
- entry = hlist_entry(list, drm_hash_item_t, head);
+ entry = hlist_entry(list, struct drm_hash_item, head);
if (entry->key == key)
return -EINVAL;
if (entry->key > key)
@@ -132,7 +132,7 @@ int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
* Just insert an item and return any "bits" bit key that hasn't been
* used before.
*/
-int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
unsigned long seed, int bits, int shift,
unsigned long add)
{
@@ -156,8 +156,8 @@ int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
return 0;
}
-int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key,
- drm_hash_item_t **item)
+int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
+ struct drm_hash_item **item)
{
struct hlist_node *list;
@@ -165,11 +165,11 @@ int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key,
if (!list)
return -EINVAL;
- *item = hlist_entry(list, drm_hash_item_t, head);
+ *item = hlist_entry(list, struct drm_hash_item, head);
return 0;
}
-int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
+int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
{
struct hlist_node *list;
@@ -182,14 +182,14 @@ int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
return -EINVAL;
}
-int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
{
hlist_del_init(&item->head);
ht->fill--;
return 0;
}
-void drm_ht_remove(drm_open_hash_t *ht)
+void drm_ht_remove(struct drm_open_hash *ht)
{
if (ht->table) {
if (ht->use_vmalloc)
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
index 613091c970af..0f1376774168 100644
--- a/drivers/char/drm/drm_hashtab.h
+++ b/drivers/char/drm/drm_hashtab.h
@@ -37,31 +37,31 @@
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
-typedef struct drm_hash_item{
+struct drm_hash_item {
struct hlist_node head;
unsigned long key;
-} drm_hash_item_t;
+};
-typedef struct drm_open_hash{
+struct drm_open_hash {
unsigned int size;
unsigned int order;
unsigned int fill;
struct hlist_head *table;
int use_vmalloc;
-} drm_open_hash_t;
+};
-extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
-extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
unsigned long seed, int bits, int shift,
unsigned long add);
-extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
+extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
-extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern void drm_ht_remove(drm_open_hash_t *ht);
+extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern void drm_ht_remove(struct drm_open_hash *ht);
#endif
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index fafeb34f89d5..462f46f2049a 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -82,7 +82,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_version32_t v32;
- drm_version_t __user *version;
+ struct drm_version __user *version;
int err;
if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
@@ -129,7 +129,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_unique32_t uq32;
- drm_unique_t __user *u;
+ struct drm_unique __user *u;
int err;
if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
@@ -159,7 +159,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_unique32_t uq32;
- drm_unique_t __user *u;
+ struct drm_unique __user *u;
if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
return -EFAULT;
@@ -179,8 +179,8 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
typedef struct drm_map32 {
u32 offset; /**< Requested physical address (0 for SAREA)*/
u32 size; /**< Requested physical size (bytes) */
- drm_map_type_t type; /**< Type of memory to map */
- drm_map_flags_t flags; /**< Flags */
+ enum drm_map_type type; /**< Type of memory to map */
+ enum drm_map_flags flags; /**< Flags */
u32 handle; /**< User-space: "Handle" to pass to mmap() */
int mtrr; /**< MTRR slot used */
} drm_map32_t;
@@ -190,7 +190,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
{
drm_map32_t __user *argp = (void __user *)arg;
drm_map32_t m32;
- drm_map_t __user *map;
+ struct drm_map __user *map;
int idx, err;
void *handle;
@@ -228,7 +228,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
{
drm_map32_t __user *argp = (void __user *)arg;
drm_map32_t m32;
- drm_map_t __user *map;
+ struct drm_map __user *map;
int err;
void *handle;
@@ -270,7 +270,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_map32_t __user *argp = (void __user *)arg;
- drm_map_t __user *map;
+ struct drm_map __user *map;
u32 handle;
if (get_user(handle, &argp->handle))
@@ -300,7 +300,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
{
drm_client32_t c32;
drm_client32_t __user *argp = (void __user *)arg;
- drm_client_t __user *client;
+ struct drm_client __user *client;
int idx, err;
if (get_user(idx, &argp->idx))
@@ -333,7 +333,7 @@ typedef struct drm_stats32 {
u32 count;
struct {
u32 value;
- drm_stat_type_t type;
+ enum drm_stat_type type;
} data[15];
} drm_stats32_t;
@@ -342,7 +342,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
{
drm_stats32_t s32;
drm_stats32_t __user *argp = (void __user *)arg;
- drm_stats_t __user *stats;
+ struct drm_stats __user *stats;
int i, err;
stats = compat_alloc_user_space(sizeof(*stats));
@@ -379,7 +379,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_buf_desc32_t __user *argp = (void __user *)arg;
- drm_buf_desc_t __user *buf;
+ struct drm_buf_desc __user *buf;
int err;
unsigned long agp_start;
@@ -411,7 +411,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
{
drm_buf_desc32_t b32;
drm_buf_desc32_t __user *argp = (void __user *)arg;
- drm_buf_desc_t __user *buf;
+ struct drm_buf_desc __user *buf;
if (copy_from_user(&b32, argp, sizeof(b32)))
return -EFAULT;
@@ -440,8 +440,8 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
drm_buf_info32_t req32;
drm_buf_info32_t __user *argp = (void __user *)arg;
drm_buf_desc32_t __user *to;
- drm_buf_info_t __user *request;
- drm_buf_desc_t __user *list;
+ struct drm_buf_info __user *request;
+ struct drm_buf_desc __user *list;
size_t nbytes;
int i, err;
int count, actual;
@@ -457,11 +457,11 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
&& !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
return -EFAULT;
- nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
+ nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
request = compat_alloc_user_space(nbytes);
if (!access_ok(VERIFY_WRITE, request, nbytes))
return -EFAULT;
- list = (drm_buf_desc_t *) (request + 1);
+ list = (struct drm_buf_desc *) (request + 1);
if (__put_user(count, &request->count)
|| __put_user(list, &request->list))
@@ -477,7 +477,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
if (count >= actual)
for (i = 0; i < actual; ++i)
if (__copy_in_user(&to[i], &list[i],
- offsetof(drm_buf_desc_t, flags)))
+ offsetof(struct drm_buf_desc, flags)))
return -EFAULT;
if (__put_user(actual, &argp->count))
@@ -505,8 +505,8 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
drm_buf_map32_t __user *argp = (void __user *)arg;
drm_buf_map32_t req32;
drm_buf_pub32_t __user *list32;
- drm_buf_map_t __user *request;
- drm_buf_pub_t __user *list;
+ struct drm_buf_map __user *request;
+ struct drm_buf_pub __user *list;
int i, err;
int count, actual;
size_t nbytes;
@@ -519,11 +519,11 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
if (count < 0)
return -EINVAL;
- nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
+ nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
request = compat_alloc_user_space(nbytes);
if (!access_ok(VERIFY_WRITE, request, nbytes))
return -EFAULT;
- list = (drm_buf_pub_t *) (request + 1);
+ list = (struct drm_buf_pub *) (request + 1);
if (__put_user(count, &request->count)
|| __put_user(list, &request->list))
@@ -539,7 +539,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
if (count >= actual)
for (i = 0; i < actual; ++i)
if (__copy_in_user(&list32[i], &list[i],
- offsetof(drm_buf_pub_t, address))
+ offsetof(struct drm_buf_pub, address))
|| __get_user(addr, &list[i].address)
|| __put_user((unsigned long)addr,
&list32[i].address))
@@ -562,7 +562,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_buf_free32_t req32;
- drm_buf_free_t __user *request;
+ struct drm_buf_free __user *request;
drm_buf_free32_t __user *argp = (void __user *)arg;
if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -589,7 +589,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_ctx_priv_map32_t req32;
- drm_ctx_priv_map_t __user *request;
+ struct drm_ctx_priv_map __user *request;
drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -610,7 +610,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
unsigned long arg)
{
- drm_ctx_priv_map_t __user *request;
+ struct drm_ctx_priv_map __user *request;
drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
int err;
unsigned int ctx_id;
@@ -648,7 +648,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
{
drm_ctx_res32_t __user *argp = (void __user *)arg;
drm_ctx_res32_t res32;
- drm_ctx_res_t __user *res;
+ struct drm_ctx_res __user *res;
int err;
if (copy_from_user(&res32, argp, sizeof(res32)))
@@ -658,7 +658,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
return -EFAULT;
if (__put_user(res32.count, &res->count)
- || __put_user((drm_ctx_t __user *) (unsigned long)res32.contexts,
+ || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
&res->contexts))
return -EFAULT;
@@ -679,7 +679,7 @@ typedef struct drm_dma32 {
int send_count; /**< Number of buffers to send */
u32 send_indices; /**< List of handles to buffers */
u32 send_sizes; /**< Lengths of data to send */
- drm_dma_flags_t flags; /**< Flags */
+ enum drm_dma_flags flags; /**< Flags */
int request_count; /**< Number of buffers requested */
int request_size; /**< Desired size for buffers */
u32 request_indices; /**< Buffer information */
@@ -692,7 +692,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
{
drm_dma32_t d32;
drm_dma32_t __user *argp = (void __user *)arg;
- drm_dma_t __user *d;
+ struct drm_dma __user *d;
int err;
if (copy_from_user(&d32, argp, sizeof(d32)))
@@ -740,7 +740,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
{
drm_agp_mode32_t __user *argp = (void __user *)arg;
drm_agp_mode32_t m32;
- drm_agp_mode_t __user *mode;
+ struct drm_agp_mode __user *mode;
if (get_user(m32.mode, &argp->mode))
return -EFAULT;
@@ -772,7 +772,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
{
drm_agp_info32_t __user *argp = (void __user *)arg;
drm_agp_info32_t i32;
- drm_agp_info_t __user *info;
+ struct drm_agp_info __user *info;
int err;
info = compat_alloc_user_space(sizeof(*info));
@@ -813,7 +813,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
{
drm_agp_buffer32_t __user *argp = (void __user *)arg;
drm_agp_buffer32_t req32;
- drm_agp_buffer_t __user *request;
+ struct drm_agp_buffer __user *request;
int err;
if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -845,7 +845,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_agp_buffer32_t __user *argp = (void __user *)arg;
- drm_agp_buffer_t __user *request;
+ struct drm_agp_buffer __user *request;
u32 handle;
request = compat_alloc_user_space(sizeof(*request));
@@ -868,7 +868,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
{
drm_agp_binding32_t __user *argp = (void __user *)arg;
drm_agp_binding32_t req32;
- drm_agp_binding_t __user *request;
+ struct drm_agp_binding __user *request;
if (copy_from_user(&req32, argp, sizeof(req32)))
return -EFAULT;
@@ -887,7 +887,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_agp_binding32_t __user *argp = (void __user *)arg;
- drm_agp_binding_t __user *request;
+ struct drm_agp_binding __user *request;
u32 handle;
request = compat_alloc_user_space(sizeof(*request));
@@ -910,7 +910,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_scatter_gather32_t __user *argp = (void __user *)arg;
- drm_scatter_gather_t __user *request;
+ struct drm_scatter_gather __user *request;
int err;
unsigned long x;
@@ -938,7 +938,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_scatter_gather32_t __user *argp = (void __user *)arg;
- drm_scatter_gather_t __user *request;
+ struct drm_scatter_gather __user *request;
unsigned long x;
request = compat_alloc_user_space(sizeof(*request));
@@ -953,13 +953,13 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
}
struct drm_wait_vblank_request32 {
- drm_vblank_seq_type_t type;
+ enum drm_vblank_seq_type type;
unsigned int sequence;
u32 signal;
};
struct drm_wait_vblank_reply32 {
- drm_vblank_seq_type_t type;
+ enum drm_vblank_seq_type type;
unsigned int sequence;
s32 tval_sec;
s32 tval_usec;
@@ -975,7 +975,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
{
drm_wait_vblank32_t __user *argp = (void __user *)arg;
drm_wait_vblank32_t req32;
- drm_wait_vblank_t __user *request;
+ union drm_wait_vblank __user *request;
int err;
if (copy_from_user(&req32, argp, sizeof(req32)))
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 565895547d75..b195e102e737 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -52,10 +52,10 @@
int drm_getunique(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_unique_t __user *argp = (void __user *)arg;
- drm_unique_t u;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_unique __user *argp = (void __user *)arg;
+ struct drm_unique u;
if (copy_from_user(&u, argp, sizeof(u)))
return -EFAULT;
@@ -86,15 +86,15 @@ int drm_getunique(struct inode *inode, struct file *filp,
int drm_setunique(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_unique_t u;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_unique u;
int domain, bus, slot, func, ret;
if (dev->unique_len || dev->unique)
return -EBUSY;
- if (copy_from_user(&u, (drm_unique_t __user *) arg, sizeof(u)))
+ if (copy_from_user(&u, (struct drm_unique __user *) arg, sizeof(u)))
return -EFAULT;
if (!u.unique_len || u.unique_len > 1024)
@@ -136,7 +136,7 @@ int drm_setunique(struct inode *inode, struct file *filp,
return 0;
}
-static int drm_set_busid(drm_device_t * dev)
+static int drm_set_busid(struct drm_device * dev)
{
int len;
@@ -184,11 +184,11 @@ static int drm_set_busid(drm_device_t * dev)
int drm_getmap(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t __user *argp = (void __user *)arg;
- drm_map_t map;
- drm_map_list_t *r_list = NULL;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_map __user *argp = (void __user *)arg;
+ struct drm_map map;
+ struct drm_map_list *r_list = NULL;
struct list_head *list;
int idx;
int i;
@@ -204,9 +204,9 @@ int drm_getmap(struct inode *inode, struct file *filp,
}
i = 0;
- list_for_each(list, &dev->maplist->head) {
+ list_for_each(list, &dev->maplist) {
if (i == idx) {
- r_list = list_entry(list, drm_map_list_t, head);
+ r_list = list_entry(list, struct drm_map_list, head);
break;
}
i++;
@@ -245,11 +245,11 @@ int drm_getmap(struct inode *inode, struct file *filp,
int drm_getclient(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_client_t __user *argp = (drm_client_t __user *)arg;
- drm_client_t client;
- drm_file_t *pt;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_client __user *argp = (struct drm_client __user *)arg;
+ struct drm_client client;
+ struct drm_file *pt;
int idx;
int i;
@@ -257,12 +257,18 @@ int drm_getclient(struct inode *inode, struct file *filp,
return -EFAULT;
idx = client.idx;
mutex_lock(&dev->struct_mutex);
- for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
-
- if (!pt) {
+
+ if (list_empty(&dev->filelist)) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
+
+ i = 0;
+ list_for_each_entry(pt, &dev->filelist, lhead) {
+ if (i++ >= idx)
+ break;
+ }
+
client.auth = pt->authenticated;
client.pid = pt->pid;
client.uid = pt->uid;
@@ -288,9 +294,9 @@ int drm_getclient(struct inode *inode, struct file *filp,
int drm_getstats(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_stats_t stats;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_stats stats;
int i;
memset(&stats, 0, sizeof(stats));
@@ -310,7 +316,7 @@ int drm_getstats(struct inode *inode, struct file *filp,
mutex_unlock(&dev->struct_mutex);
- if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
+ if (copy_to_user((struct drm_stats __user *) arg, &stats, sizeof(stats)))
return -EFAULT;
return 0;
}
@@ -329,10 +335,10 @@ int drm_getstats(struct inode *inode, struct file *filp,
int drm_setversion(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_set_version_t sv;
- drm_set_version_t retv;
+ struct drm_set_version sv;
+ struct drm_set_version retv;
int if_version;
- drm_set_version_t __user *argp = (void __user *)data;
+ struct drm_set_version __user *argp = (void __user *)data;
int ret;
if (copy_from_user(&sv, argp, sizeof(sv)))
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 2e75331fd83e..871d2fde09b3 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -53,10 +53,10 @@
int drm_irq_by_busid(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_irq_busid_t __user *argp = (void __user *)arg;
- drm_irq_busid_t p;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_irq_busid __user *argp = (void __user *)arg;
+ struct drm_irq_busid p;
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return -EINVAL;
@@ -87,7 +87,7 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
* before and after the installation.
*/
-static int drm_irq_install(drm_device_t * dev)
+static int drm_irq_install(struct drm_device * dev)
{
int ret;
unsigned long sh_flags = 0;
@@ -120,8 +120,8 @@ static int drm_irq_install(drm_device_t * dev)
spin_lock_init(&dev->vbl_lock);
- INIT_LIST_HEAD(&dev->vbl_sigs.head);
- INIT_LIST_HEAD(&dev->vbl_sigs2.head);
+ INIT_LIST_HEAD(&dev->vbl_sigs);
+ INIT_LIST_HEAD(&dev->vbl_sigs2);
dev->vbl_pending = 0;
}
@@ -155,7 +155,7 @@ static int drm_irq_install(drm_device_t * dev)
*
* Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
*/
-int drm_irq_uninstall(drm_device_t * dev)
+int drm_irq_uninstall(struct drm_device * dev)
{
int irq_enabled;
@@ -197,13 +197,13 @@ EXPORT_SYMBOL(drm_irq_uninstall);
int drm_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_control_t ctl;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_control ctl;
/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
- if (copy_from_user(&ctl, (drm_control_t __user *) arg, sizeof(ctl)))
+ if (copy_from_user(&ctl, (struct drm_control __user *) arg, sizeof(ctl)))
return -EFAULT;
switch (ctl.func) {
@@ -244,10 +244,10 @@ int drm_control(struct inode *inode, struct file *filp,
*/
int drm_wait_vblank(DRM_IOCTL_ARGS)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_wait_vblank_t __user *argp = (void __user *)data;
- drm_wait_vblank_t vblwait;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ union drm_wait_vblank __user *argp = (void __user *)data;
+ union drm_wait_vblank vblwait;
struct timeval now;
int ret = 0;
unsigned int flags, seq;
@@ -292,9 +292,9 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
if (flags & _DRM_VBLANK_SIGNAL) {
unsigned long irqflags;
- drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+ struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
? &dev->vbl_sigs2 : &dev->vbl_sigs;
- drm_vbl_sig_t *vbl_sig;
+ struct drm_vbl_sig *vbl_sig;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -302,7 +302,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
* for the same vblank sequence number; nothing to be done in
* that case
*/
- list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
+ list_for_each_entry(vbl_sig, vbl_sigs, head) {
if (vbl_sig->sequence == vblwait.request.sequence
&& vbl_sig->info.si_signo == vblwait.request.signal
&& vbl_sig->task == current) {
@@ -324,7 +324,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
if (!
(vbl_sig =
- drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
+ drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
return -ENOMEM;
}
@@ -336,7 +336,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
spin_lock_irqsave(&dev->vbl_lock, irqflags);
- list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
+ list_add_tail(&vbl_sig->head, vbl_sigs);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -371,7 +371,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
*
* If a signal is not requested, then calls vblank_wait().
*/
-void drm_vbl_send_signals(drm_device_t * dev)
+void drm_vbl_send_signals(struct drm_device * dev)
{
unsigned long flags;
int i;
@@ -379,20 +379,18 @@ void drm_vbl_send_signals(drm_device_t * dev)
spin_lock_irqsave(&dev->vbl_lock, flags);
for (i = 0; i < 2; i++) {
- struct list_head *list, *tmp;
- drm_vbl_sig_t *vbl_sig;
- drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+ struct drm_vbl_sig *vbl_sig, *tmp;
+ struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
&dev->vbl_received);
- list_for_each_safe(list, tmp, &vbl_sigs->head) {
- vbl_sig = list_entry(list, drm_vbl_sig_t, head);
+ list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
vbl_sig->info.si_code = vbl_seq;
send_sig_info(vbl_sig->info.si_signo,
&vbl_sig->info, vbl_sig->task);
- list_del(list);
+ list_del(&vbl_sig->head);
drm_free(vbl_sig, sizeof(*vbl_sig),
DRM_MEM_DRIVER);
@@ -418,7 +416,7 @@ EXPORT_SYMBOL(drm_vbl_send_signals);
*/
static void drm_locked_tasklet_func(unsigned long data)
{
- drm_device_t *dev = (drm_device_t*)data;
+ struct drm_device *dev = (struct drm_device *)data;
unsigned long irqflags;
spin_lock_irqsave(&dev->tasklet_lock, irqflags);
@@ -455,7 +453,7 @@ static void drm_locked_tasklet_func(unsigned long data)
* context, it must not make any assumptions about this. Also, the HW lock will
* be held with the kernel context or any client context.
*/
-void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*))
+void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *))
{
unsigned long irqflags;
static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index befd1af19dfe..c0534b5a8b78 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -51,15 +51,15 @@ static int drm_notifier(void *priv);
int drm_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
DECLARE_WAITQUEUE(entry, current);
- drm_lock_t lock;
+ struct drm_lock lock;
int ret = 0;
++priv->lock_count;
- if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+ if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock)))
return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -152,12 +152,12 @@ int drm_lock(struct inode *inode, struct file *filp,
int drm_unlock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_lock_t lock;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_lock lock;
unsigned long irqflags;
- if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+ if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock)))
return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -202,7 +202,7 @@ int drm_unlock(struct inode *inode, struct file *filp,
*
* Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
*/
-int drm_lock_take(drm_lock_data_t *lock_data,
+int drm_lock_take(struct drm_lock_data *lock_data,
unsigned int context)
{
unsigned int old, new, prev;
@@ -251,7 +251,7 @@ int drm_lock_take(drm_lock_data_t *lock_data,
* Resets the lock file pointer.
* Marks the lock as held by the given context, via the \p cmpxchg instruction.
*/
-static int drm_lock_transfer(drm_lock_data_t *lock_data,
+static int drm_lock_transfer(struct drm_lock_data *lock_data,
unsigned int context)
{
unsigned int old, new, prev;
@@ -277,7 +277,7 @@ static int drm_lock_transfer(drm_lock_data_t *lock_data,
* Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
* waiting on the lock queue.
*/
-int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
+int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
{
unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock;
@@ -319,7 +319,7 @@ int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
*/
static int drm_notifier(void *priv)
{
- drm_sigdata_t *s = (drm_sigdata_t *) priv;
+ struct drm_sigdata *s = (struct drm_sigdata *) priv;
unsigned int old, new, prev;
/* Allow signal delivery if lock isn't held */
@@ -350,7 +350,7 @@ static int drm_notifier(void *priv)
* having to worry about starvation.
*/
-void drm_idlelock_take(drm_lock_data_t *lock_data)
+void drm_idlelock_take(struct drm_lock_data *lock_data)
{
int ret = 0;
@@ -369,7 +369,7 @@ void drm_idlelock_take(drm_lock_data_t *lock_data)
}
EXPORT_SYMBOL(drm_idlelock_take);
-void drm_idlelock_release(drm_lock_data_t *lock_data)
+void drm_idlelock_release(struct drm_lock_data *lock_data)
{
unsigned int old, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 92a867082376..93019901bd30 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -80,7 +80,7 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
#if __OS_HAS_AGP
static void *agp_remap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
+ struct drm_device * dev)
{
unsigned long *phys_addr_map, i, num_pages =
PAGE_ALIGN(size) / PAGE_SIZE;
@@ -94,7 +94,7 @@ static void *agp_remap(unsigned long offset, unsigned long size,
offset -= dev->hose->mem_space->start;
#endif
- for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+ list_for_each_entry(agpmem, &dev->agp->memory, head)
if (agpmem->bound <= offset
&& (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
(offset + size))
@@ -123,7 +123,7 @@ static void *agp_remap(unsigned long offset, unsigned long size,
}
/** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type)
{
return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
}
@@ -148,7 +148,7 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
#else /* __OS_HAS_AGP */
static inline void *agp_remap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
+ struct drm_device * dev)
{
return NULL;
}
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
index 2ec1d9f26264..3e6bc14f7441 100644
--- a/drivers/char/drm/drm_mm.c
+++ b/drivers/char/drm/drm_mm.c
@@ -44,26 +44,26 @@
#include "drmP.h"
#include <linux/slab.h>
-unsigned long drm_mm_tail_space(drm_mm_t *mm)
+unsigned long drm_mm_tail_space(struct drm_mm *mm)
{
struct list_head *tail_node;
- drm_mm_node_t *entry;
+ struct drm_mm_node *entry;
tail_node = mm->ml_entry.prev;
- entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+ entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
if (!entry->free)
return 0;
return entry->size;
}
-int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
{
struct list_head *tail_node;
- drm_mm_node_t *entry;
+ struct drm_mm_node *entry;
tail_node = mm->ml_entry.prev;
- entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+ entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
if (!entry->free)
return -ENOMEM;
@@ -75,13 +75,13 @@ int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
}
-static int drm_mm_create_tail_node(drm_mm_t *mm,
+static int drm_mm_create_tail_node(struct drm_mm *mm,
unsigned long start,
unsigned long size)
{
- drm_mm_node_t *child;
+ struct drm_mm_node *child;
- child = (drm_mm_node_t *)
+ child = (struct drm_mm_node *)
drm_alloc(sizeof(*child), DRM_MEM_MM);
if (!child)
return -ENOMEM;
@@ -98,13 +98,13 @@ static int drm_mm_create_tail_node(drm_mm_t *mm,
}
-int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
{
struct list_head *tail_node;
- drm_mm_node_t *entry;
+ struct drm_mm_node *entry;
tail_node = mm->ml_entry.prev;
- entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+ entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
if (!entry->free) {
return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
}
@@ -112,12 +112,12 @@ int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
return 0;
}
-static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
+static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
unsigned long size)
{
- drm_mm_node_t *child;
+ struct drm_mm_node *child;
- child = (drm_mm_node_t *)
+ child = (struct drm_mm_node *)
drm_alloc(sizeof(*child), DRM_MEM_MM);
if (!child)
return NULL;
@@ -139,12 +139,12 @@ static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
-drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
unsigned long size, unsigned alignment)
{
- drm_mm_node_t *align_splitoff = NULL;
- drm_mm_node_t *child;
+ struct drm_mm_node *align_splitoff = NULL;
+ struct drm_mm_node *child;
unsigned tmp = 0;
if (alignment)
@@ -175,26 +175,26 @@ drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
* Otherwise add to the free stack.
*/
-void drm_mm_put_block(drm_mm_node_t * cur)
+void drm_mm_put_block(struct drm_mm_node * cur)
{
- drm_mm_t *mm = cur->mm;
+ struct drm_mm *mm = cur->mm;
struct list_head *cur_head = &cur->ml_entry;
struct list_head *root_head = &mm->ml_entry;
- drm_mm_node_t *prev_node = NULL;
- drm_mm_node_t *next_node;
+ struct drm_mm_node *prev_node = NULL;
+ struct drm_mm_node *next_node;
int merged = 0;
if (cur_head->prev != root_head) {
- prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry);
+ prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
if (prev_node->free) {
prev_node->size += cur->size;
merged = 1;
}
}
if (cur_head->next != root_head) {
- next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry);
+ next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
if (next_node->free) {
if (merged) {
prev_node->size += next_node->size;
@@ -218,14 +218,14 @@ void drm_mm_put_block(drm_mm_node_t * cur)
}
}
-drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
+struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
unsigned long size,
unsigned alignment, int best_match)
{
struct list_head *list;
const struct list_head *free_stack = &mm->fl_entry;
- drm_mm_node_t *entry;
- drm_mm_node_t *best;
+ struct drm_mm_node *entry;
+ struct drm_mm_node *best;
unsigned long best_size;
unsigned wasted;
@@ -233,7 +233,7 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
best_size = ~0UL;
list_for_each(list, free_stack) {
- entry = list_entry(list, drm_mm_node_t, fl_entry);
+ entry = list_entry(list, struct drm_mm_node, fl_entry);
wasted = 0;
if (entry->size < size)
@@ -259,14 +259,14 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
return best;
}
-int drm_mm_clean(drm_mm_t * mm)
+int drm_mm_clean(struct drm_mm * mm)
{
struct list_head *head = &mm->ml_entry;
return (head->next->next == head);
}
-int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
+int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
{
INIT_LIST_HEAD(&mm->ml_entry);
INIT_LIST_HEAD(&mm->fl_entry);
@@ -275,12 +275,12 @@ int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
}
-void drm_mm_takedown(drm_mm_t * mm)
+void drm_mm_takedown(struct drm_mm * mm)
{
struct list_head *bnode = mm->fl_entry.next;
- drm_mm_node_t *entry;
+ struct drm_mm_node *entry;
- entry = list_entry(bnode, drm_mm_node_t, fl_entry);
+ entry = list_entry(bnode, struct drm_mm_node, fl_entry);
if (entry->ml_entry.next != &mm->ml_entry ||
entry->fl_entry.next != &mm->fl_entry) {
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 0fe7b4497927..0b8d3433386d 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -34,8 +34,8 @@
/** Read/write memory barrier */
#define DRM_MEMORYBARRIER() mb()
/** DRM device local declaration */
-#define DRM_DEVICE drm_file_t *priv = filp->private_data; \
- drm_device_t *dev = priv->head->dev
+#define DRM_DEVICE struct drm_file *priv = filp->private_data; \
+ struct drm_device *dev = priv->head->dev
/** IRQ handler arguments and return type and values */
#define DRM_IRQ_ARGS int irq, void *arg
@@ -96,24 +96,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
-/**
- * Get the pointer to the SAREA.
- *
- * Searches the SAREA on the mapping lists and points drm_device::sarea to it.
- */
-#define DRM_GETSAREA() \
-do { \
- drm_map_list_t *entry; \
- list_for_each_entry( entry, &dev->maplist->head, head ) { \
- if ( entry->map && \
- entry->map->type == _DRM_SHM && \
- (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \
- dev_priv->sarea = entry->map; \
- break; \
- } \
- } \
-} while (0)
-
#define DRM_HZ HZ
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 86a0f1c22091..e292bb0eaca2 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -47,7 +47,7 @@
/**
* \brief Allocate a PCI consistent memory block, for DMA.
*/
-drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
dma_addr_t maxaddr)
{
drm_dma_handle_t *dmah;
@@ -126,7 +126,7 @@ EXPORT_SYMBOL(drm_pci_alloc);
*
* This function is for internal use in the Linux-specific DRM core code.
*/
-void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
{
#if 1
unsigned long addr;
@@ -172,7 +172,7 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
/**
* \brief Free a PCI consistent memory block
*/
-void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
{
__drm_pci_free(dev, dmah);
kfree(dmah);
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index b204498d1a28..12dfea89c7f3 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -87,7 +87,7 @@ static struct drm_proc_list {
* "/proc/dri/%minor%/", and each entry in proc_list as
* "/proc/dri/%minor%/%name%".
*/
-int drm_proc_init(drm_device_t * dev, int minor,
+int drm_proc_init(struct drm_device * dev, int minor,
struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
{
struct proc_dir_entry *ent;
@@ -163,7 +163,7 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
static int drm_name_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int len = 0;
if (offset > DRM_PROC_LIMIT) {
@@ -205,11 +205,10 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
static int drm__vm_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int len = 0;
- drm_map_t *map;
- drm_map_list_t *r_list;
- struct list_head *list;
+ struct drm_map *map;
+ struct drm_map_list *r_list;
/* Hardcoded from _DRM_FRAME_BUFFER,
_DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
@@ -229,9 +228,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("slot offset size type flags "
"address mtrr\n\n");
i = 0;
- if (dev->maplist != NULL)
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
map = r_list->map;
if (!map)
continue;
@@ -242,14 +239,15 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ",
i,
map->offset,
- map->size, type, map->flags, r_list->user_token);
+ map->size, type, map->flags,
+ r_list->user_token);
if (map->mtrr < 0) {
DRM_PROC_PRINT("none\n");
} else {
DRM_PROC_PRINT("%4d\n", map->mtrr);
}
i++;
- }
+ }
if (len > request + offset)
return request;
@@ -263,7 +261,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
static int drm_vm_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int ret;
mutex_lock(&dev->struct_mutex);
@@ -286,10 +284,10 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
static int drm__queues_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int len = 0;
int i;
- drm_queue_t *q;
+ struct drm_queue *q;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -336,7 +334,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
static int drm_queues_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int ret;
mutex_lock(&dev->struct_mutex);
@@ -359,9 +357,9 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int len = 0;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
if (!dma || offset > DRM_PROC_LIMIT) {
@@ -408,7 +406,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int ret;
mutex_lock(&dev->struct_mutex);
@@ -431,9 +429,9 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
static int drm__clients_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int len = 0;
- drm_file_t *priv;
+ struct drm_file *priv;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@@ -444,7 +442,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
*eof = 0;
DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
- for (priv = dev->file_first; priv; priv = priv->next) {
+ list_for_each_entry(priv, &dev->filelist, lhead) {
DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
priv->authenticated ? 'y' : 'n',
priv->minor,
@@ -464,7 +462,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
static int drm_clients_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int ret;
mutex_lock(&dev->struct_mutex);
@@ -478,9 +476,9 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
static int drm__vma_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int len = 0;
- drm_vma_entry_t *pt;
+ struct drm_vma_entry *pt;
struct vm_area_struct *vma;
#if defined(__i386__)
unsigned int pgprot;
@@ -497,7 +495,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
atomic_read(&dev->vma_count),
high_memory, virt_to_phys(high_memory));
- for (pt = dev->vmalist; pt; pt = pt->next) {
+ list_for_each_entry(pt, &dev->vmalist, head) {
if (!(vma = pt->vma))
continue;
DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
@@ -537,7 +535,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
static int drm_vma_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
- drm_device_t *dev = (drm_device_t *) data;
+ struct drm_device *dev = (struct drm_device *) data;
int ret;
mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
index e94297b751b8..f5466966081e 100644
--- a/drivers/char/drm/drm_sarea.h
+++ b/drivers/char/drm/drm_sarea.h
@@ -50,29 +50,35 @@
#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000
/** SAREA drawable */
-typedef struct drm_sarea_drawable {
+struct drm_sarea_drawable {
unsigned int stamp;
unsigned int flags;
-} drm_sarea_drawable_t;
+};
/** SAREA frame */
-typedef struct drm_sarea_frame {
+struct drm_sarea_frame {
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
unsigned int fullscreen;
-} drm_sarea_frame_t;
+};
/** SAREA */
-typedef struct drm_sarea {
+struct drm_sarea {
/** first thing is always the DRM locking structure */
- drm_hw_lock_t lock;
+ struct drm_hw_lock lock;
/** \todo Use readers/writer lock for drm_sarea::drawable_lock */
- drm_hw_lock_t drawable_lock;
- drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
- drm_sarea_frame_t frame; /**< frame */
+ struct drm_hw_lock drawable_lock;
+ struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
+ struct drm_sarea_frame frame; /**< frame */
drm_context_t dummy_context;
-} drm_sarea_t;
+};
+
+#ifndef __KERNEL__
+typedef struct drm_sarea_drawable drm_sarea_drawable_t;
+typedef struct drm_sarea_frame drm_sarea_frame_t;
+typedef struct drm_sarea drm_sarea_t;
+#endif
#endif /* _DRM_SAREA_H_ */
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
index 06ef7ddbe67d..067d25daaf17 100644
--- a/drivers/char/drm/drm_scatter.c
+++ b/drivers/char/drm/drm_scatter.c
@@ -36,7 +36,7 @@
#define DEBUG_SCATTER 0
-void drm_sg_cleanup(drm_sg_mem_t * entry)
+void drm_sg_cleanup(struct drm_sg_mem * entry)
{
struct page *page;
int i;
@@ -65,11 +65,11 @@ void drm_sg_cleanup(drm_sg_mem_t * entry)
int drm_sg_alloc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_scatter_gather_t __user *argp = (void __user *)arg;
- drm_scatter_gather_t request;
- drm_sg_mem_t *entry;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_scatter_gather __user *argp = (void __user *)arg;
+ struct drm_scatter_gather request;
+ struct drm_sg_mem *entry;
unsigned long pages, i, j;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -201,16 +201,16 @@ int drm_sg_alloc(struct inode *inode, struct file *filp,
int drm_sg_free(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_scatter_gather_t request;
- drm_sg_mem_t *entry;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_scatter_gather request;
+ struct drm_sg_mem *entry;
if (!drm_core_check_feature(dev, DRIVER_SG))
return -EINVAL;
if (copy_from_user(&request,
- (drm_scatter_gather_t __user *) arg,
+ (struct drm_scatter_gather __user *) arg,
sizeof(request)))
return -EFAULT;
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
index e15db6d6bea9..8421a93946d8 100644
--- a/drivers/char/drm/drm_sman.c
+++ b/drivers/char/drm/drm_sman.c
@@ -38,13 +38,13 @@
#include "drm_sman.h"
-typedef struct drm_owner_item {
- drm_hash_item_t owner_hash;
+struct drm_owner_item {
+ struct drm_hash_item owner_hash;
struct list_head sman_list;
struct list_head mem_blocks;
-} drm_owner_item_t;
+};
-void drm_sman_takedown(drm_sman_t * sman)
+void drm_sman_takedown(struct drm_sman * sman)
{
drm_ht_remove(&sman->user_hash_tab);
drm_ht_remove(&sman->owner_hash_tab);
@@ -56,12 +56,12 @@ void drm_sman_takedown(drm_sman_t * sman)
EXPORT_SYMBOL(drm_sman_takedown);
int
-drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
unsigned int user_order, unsigned int owner_order)
{
int ret = 0;
- sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm),
+ sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
DRM_MEM_MM);
if (!sman->mm) {
ret = -ENOMEM;
@@ -88,8 +88,8 @@ EXPORT_SYMBOL(drm_sman_init);
static void *drm_sman_mm_allocate(void *private, unsigned long size,
unsigned alignment)
{
- drm_mm_t *mm = (drm_mm_t *) private;
- drm_mm_node_t *tmp;
+ struct drm_mm *mm = (struct drm_mm *) private;
+ struct drm_mm_node *tmp;
tmp = drm_mm_search_free(mm, size, alignment, 1);
if (!tmp) {
@@ -101,30 +101,30 @@ static void *drm_sman_mm_allocate(void *private, unsigned long size,
static void drm_sman_mm_free(void *private, void *ref)
{
- drm_mm_node_t *node = (drm_mm_node_t *) ref;
+ struct drm_mm_node *node = (struct drm_mm_node *) ref;
drm_mm_put_block(node);
}
static void drm_sman_mm_destroy(void *private)
{
- drm_mm_t *mm = (drm_mm_t *) private;
+ struct drm_mm *mm = (struct drm_mm *) private;
drm_mm_takedown(mm);
drm_free(mm, sizeof(*mm), DRM_MEM_MM);
}
static unsigned long drm_sman_mm_offset(void *private, void *ref)
{
- drm_mm_node_t *node = (drm_mm_node_t *) ref;
+ struct drm_mm_node *node = (struct drm_mm_node *) ref;
return node->start;
}
int
-drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
unsigned long start, unsigned long size)
{
- drm_sman_mm_t *sman_mm;
- drm_mm_t *mm;
+ struct drm_sman_mm *sman_mm;
+ struct drm_mm *mm;
int ret;
BUG_ON(manager >= sman->num_managers);
@@ -153,8 +153,8 @@ drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
EXPORT_SYMBOL(drm_sman_set_range);
int
-drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
- drm_sman_mm_t * allocator)
+drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
+ struct drm_sman_mm * allocator)
{
BUG_ON(manager >= sman->num_managers);
sman->mm[manager] = *allocator;
@@ -163,16 +163,16 @@ drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
}
EXPORT_SYMBOL(drm_sman_set_manager);
-static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
+static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
unsigned long owner)
{
int ret;
- drm_hash_item_t *owner_hash_item;
- drm_owner_item_t *owner_item;
+ struct drm_hash_item *owner_hash_item;
+ struct drm_owner_item *owner_item;
ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
if (!ret) {
- return drm_hash_entry(owner_hash_item, drm_owner_item_t,
+ return drm_hash_entry(owner_hash_item, struct drm_owner_item,
owner_hash);
}
@@ -194,14 +194,14 @@ out:
return NULL;
}
-drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager,
+struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
unsigned long size, unsigned alignment,
unsigned long owner)
{
void *tmp;
- drm_sman_mm_t *sman_mm;
- drm_owner_item_t *owner_item;
- drm_memblock_item_t *memblock;
+ struct drm_sman_mm *sman_mm;
+ struct drm_owner_item *owner_item;
+ struct drm_memblock_item *memblock;
BUG_ON(manager >= sman->num_managers);
@@ -246,9 +246,9 @@ out:
EXPORT_SYMBOL(drm_sman_alloc);
-static void drm_sman_free(drm_memblock_item_t *item)
+static void drm_sman_free(struct drm_memblock_item *item)
{
- drm_sman_t *sman = item->sman;
+ struct drm_sman *sman = item->sman;
list_del(&item->owner_list);
drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
@@ -256,40 +256,41 @@ static void drm_sman_free(drm_memblock_item_t *item)
drm_free(item, sizeof(*item), DRM_MEM_MM);
}
-int drm_sman_free_key(drm_sman_t *sman, unsigned int key)
+int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
{
- drm_hash_item_t *hash_item;
- drm_memblock_item_t *memblock_item;
+ struct drm_hash_item *hash_item;
+ struct drm_memblock_item *memblock_item;
if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
return -EINVAL;
- memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash);
+ memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
+ user_hash);
drm_sman_free(memblock_item);
return 0;
}
EXPORT_SYMBOL(drm_sman_free_key);
-static void drm_sman_remove_owner(drm_sman_t *sman,
- drm_owner_item_t *owner_item)
+static void drm_sman_remove_owner(struct drm_sman *sman,
+ struct drm_owner_item *owner_item)
{
list_del(&owner_item->sman_list);
drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
}
-int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
+int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
{
- drm_hash_item_t *hash_item;
- drm_owner_item_t *owner_item;
+ struct drm_hash_item *hash_item;
+ struct drm_owner_item *owner_item;
if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
return -1;
}
- owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+ owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
drm_sman_remove_owner(sman, owner_item);
return -1;
@@ -300,10 +301,10 @@ int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
EXPORT_SYMBOL(drm_sman_owner_clean);
-static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
- drm_owner_item_t *owner_item)
+static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
+ struct drm_owner_item *owner_item)
{
- drm_memblock_item_t *entry, *next;
+ struct drm_memblock_item *entry, *next;
list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
owner_list) {
@@ -312,28 +313,28 @@ static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
drm_sman_remove_owner(sman, owner_item);
}
-void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner)
+void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
{
- drm_hash_item_t *hash_item;
- drm_owner_item_t *owner_item;
+ struct drm_hash_item *hash_item;
+ struct drm_owner_item *owner_item;
if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
return;
}
- owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+ owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
drm_sman_do_owner_cleanup(sman, owner_item);
}
EXPORT_SYMBOL(drm_sman_owner_cleanup);
-void drm_sman_cleanup(drm_sman_t *sman)
+void drm_sman_cleanup(struct drm_sman *sman)
{
- drm_owner_item_t *entry, *next;
+ struct drm_owner_item *entry, *next;
unsigned int i;
- drm_sman_mm_t *sman_mm;
+ struct drm_sman_mm *sman_mm;
list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
drm_sman_do_owner_cleanup(sman, entry);
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
index ddc732a1bf27..39a39fefeef1 100644
--- a/drivers/char/drm/drm_sman.h
+++ b/drivers/char/drm/drm_sman.h
@@ -50,7 +50,7 @@
* for memory management.
*/
-typedef struct drm_sman_mm {
+struct drm_sman_mm {
/* private info. If allocated, needs to be destroyed by the destroy
function */
void *private;
@@ -74,30 +74,30 @@ typedef struct drm_sman_mm {
"alloc" function */
unsigned long (*offset) (void *private, void *ref);
-} drm_sman_mm_t;
+};
-typedef struct drm_memblock_item {
+struct drm_memblock_item {
struct list_head owner_list;
- drm_hash_item_t user_hash;
+ struct drm_hash_item user_hash;
void *mm_info;
- drm_sman_mm_t *mm;
+ struct drm_sman_mm *mm;
struct drm_sman *sman;
-} drm_memblock_item_t;
+};
-typedef struct drm_sman {
- drm_sman_mm_t *mm;
+struct drm_sman {
+ struct drm_sman_mm *mm;
int num_managers;
- drm_open_hash_t owner_hash_tab;
- drm_open_hash_t user_hash_tab;
+ struct drm_open_hash owner_hash_tab;
+ struct drm_open_hash user_hash_tab;
struct list_head owner_items;
-} drm_sman_t;
+};
/*
* Take down a memory manager. This function should only be called after a
* successful init and after a call to drm_sman_cleanup.
*/
-extern void drm_sman_takedown(drm_sman_t * sman);
+extern void drm_sman_takedown(struct drm_sman * sman);
/*
* Allocate structures for a manager.
@@ -112,7 +112,7 @@ extern void drm_sman_takedown(drm_sman_t * sman);
*
*/
-extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
unsigned int user_order, unsigned int owner_order);
/*
@@ -120,7 +120,7 @@ extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
* manager unless a customized allogator is used.
*/
-extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
unsigned long start, unsigned long size);
/*
@@ -129,23 +129,23 @@ extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
* so it can be destroyed after this call.
*/
-extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger,
- drm_sman_mm_t * allocator);
+extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
+ struct drm_sman_mm * allocator);
/*
* Allocate a memory block. Aligment is not implemented yet.
*/
-extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman,
- unsigned int manager,
- unsigned long size,
- unsigned alignment,
- unsigned long owner);
+extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
+ unsigned int manager,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long owner);
/*
* Free a memory block identified by its user hash key.
*/
-extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
+extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
/*
* returns 1 iff there are no stale memory blocks associated with this owner.
@@ -154,7 +154,7 @@ extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
* resources associated with owner.
*/
-extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
+extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
/*
* Frees all stale memory blocks associated with this owner. Note that this
@@ -164,13 +164,13 @@ extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
* is not going to be referenced anymore.
*/
-extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner);
+extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
/*
* Frees all stale memory blocks associated with the memory manager.
* See idling above.
*/
-extern void drm_sman_cleanup(drm_sman_t * sman);
+extern void drm_sman_cleanup(struct drm_sman * sman);
#endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 19408adcc775..ee83ff9efed6 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -49,16 +49,21 @@ MODULE_PARM_DESC(debug, "Enable debug output");
module_param_named(cards_limit, drm_cards_limit, int, 0444);
module_param_named(debug, drm_debug, int, 0600);
-drm_head_t **drm_heads;
+struct drm_head **drm_heads;
struct class *drm_class;
struct proc_dir_entry *drm_proc_root;
-static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
+static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
const struct pci_device_id *ent,
struct drm_driver *driver)
{
int retcode;
+ INIT_LIST_HEAD(&dev->filelist);
+ INIT_LIST_HEAD(&dev->ctxlist);
+ INIT_LIST_HEAD(&dev->vmalist);
+ INIT_LIST_HEAD(&dev->maplist);
+
spin_lock_init(&dev->count_lock);
spin_lock_init(&dev->drw_lock);
spin_lock_init(&dev->tasklet_lock);
@@ -67,6 +72,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex);
+ idr_init(&dev->drw_idr);
+
dev->pdev = pdev;
dev->pci_device = pdev->device;
dev->pci_vendor = pdev->vendor;
@@ -76,12 +83,7 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
#endif
dev->irq = pdev->irq;
- dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
- if (dev->maplist == NULL)
- return -ENOMEM;
- INIT_LIST_HEAD(&dev->maplist->head);
if (drm_ht_create(&dev->map_hash, 12)) {
- drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
return -ENOMEM;
}
@@ -143,9 +145,9 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
* create the proc init entry via proc_init(). This routines assigns
* minor numbers to secondary heads of multi-headed cards
*/
-static int drm_get_head(drm_device_t * dev, drm_head_t * head)
+static int drm_get_head(struct drm_device * dev, struct drm_head * head)
{
- drm_head_t **heads = drm_heads;
+ struct drm_head **heads = drm_heads;
int ret;
int minor;
@@ -154,7 +156,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
if (!*heads) {
- *head = (drm_head_t) {
+ *head = (struct drm_head) {
.dev = dev,.device =
MKDEV(DRM_MAJOR, minor),.minor = minor,};
@@ -184,7 +186,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
err_g2:
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
err_g1:
- *head = (drm_head_t) {
+ *head = (struct drm_head) {
.dev = NULL};
return ret;
}
@@ -203,7 +205,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver)
{
- drm_device_t *dev;
+ struct drm_device *dev;
int ret;
DRM_DEBUG("\n");
@@ -246,7 +248,7 @@ err_g1:
* "drm" data, otherwise unregisters the "drm" data, frees the dev list and
* unregisters the character device.
*/
-int drm_put_dev(drm_device_t * dev)
+int drm_put_dev(struct drm_device * dev)
{
DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
@@ -274,7 +276,7 @@ int drm_put_dev(drm_device_t * dev)
* last minor released.
*
*/
-int drm_put_head(drm_head_t * head)
+int drm_put_head(struct drm_head * head)
{
int minor = head->minor;
@@ -283,7 +285,7 @@ int drm_put_head(drm_head_t * head)
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
drm_sysfs_device_remove(head->dev_class);
- *head = (drm_head_t) {.dev = NULL};
+ *head = (struct drm_head) {.dev = NULL};
drm_heads[minor] = NULL;
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index cc8e2ebe128c..cf4349b00b07 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -80,7 +80,7 @@ void drm_sysfs_destroy(struct class *class)
static ssize_t show_dri(struct class_device *class_device, char *buf)
{
- drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;
+ struct drm_device * dev = ((struct drm_head *)class_get_devdata(class_device))->dev;
if (dev->driver->dri_library_name)
return dev->driver->dri_library_name(dev, buf);
return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
@@ -104,7 +104,7 @@ static struct class_device_attribute class_device_attrs[] = {
* Note: the struct class passed to this function must have previously been
* created with a call to drm_sysfs_create().
*/
-struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
+struct class_device *drm_sysfs_device_add(struct class *cs, struct drm_head *head)
{
struct class_device *class_dev;
int i, j, err;
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index b5c5b9fa84c3..68e36e51ba0c 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -79,11 +79,11 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
unsigned long address)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t *map = NULL;
- drm_map_list_t *r_list;
- drm_hash_item_t *hash;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_map *map = NULL;
+ struct drm_map_list *r_list;
+ struct drm_hash_item *hash;
/*
* Find the right map
@@ -97,7 +97,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
goto vm_nopage_error;
- r_list = drm_hash_entry(hash, drm_map_list_t, hash);
+ r_list = drm_hash_entry(hash, struct drm_map_list, hash);
map = r_list->map;
if (map && map->type == _DRM_AGP) {
@@ -116,7 +116,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
/*
* It's AGP memory - find the real physical page to map
*/
- for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+ list_for_each_entry(agpmem, &dev->agp->memory, head) {
if (agpmem->bound <= baddr &&
agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
break;
@@ -163,7 +163,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
unsigned long address)
{
- drm_map_t *map = (drm_map_t *) vma->vm_private_data;
+ struct drm_map *map = (struct drm_map *) vma->vm_private_data;
unsigned long offset;
unsigned long i;
struct page *page;
@@ -194,12 +194,11 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
*/
static void drm_vm_shm_close(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_vma_entry_t *pt, *prev, *next;
- drm_map_t *map;
- drm_map_list_t *r_list;
- struct list_head *list;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_vma_entry *pt, *temp;
+ struct drm_map *map;
+ struct drm_map_list *r_list;
int found_maps = 0;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -209,30 +208,22 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
map = vma->vm_private_data;
mutex_lock(&dev->struct_mutex);
- for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
- next = pt->next;
+ list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma->vm_private_data == map)
found_maps++;
if (pt->vma == vma) {
- if (prev) {
- prev->next = pt->next;
- } else {
- dev->vmalist = pt->next;
- }
+ list_del(&pt->head);
drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
- } else {
- prev = pt;
}
}
+
/* We were the only map that was found */
if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
/* Check to see if we are in the maplist, if we are not, then
* we delete this mappings information.
*/
found_maps = 0;
- list = &dev->maplist->head;
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map == map)
found_maps++;
}
@@ -283,9 +274,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
unsigned long offset;
unsigned long page_nr;
struct page *page;
@@ -319,10 +310,10 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
unsigned long address)
{
- drm_map_t *map = (drm_map_t *) vma->vm_private_data;
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_sg_mem_t *entry = dev->sg;
+ struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_sg_mem *entry = dev->sg;
unsigned long offset;
unsigned long map_offset;
unsigned long page_offset;
@@ -414,9 +405,9 @@ static struct vm_operations_struct drm_vm_sg_ops = {
*/
static void drm_vm_open_locked(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_vma_entry_t *vma_entry;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_vma_entry *vma_entry;
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
@@ -425,16 +416,15 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) {
vma_entry->vma = vma;
- vma_entry->next = dev->vmalist;
vma_entry->pid = current->pid;
- dev->vmalist = vma_entry;
+ list_add(&vma_entry->head, &dev->vmalist);
}
}
static void drm_vm_open(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
mutex_lock(&dev->struct_mutex);
drm_vm_open_locked(vma);
@@ -451,22 +441,18 @@ static void drm_vm_open(struct vm_area_struct *vma)
*/
static void drm_vm_close(struct vm_area_struct *vma)
{
- drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_vma_entry_t *pt, *prev;
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_vma_entry *pt, *temp;
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_dec(&dev->vma_count);
mutex_lock(&dev->struct_mutex);
- for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+ list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma == vma) {
- if (prev) {
- prev->next = pt->next;
- } else {
- dev->vmalist = pt->next;
- }
+ list_del(&pt->head);
drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
break;
}
@@ -486,9 +472,9 @@ static void drm_vm_close(struct vm_area_struct *vma)
*/
static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
- drm_device_dma_t *dma;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev;
+ struct drm_device_dma *dma;
unsigned long length = vma->vm_end - vma->vm_start;
dev = priv->head->dev;
@@ -526,7 +512,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
return 0;
}
-unsigned long drm_core_get_map_ofs(drm_map_t * map)
+unsigned long drm_core_get_map_ofs(struct drm_map * map)
{
return map->offset;
}
@@ -559,11 +545,11 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
*/
static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_map_t *map = NULL;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_map *map = NULL;
unsigned long offset = 0;
- drm_hash_item_t *hash;
+ struct drm_hash_item *hash;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
vma->vm_start, vma->vm_end, vma->vm_pgoff);
@@ -588,7 +574,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
return -EINVAL;
}
- map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
+ map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
@@ -677,8 +663,8 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
int ret;
mutex_lock(&dev->struct_mutex);
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 603d17fd2d69..cb449999d0ef 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -45,16 +45,16 @@
#define I810_BUF_UNMAPPED 0
#define I810_BUF_MAPPED 1
-static drm_buf_t *i810_freelist_get(drm_device_t * dev)
+static struct drm_buf *i810_freelist_get(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
int used;
/* Linear search might not be the best solution */
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
/* In use is already a pointer */
used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
@@ -70,7 +70,7 @@ static drm_buf_t *i810_freelist_get(drm_device_t * dev)
* yet, the hardware updates in use for us once its on the ring buffer.
*/
-static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
{
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
int used;
@@ -87,10 +87,10 @@ static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev;
drm_i810_private_t *dev_priv;
- drm_buf_t *buf;
+ struct drm_buf *buf;
drm_i810_buf_priv_t *buf_priv;
lock_kernel();
@@ -120,10 +120,10 @@ static const struct file_operations i810_buffer_fops = {
.fasync = drm_fasync,
};
-static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i810_map_buffer(struct drm_buf * buf, struct file *filp)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
drm_i810_private_t *dev_priv = dev->dev_private;
const struct file_operations *old_fops;
@@ -152,7 +152,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
return retcode;
}
-static int i810_unmap_buffer(drm_buf_t * buf)
+static int i810_unmap_buffer(struct drm_buf * buf)
{
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
int retcode = 0;
@@ -172,10 +172,10 @@ static int i810_unmap_buffer(drm_buf_t * buf)
return retcode;
}
-static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
+static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
struct file *filp)
{
- drm_buf_t *buf;
+ struct drm_buf *buf;
drm_i810_buf_priv_t *buf_priv;
int retcode = 0;
@@ -202,9 +202,9 @@ static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
return retcode;
}
-static int i810_dma_cleanup(drm_device_t * dev)
+static int i810_dma_cleanup(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
@@ -233,7 +233,7 @@ static int i810_dma_cleanup(drm_device_t * dev)
dev->dev_private = NULL;
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
if (buf_priv->kernel_virtual && buf->total)
@@ -243,7 +243,7 @@ static int i810_dma_cleanup(drm_device_t * dev)
return 0;
}
-static int i810_wait_ring(drm_device_t * dev, int n)
+static int i810_wait_ring(struct drm_device * dev, int n)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -276,7 +276,7 @@ static int i810_wait_ring(drm_device_t * dev, int n)
return iters;
}
-static void i810_kernel_lost_context(drm_device_t * dev)
+static void i810_kernel_lost_context(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -288,9 +288,9 @@ static void i810_kernel_lost_context(drm_device_t * dev)
ring->space += ring->Size;
}
-static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
+static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int my_idx = 24;
u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
int i;
@@ -301,7 +301,7 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
}
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
buf_priv->in_use = hw_status++;
@@ -323,16 +323,14 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
return 0;
}
-static int i810_dma_initialize(drm_device_t * dev,
+static int i810_dma_initialize(struct drm_device * dev,
drm_i810_private_t * dev_priv,
drm_i810_init_t * init)
{
- struct list_head *list;
-
+ struct drm_map_list *r_list;
memset(dev_priv, 0, sizeof(drm_i810_private_t));
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
r_list->map->type == _DRM_SHM &&
r_list->map->flags & _DRM_CONTAINS_LOCK) {
@@ -478,8 +476,8 @@ static int i810_dma_init_compat(drm_i810_init_t * init, unsigned long arg)
static int i810_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv;
drm_i810_init_t init;
int retcode = 0;
@@ -536,7 +534,7 @@ static int i810_dma_init(struct inode *inode, struct file *filp,
* Use 'volatile' & local var tmp to force the emitted values to be
* identical to the verified ones.
*/
-static void i810EmitContextVerified(drm_device_t * dev,
+static void i810EmitContextVerified(struct drm_device * dev,
volatile unsigned int *code)
{
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -569,7 +567,7 @@ static void i810EmitContextVerified(drm_device_t * dev,
ADVANCE_LP_RING();
}
-static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
+static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
{
drm_i810_private_t *dev_priv = dev->dev_private;
int i, j = 0;
@@ -602,7 +600,7 @@ static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
/* Need to do some additional checking when setting the dest buffer.
*/
-static void i810EmitDestVerified(drm_device_t * dev,
+static void i810EmitDestVerified(struct drm_device * dev,
volatile unsigned int *code)
{
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -637,7 +635,7 @@ static void i810EmitDestVerified(drm_device_t * dev,
ADVANCE_LP_RING();
}
-static void i810EmitState(drm_device_t * dev)
+static void i810EmitState(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -668,14 +666,14 @@ static void i810EmitState(drm_device_t * dev)
/* need to verify
*/
-static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
+static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
unsigned int clear_color,
unsigned int clear_zval)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = 2;
int i;
@@ -743,12 +741,12 @@ static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
}
}
-static void i810_dma_dispatch_swap(drm_device_t * dev)
+static void i810_dma_dispatch_swap(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = 2;
int i;
@@ -789,13 +787,13 @@ static void i810_dma_dispatch_swap(drm_device_t * dev)
}
}
-static void i810_dma_dispatch_vertex(drm_device_t * dev,
- drm_buf_t * buf, int discard, int used)
+static void i810_dma_dispatch_vertex(struct drm_device * dev,
+ struct drm_buf * buf, int discard, int used)
{
drm_i810_private_t *dev_priv = dev->dev_private;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_clip_rect_t *box = sarea_priv->boxes;
+ struct drm_clip_rect *box = sarea_priv->boxes;
int nbox = sarea_priv->nbox;
unsigned long address = (unsigned long)buf->bus_address;
unsigned long start = address - dev->agp->base;
@@ -869,7 +867,7 @@ static void i810_dma_dispatch_vertex(drm_device_t * dev,
}
}
-static void i810_dma_dispatch_flip(drm_device_t * dev)
+static void i810_dma_dispatch_flip(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
int pitch = dev_priv->pitch;
@@ -916,7 +914,7 @@ static void i810_dma_dispatch_flip(drm_device_t * dev)
}
-static void i810_dma_quiescent(drm_device_t * dev)
+static void i810_dma_quiescent(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -935,10 +933,10 @@ static void i810_dma_quiescent(drm_device_t * dev)
i810_wait_ring(dev, dev_priv->ring.Size - 8);
}
-static int i810_flush_queue(drm_device_t * dev)
+static int i810_flush_queue(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i, ret = 0;
RING_LOCALS;
@@ -954,7 +952,7 @@ static int i810_flush_queue(drm_device_t * dev)
i810_wait_ring(dev, dev_priv->ring.Size - 8);
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
@@ -970,9 +968,9 @@ static int i810_flush_queue(drm_device_t * dev)
}
/* Must be called with the lock held */
-static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
if (!dma)
@@ -985,7 +983,7 @@ static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
i810_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
if (buf->filp == filp && buf_priv) {
@@ -1003,8 +1001,8 @@ static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
static int i810_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1015,9 +1013,9 @@ static int i810_flush_ioctl(struct inode *inode, struct file *filp,
static int i810_dma_vertex(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1051,8 +1049,8 @@ static int i810_dma_vertex(struct inode *inode, struct file *filp,
static int i810_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_clear_t clear;
if (copy_from_user
@@ -1074,8 +1072,8 @@ static int i810_clear_bufs(struct inode *inode, struct file *filp,
static int i810_swap_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
DRM_DEBUG("i810_swap_bufs\n");
@@ -1088,8 +1086,8 @@ static int i810_swap_bufs(struct inode *inode, struct file *filp,
static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1102,8 +1100,8 @@ static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
int retcode = 0;
drm_i810_dma_t d;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
@@ -1123,7 +1121,7 @@ static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted);
- if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
+ if (copy_to_user((void __user *) arg, &d, sizeof(d)))
return -EFAULT;
sarea_priv->last_dispatch = (int)hw_status[5];
@@ -1144,7 +1142,7 @@ static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
return 0;
}
-static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
+static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
unsigned int last_render)
{
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1207,9 +1205,9 @@ static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
static int i810_dma_mc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1238,8 +1236,8 @@ static int i810_dma_mc(struct inode *inode, struct file *filp,
static int i810_rstatus(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
@@ -1248,8 +1246,8 @@ static int i810_rstatus(struct inode *inode, struct file *filp,
static int i810_ov0_info(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
drm_i810_overlay_t data;
@@ -1264,8 +1262,8 @@ static int i810_ov0_info(struct inode *inode, struct file *filp,
static int i810_fstatus(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1276,8 +1274,8 @@ static int i810_fstatus(struct inode *inode, struct file *filp,
static int i810_ov0_flip(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1290,7 +1288,7 @@ static int i810_ov0_flip(struct inode *inode, struct file *filp,
/* Not sure why this isn't set all the time:
*/
-static void i810_do_init_pageflip(drm_device_t * dev)
+static void i810_do_init_pageflip(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1300,7 +1298,7 @@ static void i810_do_init_pageflip(drm_device_t * dev)
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-static int i810_do_cleanup_pageflip(drm_device_t * dev)
+static int i810_do_cleanup_pageflip(struct drm_device * dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1315,8 +1313,8 @@ static int i810_do_cleanup_pageflip(drm_device_t * dev)
static int i810_flip_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i810_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1330,7 +1328,7 @@ static int i810_flip_bufs(struct inode *inode, struct file *filp,
return 0;
}
-int i810_driver_load(drm_device_t *dev, unsigned long flags)
+int i810_driver_load(struct drm_device *dev, unsigned long flags)
{
/* i810 has 4 more counters */
dev->counters += 4;
@@ -1342,12 +1340,12 @@ int i810_driver_load(drm_device_t *dev, unsigned long flags)
return 0;
}
-void i810_driver_lastclose(drm_device_t * dev)
+void i810_driver_lastclose(struct drm_device * dev)
{
i810_dma_cleanup(dev);
}
-void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i810_driver_preclose(struct drm_device * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1357,12 +1355,12 @@ void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
}
}
-void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i810_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
{
i810_reclaim_buffers(dev, filp);
}
-int i810_driver_dma_quiescent(drm_device_t * dev)
+int i810_driver_dma_quiescent(struct drm_device * dev)
{
i810_dma_quiescent(dev);
return 0;
@@ -1399,7 +1397,7 @@ int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
* \returns
* A value of 1 is always retured to indictate every i810 is AGP.
*/
-int i810_driver_device_is_agp(drm_device_t * dev)
+int i810_driver_device_is_agp(struct drm_device * dev)
{
return 1;
}
diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
index 2deb925a94f3..614977dbce45 100644
--- a/drivers/char/drm/i810_drm.h
+++ b/drivers/char/drm/i810_drm.h
@@ -158,7 +158,7 @@ typedef struct _drm_i810_sarea {
unsigned int dirty;
unsigned int nbox;
- drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect boxes[I810_NR_SAREA_CLIPRECTS];
/* Maintain an LRU of contiguous regions of texture space. If
* you think you own a region of texture memory, and it has an
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index e6df49f4928a..648833844c7f 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -77,8 +77,8 @@ typedef struct _drm_i810_ring_buffer {
} drm_i810_ring_buffer_t;
typedef struct drm_i810_private {
- drm_map_t *sarea_map;
- drm_map_t *mmio_map;
+ struct drm_map *sarea_map;
+ struct drm_map *mmio_map;
drm_i810_sarea_t *sarea_priv;
drm_i810_ring_buffer_t ring;
@@ -88,7 +88,7 @@ typedef struct drm_i810_private {
dma_addr_t dma_status_page;
- drm_buf_t *mmap_buffer;
+ struct drm_buf *mmap_buffer;
u32 front_di1, back_di1, zi1;
@@ -115,15 +115,15 @@ typedef struct drm_i810_private {
} drm_i810_private_t;
/* i810_dma.c */
-extern int i810_driver_dma_quiescent(drm_device_t * dev);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern int i810_driver_dma_quiescent(struct drm_device * dev);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
struct file *filp);
extern int i810_driver_load(struct drm_device *, unsigned long flags);
-extern void i810_driver_lastclose(drm_device_t * dev);
-extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern void i810_driver_lastclose(struct drm_device * dev);
+extern void i810_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
struct file *filp);
-extern int i810_driver_device_is_agp(drm_device_t * dev);
+extern int i810_driver_device_is_agp(struct drm_device * dev);
extern drm_ioctl_desc_t i810_ioctls[];
extern int i810_max_ioctl;
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 3314a9fea9e5..dc20c1a7834e 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -47,16 +47,16 @@
#define I830_BUF_UNMAPPED 0
#define I830_BUF_MAPPED 1
-static drm_buf_t *i830_freelist_get(drm_device_t * dev)
+static struct drm_buf *i830_freelist_get(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
int used;
/* Linear search might not be the best solution */
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
/* In use is already a pointer */
used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
@@ -72,7 +72,7 @@ static drm_buf_t *i830_freelist_get(drm_device_t * dev)
* yet, the hardware updates in use for us once its on the ring buffer.
*/
-static int i830_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf)
{
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
int used;
@@ -89,10 +89,10 @@ static int i830_freelist_put(drm_device_t * dev, drm_buf_t * buf)
static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev;
drm_i830_private_t *dev_priv;
- drm_buf_t *buf;
+ struct drm_buf *buf;
drm_i830_buf_priv_t *buf_priv;
lock_kernel();
@@ -122,10 +122,10 @@ static const struct file_operations i830_buffer_fops = {
.fasync = drm_fasync,
};
-static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i830_map_buffer(struct drm_buf * buf, struct file *filp)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
drm_i830_private_t *dev_priv = dev->dev_private;
const struct file_operations *old_fops;
@@ -156,7 +156,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
return retcode;
}
-static int i830_unmap_buffer(drm_buf_t * buf)
+static int i830_unmap_buffer(struct drm_buf * buf)
{
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
int retcode = 0;
@@ -176,10 +176,10 @@ static int i830_unmap_buffer(drm_buf_t * buf)
return retcode;
}
-static int i830_dma_get_buffer(drm_device_t * dev, drm_i830_dma_t * d,
+static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
struct file *filp)
{
- drm_buf_t *buf;
+ struct drm_buf *buf;
drm_i830_buf_priv_t *buf_priv;
int retcode = 0;
@@ -206,9 +206,9 @@ static int i830_dma_get_buffer(drm_device_t * dev, drm_i830_dma_t * d,
return retcode;
}
-static int i830_dma_cleanup(drm_device_t * dev)
+static int i830_dma_cleanup(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
@@ -238,7 +238,7 @@ static int i830_dma_cleanup(drm_device_t * dev)
dev->dev_private = NULL;
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
if (buf_priv->kernel_virtual && buf->total)
drm_core_ioremapfree(&buf_priv->map, dev);
@@ -247,7 +247,7 @@ static int i830_dma_cleanup(drm_device_t * dev)
return 0;
}
-int i830_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -281,7 +281,7 @@ int i830_wait_ring(drm_device_t * dev, int n, const char *caller)
return iters;
}
-static void i830_kernel_lost_context(drm_device_t * dev)
+static void i830_kernel_lost_context(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -296,9 +296,9 @@ static void i830_kernel_lost_context(drm_device_t * dev)
dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
}
-static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
+static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int my_idx = 36;
u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
int i;
@@ -309,7 +309,7 @@ static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
}
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
buf_priv->in_use = hw_status++;
@@ -330,16 +330,15 @@ static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
return 0;
}
-static int i830_dma_initialize(drm_device_t * dev,
+static int i830_dma_initialize(struct drm_device * dev,
drm_i830_private_t * dev_priv,
drm_i830_init_t * init)
{
- struct list_head *list;
+ struct drm_map_list *r_list;
memset(dev_priv, 0, sizeof(drm_i830_private_t));
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
r_list->map->type == _DRM_SHM &&
r_list->map->flags & _DRM_CONTAINS_LOCK) {
@@ -455,8 +454,8 @@ static int i830_dma_initialize(drm_device_t * dev,
static int i830_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv;
drm_i830_init_t init;
int retcode = 0;
@@ -490,7 +489,7 @@ static int i830_dma_init(struct inode *inode, struct file *filp,
/* Most efficient way to verify state for the i830 is as it is
* emitted. Non-conformant state is silently dropped.
*/
-static void i830EmitContextVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
{
drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
@@ -535,7 +534,7 @@ static void i830EmitContextVerified(drm_device_t * dev, unsigned int *code)
ADVANCE_LP_RING();
}
-static void i830EmitTexVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
{
drm_i830_private_t *dev_priv = dev->dev_private;
int i, j = 0;
@@ -569,7 +568,7 @@ static void i830EmitTexVerified(drm_device_t * dev, unsigned int *code)
printk("rejected packet %x\n", code[0]);
}
-static void i830EmitTexBlendVerified(drm_device_t * dev,
+static void i830EmitTexBlendVerified(struct drm_device * dev,
unsigned int *code, unsigned int num)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -594,7 +593,7 @@ static void i830EmitTexBlendVerified(drm_device_t * dev,
ADVANCE_LP_RING();
}
-static void i830EmitTexPalette(drm_device_t * dev,
+static void i830EmitTexPalette(struct drm_device * dev,
unsigned int *palette, int number, int is_shared)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -621,7 +620,7 @@ static void i830EmitTexPalette(drm_device_t * dev,
/* Need to do some additional checking when setting the dest buffer.
*/
-static void i830EmitDestVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
{
drm_i830_private_t *dev_priv = dev->dev_private;
unsigned int tmp;
@@ -682,7 +681,7 @@ static void i830EmitDestVerified(drm_device_t * dev, unsigned int *code)
ADVANCE_LP_RING();
}
-static void i830EmitStippleVerified(drm_device_t * dev, unsigned int *code)
+static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -693,7 +692,7 @@ static void i830EmitStippleVerified(drm_device_t * dev, unsigned int *code)
ADVANCE_LP_RING();
}
-static void i830EmitState(drm_device_t * dev)
+static void i830EmitState(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -796,7 +795,7 @@ static void i830EmitState(drm_device_t * dev)
* Performance monitoring functions
*/
-static void i830_fill_box(drm_device_t * dev,
+static void i830_fill_box(struct drm_device * dev,
int x, int y, int w, int h, int r, int g, int b)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -834,7 +833,7 @@ static void i830_fill_box(drm_device_t * dev,
ADVANCE_LP_RING();
}
-static void i830_cp_performance_boxes(drm_device_t * dev)
+static void i830_cp_performance_boxes(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -879,7 +878,7 @@ static void i830_cp_performance_boxes(drm_device_t * dev)
dev_priv->sarea_priv->perf_boxes = 0;
}
-static void i830_dma_dispatch_clear(drm_device_t * dev, int flags,
+static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
unsigned int clear_color,
unsigned int clear_zval,
unsigned int clear_depthmask)
@@ -887,7 +886,7 @@ static void i830_dma_dispatch_clear(drm_device_t * dev, int flags,
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = dev_priv->cpp;
int i;
@@ -974,12 +973,12 @@ static void i830_dma_dispatch_clear(drm_device_t * dev, int flags,
}
}
-static void i830_dma_dispatch_swap(drm_device_t * dev)
+static void i830_dma_dispatch_swap(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int pitch = dev_priv->pitch;
int cpp = dev_priv->cpp;
int i;
@@ -1044,7 +1043,7 @@ static void i830_dma_dispatch_swap(drm_device_t * dev)
}
}
-static void i830_dma_dispatch_flip(drm_device_t * dev)
+static void i830_dma_dispatch_flip(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -1087,13 +1086,13 @@ static void i830_dma_dispatch_flip(drm_device_t * dev)
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-static void i830_dma_dispatch_vertex(drm_device_t * dev,
- drm_buf_t * buf, int discard, int used)
+static void i830_dma_dispatch_vertex(struct drm_device * dev,
+ struct drm_buf * buf, int discard, int used)
{
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_clip_rect_t *box = sarea_priv->boxes;
+ struct drm_clip_rect *box = sarea_priv->boxes;
int nbox = sarea_priv->nbox;
unsigned long address = (unsigned long)buf->bus_address;
unsigned long start = address - dev->agp->base;
@@ -1199,7 +1198,7 @@ static void i830_dma_dispatch_vertex(drm_device_t * dev,
}
}
-static void i830_dma_quiescent(drm_device_t * dev)
+static void i830_dma_quiescent(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -1216,10 +1215,10 @@ static void i830_dma_quiescent(drm_device_t * dev)
i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
}
-static int i830_flush_queue(drm_device_t * dev)
+static int i830_flush_queue(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i, ret = 0;
RING_LOCALS;
@@ -1233,7 +1232,7 @@ static int i830_flush_queue(drm_device_t * dev)
i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
@@ -1249,9 +1248,9 @@ static int i830_flush_queue(drm_device_t * dev)
}
/* Must be called with the lock held */
-static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
+static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
if (!dma)
@@ -1264,7 +1263,7 @@ static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
i830_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
if (buf->filp == filp && buf_priv) {
@@ -1282,8 +1281,8 @@ static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
static int i830_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1294,9 +1293,9 @@ static int i830_flush_ioctl(struct inode *inode, struct file *filp,
static int i830_dma_vertex(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
+ struct drm_device_dma *dma = dev->dma;
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
@@ -1328,8 +1327,8 @@ static int i830_dma_vertex(struct inode *inode, struct file *filp,
static int i830_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_clear_t clear;
if (copy_from_user
@@ -1352,8 +1351,8 @@ static int i830_clear_bufs(struct inode *inode, struct file *filp,
static int i830_swap_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
DRM_DEBUG("i830_swap_bufs\n");
@@ -1365,7 +1364,7 @@ static int i830_swap_bufs(struct inode *inode, struct file *filp,
/* Not sure why this isn't set all the time:
*/
-static void i830_do_init_pageflip(drm_device_t * dev)
+static void i830_do_init_pageflip(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1375,7 +1374,7 @@ static void i830_do_init_pageflip(drm_device_t * dev)
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-static int i830_do_cleanup_pageflip(drm_device_t * dev)
+static int i830_do_cleanup_pageflip(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1390,8 +1389,8 @@ static int i830_do_cleanup_pageflip(drm_device_t * dev)
static int i830_flip_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1408,8 +1407,8 @@ static int i830_flip_bufs(struct inode *inode, struct file *filp,
static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
@@ -1422,8 +1421,8 @@ static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
int retcode = 0;
drm_i830_dma_t d;
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
@@ -1444,7 +1443,7 @@ static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted);
- if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
+ if (copy_to_user((void __user *) arg, &d, sizeof(d)))
return -EFAULT;
sarea_priv->last_dispatch = (int)hw_status[5];
@@ -1467,8 +1466,8 @@ static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
static int i830_getparam(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_getparam_t param;
int value;
@@ -1501,8 +1500,8 @@ static int i830_getparam(struct inode *inode, struct file *filp,
static int i830_setparam(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_setparam_t param;
@@ -1526,7 +1525,7 @@ static int i830_setparam(struct inode *inode, struct file *filp,
return 0;
}
-int i830_driver_load(drm_device_t *dev, unsigned long flags)
+int i830_driver_load(struct drm_device *dev, unsigned long flags)
{
/* i830 has 4 more counters */
dev->counters += 4;
@@ -1538,12 +1537,12 @@ int i830_driver_load(drm_device_t *dev, unsigned long flags)
return 0;
}
-void i830_driver_lastclose(drm_device_t * dev)
+void i830_driver_lastclose(struct drm_device * dev)
{
i830_dma_cleanup(dev);
}
-void i830_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i830_driver_preclose(struct drm_device * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1553,12 +1552,12 @@ void i830_driver_preclose(drm_device_t * dev, DRMFILE filp)
}
}
-void i830_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
{
i830_reclaim_buffers(dev, filp);
}
-int i830_driver_dma_quiescent(drm_device_t * dev)
+int i830_driver_dma_quiescent(struct drm_device * dev)
{
i830_dma_quiescent(dev);
return 0;
@@ -1594,7 +1593,7 @@ int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
* \returns
* A value of 1 is always retured to indictate every i8xx is AGP.
*/
-int i830_driver_device_is_agp(drm_device_t * dev)
+int i830_driver_device_is_agp(struct drm_device * dev)
{
return 1;
}
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
index 66dd75027967..968a6d9f9dcb 100644
--- a/drivers/char/drm/i830_drm.h
+++ b/drivers/char/drm/i830_drm.h
@@ -191,7 +191,7 @@ typedef struct _drm_i830_sarea {
unsigned int dirty;
unsigned int nbox;
- drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect boxes[I830_NR_SAREA_CLIPRECTS];
/* Maintain an LRU of contiguous regions of texture space. If
* you think you own a region of texture memory, and it has an
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index e91f94afb4bb..ddda67956dea 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -84,8 +84,8 @@ typedef struct _drm_i830_ring_buffer {
} drm_i830_ring_buffer_t;
typedef struct drm_i830_private {
- drm_map_t *sarea_map;
- drm_map_t *mmio_map;
+ struct drm_map *sarea_map;
+ struct drm_map *mmio_map;
drm_i830_sarea_t *sarea_priv;
drm_i830_ring_buffer_t ring;
@@ -95,7 +95,7 @@ typedef struct drm_i830_private {
dma_addr_t dma_status_page;
- drm_buf_t *mmap_buffer;
+ struct drm_buf *mmap_buffer;
u32 front_di1, back_di1, zi1;
@@ -132,16 +132,16 @@ extern int i830_irq_wait(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i830_driver_irq_preinstall(drm_device_t * dev);
-extern void i830_driver_irq_postinstall(drm_device_t * dev);
-extern void i830_driver_irq_uninstall(drm_device_t * dev);
+extern void i830_driver_irq_preinstall(struct drm_device * dev);
+extern void i830_driver_irq_postinstall(struct drm_device * dev);
+extern void i830_driver_irq_uninstall(struct drm_device * dev);
extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i830_driver_lastclose(drm_device_t * dev);
-extern void i830_driver_reclaim_buffers_locked(drm_device_t * dev,
+extern void i830_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void i830_driver_lastclose(struct drm_device * dev);
+extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
struct file *filp);
-extern int i830_driver_dma_quiescent(drm_device_t * dev);
-extern int i830_driver_device_is_agp(drm_device_t * dev);
+extern int i830_driver_dma_quiescent(struct drm_device * dev);
+extern int i830_driver_device_is_agp(struct drm_device * dev);
#define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
#define I830_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
@@ -180,7 +180,7 @@ extern int i830_driver_device_is_agp(drm_device_t * dev);
I830_WRITE(LP_RING + RING_TAIL, outring); \
} while(0)
-extern int i830_wait_ring(drm_device_t * dev, int n, const char *caller);
+extern int i830_wait_ring(struct drm_device * dev, int n, const char *caller);
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 5841f7674956..a1b5c63c3c3e 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -35,7 +35,7 @@
irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *) arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
u16 temp;
@@ -53,7 +53,7 @@ irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_HANDLED;
}
-static int i830_emit_irq(drm_device_t * dev)
+static int i830_emit_irq(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -70,7 +70,7 @@ static int i830_emit_irq(drm_device_t * dev)
return atomic_read(&dev_priv->irq_emitted);
}
-static int i830_wait_irq(drm_device_t * dev, int irq_nr)
+static int i830_wait_irq(struct drm_device * dev, int irq_nr)
{
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
DECLARE_WAITQUEUE(entry, current);
@@ -117,8 +117,8 @@ static int i830_wait_irq(drm_device_t * dev, int irq_nr)
int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_irq_emit_t emit;
int result;
@@ -149,8 +149,8 @@ int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd,
int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ struct drm_file *priv = filp->private_data;
+ struct drm_device *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_irq_wait_t irqwait;
@@ -168,7 +168,7 @@ int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd,
/* drm_dma.h hooks
*/
-void i830_driver_irq_preinstall(drm_device_t * dev)
+void i830_driver_irq_preinstall(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
@@ -180,14 +180,14 @@ void i830_driver_irq_preinstall(drm_device_t * dev)
init_waitqueue_head(&dev_priv->irq_queue);
}
-void i830_driver_irq_postinstall(drm_device_t * dev)
+void i830_driver_irq_postinstall(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
}
-void i830_driver_irq_uninstall(drm_device_t * dev)
+void i830_driver_irq_uninstall(struct drm_device * dev)
{
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
if (!dev_priv)
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index ea52740af4f6..3359cc2b9736 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -47,7 +47,7 @@
* the head pointer changes, so that EBUSY only happens if the ring
* actually stalls for (eg) 3 seconds.
*/
-int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
@@ -73,7 +73,7 @@ int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
return DRM_ERR(EBUSY);
}
-void i915_kernel_lost_context(drm_device_t * dev)
+void i915_kernel_lost_context(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
@@ -88,7 +88,7 @@ void i915_kernel_lost_context(drm_device_t * dev)
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
}
-static int i915_dma_cleanup(drm_device_t * dev)
+static int i915_dma_cleanup(struct drm_device * dev)
{
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
@@ -126,13 +126,13 @@ static int i915_dma_cleanup(drm_device_t * dev)
return 0;
}
-static int i915_initialize(drm_device_t * dev,
+static int i915_initialize(struct drm_device * dev,
drm_i915_private_t * dev_priv,
drm_i915_init_t * init)
{
memset(dev_priv, 0, sizeof(drm_i915_private_t));
- DRM_GETSAREA();
+ dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("can not find sarea!\n");
dev->dev_private = (void *)dev_priv;
@@ -211,7 +211,7 @@ static int i915_initialize(drm_device_t * dev,
return 0;
}
-static int i915_dma_resume(drm_device_t * dev)
+static int i915_dma_resume(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -357,7 +357,7 @@ static int validate_cmd(int cmd)
return ret;
}
-static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;
@@ -396,12 +396,12 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
return 0;
}
-static int i915_emit_box(drm_device_t * dev,
- drm_clip_rect_t __user * boxes,
+static int i915_emit_box(struct drm_device * dev,
+ struct drm_clip_rect __user * boxes,
int i, int DR1, int DR4)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- drm_clip_rect_t box;
+ struct drm_clip_rect box;
RING_LOCALS;
if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
@@ -439,7 +439,7 @@ static int i915_emit_box(drm_device_t * dev,
* emit. For now, do it in both places:
*/
-static void i915_emit_breadcrumb(drm_device_t *dev)
+static void i915_emit_breadcrumb(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -457,7 +457,7 @@ static void i915_emit_breadcrumb(drm_device_t *dev)
ADVANCE_LP_RING();
}
-static int i915_dispatch_cmdbuffer(drm_device_t * dev,
+static int i915_dispatch_cmdbuffer(struct drm_device * dev,
drm_i915_cmdbuffer_t * cmd)
{
int nbox = cmd->num_cliprects;
@@ -489,11 +489,11 @@ static int i915_dispatch_cmdbuffer(drm_device_t * dev,
return 0;
}
-static int i915_dispatch_batchbuffer(drm_device_t * dev,
+static int i915_dispatch_batchbuffer(struct drm_device * dev,
drm_i915_batchbuffer_t * batch)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- drm_clip_rect_t __user *boxes = batch->cliprects;
+ struct drm_clip_rect __user *boxes = batch->cliprects;
int nbox = batch->num_cliprects;
int i = 0, count;
RING_LOCALS;
@@ -535,7 +535,7 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
return 0;
}
-static int i915_dispatch_flip(drm_device_t * dev)
+static int i915_dispatch_flip(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -583,7 +583,7 @@ static int i915_dispatch_flip(drm_device_t * dev)
return 0;
}
-static int i915_quiescent(drm_device_t * dev)
+static int i915_quiescent(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -625,7 +625,7 @@ static int i915_batchbuffer(DRM_IOCTL_ARGS)
if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
batch.num_cliprects *
- sizeof(drm_clip_rect_t)))
+ sizeof(struct drm_clip_rect)))
return DRM_ERR(EFAULT);
ret = i915_dispatch_batchbuffer(dev, &batch);
@@ -655,7 +655,7 @@ static int i915_cmdbuffer(DRM_IOCTL_ARGS)
if (cmdbuf.num_cliprects &&
DRM_VERIFYAREA_READ(cmdbuf.cliprects,
cmdbuf.num_cliprects *
- sizeof(drm_clip_rect_t))) {
+ sizeof(struct drm_clip_rect))) {
DRM_ERROR("Fault accessing cliprects\n");
return DRM_ERR(EFAULT);
}
@@ -792,7 +792,7 @@ static int i915_set_status_page(DRM_IOCTL_ARGS)
return 0;
}
-int i915_driver_load(drm_device_t *dev, unsigned long flags)
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
{
/* i915 has 4 more counters */
dev->counters += 4;
@@ -804,7 +804,7 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
return 0;
}
-void i915_driver_lastclose(drm_device_t * dev)
+void i915_driver_lastclose(struct drm_device * dev)
{
if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -813,7 +813,7 @@ void i915_driver_lastclose(drm_device_t * dev)
i915_dma_cleanup(dev);
}
-void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i915_driver_preclose(struct drm_device * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -854,7 +854,7 @@ int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
* \returns
* A value of 1 is always retured to indictate every i9x5 is AGP.
*/
-int i915_driver_device_is_agp(drm_device_t * dev)
+int i915_driver_device_is_agp(struct drm_device * dev)
{
return 1;
}
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 7b7b68b96f31..05c66cf03a9e 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -64,7 +64,7 @@ typedef struct _drm_i915_init {
} drm_i915_init_t;
typedef struct _drm_i915_sarea {
- drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
+ struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
int last_upload; /* last time texture was uploaded */
int last_enqueue; /* last time a buffer was enqueued */
int last_dispatch; /* age of the most recently dispatched buffer */
@@ -170,7 +170,7 @@ typedef struct _drm_i915_batchbuffer {
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
int num_cliprects; /* mulitpass with multiple cliprects? */
- drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */
+ struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
} drm_i915_batchbuffer_t;
/* As above, but pass a pointer to userspace buffer which can be
@@ -182,7 +182,7 @@ typedef struct _drm_i915_cmdbuffer {
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
int num_cliprects; /* mulitpass with multiple cliprects? */
- drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */
+ struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
} drm_i915_cmdbuffer_t;
/* Userspace can request & wait on irq's:
@@ -259,7 +259,7 @@ typedef struct drm_i915_vblank_pipe {
*/
typedef struct drm_i915_vblank_swap {
drm_drawable_t drawable;
- drm_vblank_seq_type_t seqtype;
+ enum drm_vblank_seq_type seqtype;
unsigned int sequence;
} drm_i915_vblank_swap_t;
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 85e323acb95d..fd918565f4e5 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -120,11 +120,11 @@ extern drm_ioctl_desc_t i915_ioctls[];
extern int i915_max_ioctl;
/* i915_dma.c */
-extern void i915_kernel_lost_context(drm_device_t * dev);
+extern void i915_kernel_lost_context(struct drm_device * dev);
extern int i915_driver_load(struct drm_device *, unsigned long flags);
-extern void i915_driver_lastclose(drm_device_t * dev);
-extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern void i915_driver_lastclose(struct drm_device * dev);
+extern void i915_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(struct drm_device * dev);
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@@ -132,12 +132,12 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
-extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i915_driver_irq_preinstall(drm_device_t * dev);
-extern void i915_driver_irq_postinstall(drm_device_t * dev);
-extern void i915_driver_irq_uninstall(drm_device_t * dev);
+extern void i915_driver_irq_preinstall(struct drm_device * dev);
+extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern void i915_driver_irq_uninstall(struct drm_device * dev);
extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
extern int i915_vblank_swap(DRM_IOCTL_ARGS);
@@ -148,7 +148,7 @@ extern int i915_mem_free(DRM_IOCTL_ARGS);
extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
extern void i915_mem_takedown(struct mem_block **heap);
-extern void i915_mem_release(drm_device_t * dev,
+extern void i915_mem_release(struct drm_device * dev,
DRMFILE filp, struct mem_block *heap);
#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
@@ -188,7 +188,7 @@ extern void i915_mem_release(drm_device_t * dev,
I915_WRITE(LP_RING + RING_TAIL, outring); \
} while(0)
-extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index b92062a239f1..4b4b2ce89863 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -42,7 +42,7 @@
*
* This function will be called with the HW lock held.
*/
-static void i915_vblank_tasklet(drm_device_t *dev)
+static void i915_vblank_tasklet(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags;
@@ -50,7 +50,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
int nhits, nrects, slice[2], upper[2], lower[2], i;
unsigned counter[2] = { atomic_read(&dev->vbl_received),
atomic_read(&dev->vbl_received2) };
- drm_drawable_info_t *drw;
+ struct drm_drawable_info *drw;
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
u32 cpp = dev_priv->cpp;
u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
@@ -95,7 +95,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
list_for_each(hit, &hits) {
drm_i915_vbl_swap_t *swap_cmp =
list_entry(hit, drm_i915_vbl_swap_t, head);
- drm_drawable_info_t *drw_cmp =
+ struct drm_drawable_info *drw_cmp =
drm_get_drawable_info(dev, swap_cmp->drw_id);
if (drw_cmp &&
@@ -160,7 +160,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
list_for_each(hit, &hits) {
drm_i915_vbl_swap_t *swap_hit =
list_entry(hit, drm_i915_vbl_swap_t, head);
- drm_clip_rect_t *rect;
+ struct drm_clip_rect *rect;
int num_rects, pipe;
unsigned short top, bottom;
@@ -211,7 +211,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *) arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u16 temp;
@@ -257,7 +257,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_HANDLED;
}
-static int i915_emit_irq(drm_device_t * dev)
+static int i915_emit_irq(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -283,7 +283,7 @@ static int i915_emit_irq(drm_device_t * dev)
return dev_priv->counter;
}
-static int i915_wait_irq(drm_device_t * dev, int irq_nr)
+static int i915_wait_irq(struct drm_device * dev, int irq_nr)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = 0;
@@ -309,7 +309,7 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
return ret;
}
-static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
atomic_t *counter)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -331,12 +331,12 @@ static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
}
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
{
return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
}
-int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
{
return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
}
@@ -389,7 +389,7 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
return i915_wait_irq(dev, irqwait.irq_seq);
}
-static void i915_enable_interrupt (drm_device_t *dev)
+static void i915_enable_interrupt (struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u16 flag;
@@ -569,7 +569,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
/* drm_dma.h hooks
*/
-void i915_driver_irq_preinstall(drm_device_t * dev)
+void i915_driver_irq_preinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -578,7 +578,7 @@ void i915_driver_irq_preinstall(drm_device_t * dev)
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
}
-void i915_driver_irq_postinstall(drm_device_t * dev)
+void i915_driver_irq_postinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -592,7 +592,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}
-void i915_driver_irq_uninstall(drm_device_t * dev)
+void i915_driver_irq_uninstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u16 temp;
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index 52c67324df58..50b4bacef0e0 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -43,11 +43,11 @@
* block to allocate, and the ring is drained prior to allocations --
* in other words allocation is expensive.
*/
-static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_tex_region_t *list;
+ struct drm_tex_region *list;
unsigned shift, nr;
unsigned start;
unsigned end;
@@ -208,7 +208,7 @@ static int init_heap(struct mem_block **heap, int start, int size)
/* Free all blocks associated with the releasing file.
*/
-void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+void i915_mem_release(struct drm_device * dev, DRMFILE filp, struct mem_block *heap)
{
struct mem_block *p;
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index c2a4bac14521..9c73a6e3861b 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -46,7 +46,7 @@
#define MINIMAL_CLEANUP 0
#define FULL_CLEANUP 1
-static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
/* ================================================================
* Engine control
@@ -224,7 +224,7 @@ void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
#define MGA_BUFFER_FREE 0
#if MGA_FREELIST_DEBUG
-static void mga_freelist_print(drm_device_t * dev)
+static void mga_freelist_print(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_freelist_t *entry;
@@ -245,10 +245,10 @@ static void mga_freelist_print(drm_device_t * dev)
}
#endif
-static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
+static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_freelist_t *entry;
int i;
@@ -291,7 +291,7 @@ static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
return 0;
}
-static void mga_freelist_cleanup(drm_device_t * dev)
+static void mga_freelist_cleanup(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_freelist_t *entry;
@@ -311,10 +311,10 @@ static void mga_freelist_cleanup(drm_device_t * dev)
#if 0
/* FIXME: Still needed?
*/
-static void mga_freelist_reset(drm_device_t * dev)
+static void mga_freelist_reset(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_mga_buf_priv_t *buf_priv;
int i;
@@ -326,7 +326,7 @@ static void mga_freelist_reset(drm_device_t * dev)
}
#endif
-static drm_buf_t *mga_freelist_get(drm_device_t * dev)
+static struct drm_buf *mga_freelist_get(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_freelist_t *next;
@@ -359,7 +359,7 @@ static drm_buf_t *mga_freelist_get(drm_device_t * dev)
return NULL;
}
-int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -393,7 +393,7 @@ int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
* DMA initialization, cleanup
*/
-int mga_driver_load(drm_device_t * dev, unsigned long flags)
+int mga_driver_load(struct drm_device * dev, unsigned long flags)
{
drm_mga_private_t *dev_priv;
@@ -434,7 +434,7 @@ int mga_driver_load(drm_device_t * dev, unsigned long flags)
*
* \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
*/
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
drm_mga_dma_bootstrap_t * dma_bs)
{
drm_mga_private_t *const dev_priv =
@@ -445,11 +445,11 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
const unsigned secondary_size = dma_bs->secondary_bin_count
* dma_bs->secondary_bin_size;
const unsigned agp_size = (dma_bs->agp_size << 20);
- drm_buf_desc_t req;
- drm_agp_mode_t mode;
- drm_agp_info_t info;
- drm_agp_buffer_t agp_req;
- drm_agp_binding_t bind_req;
+ struct drm_buf_desc req;
+ struct drm_agp_mode mode;
+ struct drm_agp_info info;
+ struct drm_agp_buffer agp_req;
+ struct drm_agp_binding bind_req;
/* Acquire AGP. */
err = drm_agp_acquire(dev);
@@ -548,10 +548,10 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
}
{
- drm_map_list_t *_entry;
+ struct drm_map_list *_entry;
unsigned long agp_token = 0;
- list_for_each_entry(_entry, &dev->maplist->head, head) {
+ list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == dev->agp_buffer_map)
agp_token = _entry->user_token;
}
@@ -588,7 +588,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
return 0;
}
#else
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
drm_mga_dma_bootstrap_t * dma_bs)
{
return -EINVAL;
@@ -609,7 +609,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
*
* \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
*/
-static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
drm_mga_dma_bootstrap_t * dma_bs)
{
drm_mga_private_t *const dev_priv =
@@ -618,7 +618,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
unsigned int primary_size;
unsigned int bin_count;
int err;
- drm_buf_desc_t req;
+ struct drm_buf_desc req;
if (dev->dma == NULL) {
DRM_ERROR("dev->dma is NULL\n");
@@ -699,7 +699,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
return 0;
}
-static int mga_do_dma_bootstrap(drm_device_t * dev,
+static int mga_do_dma_bootstrap(struct drm_device * dev,
drm_mga_dma_bootstrap_t * dma_bs)
{
const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
@@ -793,7 +793,7 @@ int mga_dma_bootstrap(DRM_IOCTL_ARGS)
return err;
}
-static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
{
drm_mga_private_t *dev_priv;
int ret;
@@ -823,8 +823,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
dev_priv->texture_offset = init->texture_offset[0];
dev_priv->texture_size = init->texture_size[0];
- DRM_GETSAREA();
-
+ dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("failed to find sarea!\n");
return DRM_ERR(EINVAL);
@@ -934,7 +933,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
return 0;
}
-static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
{
int err = 0;
DRM_DEBUG("\n");
@@ -963,8 +962,8 @@ static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)
if (dev_priv->used_new_dma_init) {
#if __OS_HAS_AGP
if (dev_priv->agp_handle != 0) {
- drm_agp_binding_t unbind_req;
- drm_agp_buffer_t free_req;
+ struct drm_agp_binding unbind_req;
+ struct drm_agp_buffer free_req;
unbind_req.handle = dev_priv->agp_handle;
drm_agp_unbind(dev, &unbind_req);
@@ -1041,11 +1040,11 @@ int mga_dma_flush(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- drm_lock_t lock;
+ struct drm_lock lock;
LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
+ DRM_COPY_FROM_USER_IOCTL(lock, (struct drm_lock __user *) data,
sizeof(lock));
DRM_DEBUG("%s%s%s\n",
@@ -1087,9 +1086,9 @@ int mga_dma_reset(DRM_IOCTL_ARGS)
* DMA buffer management
*/
-static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+static int mga_dma_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d)
{
- drm_buf_t *buf;
+ struct drm_buf *buf;
int i;
for (i = d->granted_count; i < d->request_count; i++) {
@@ -1114,10 +1113,10 @@ static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
int mga_dma_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- drm_dma_t __user *argp = (void __user *)data;
- drm_dma_t d;
+ struct drm_dma __user *argp = (void __user *)data;
+ struct drm_dma d;
int ret = 0;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1156,7 +1155,7 @@ int mga_dma_buffers(DRM_IOCTL_ARGS)
/**
* Called just before the module is unloaded.
*/
-int mga_driver_unload(drm_device_t * dev)
+int mga_driver_unload(struct drm_device * dev)
{
drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
dev->dev_private = NULL;
@@ -1167,12 +1166,12 @@ int mga_driver_unload(drm_device_t * dev)
/**
* Called when the last opener of the device is closed.
*/
-void mga_driver_lastclose(drm_device_t * dev)
+void mga_driver_lastclose(struct drm_device * dev)
{
mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
-int mga_driver_dma_quiescent(drm_device_t * dev)
+int mga_driver_dma_quiescent(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
return mga_do_wait_for_idle(dev_priv);
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
index 44d1293e2947..944b50a5ff24 100644
--- a/drivers/char/drm/mga_drm.h
+++ b/drivers/char/drm/mga_drm.h
@@ -181,7 +181,7 @@ typedef struct _drm_mga_sarea {
/* The current cliprects, or a subset thereof.
*/
- drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS];
unsigned int nbox;
/* Information about the most recently used 3d drawable. The
@@ -202,7 +202,7 @@ typedef struct _drm_mga_sarea {
unsigned int exported_nback;
int exported_back_x, exported_front_x, exported_w;
int exported_back_y, exported_front_y, exported_h;
- drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS];
/* Counters for aging textures and for client-side throttling.
*/
@@ -216,7 +216,7 @@ typedef struct _drm_mga_sarea {
/* LRU lists for texture memory in agp space and on the card.
*/
- drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
+ struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
unsigned int texAge[MGA_NR_TEX_HEAPS];
/* Mechanism to validate card state.
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index be49dbb9ec3f..5572939fc7d1 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -36,7 +36,7 @@
#include "drm_pciids.h"
-static int mga_driver_device_is_agp(drm_device_t * dev);
+static int mga_driver_device_is_agp(struct drm_device * dev);
static struct pci_device_id pciidlist[] = {
mga_PCI_IDS
@@ -118,7 +118,7 @@ MODULE_LICENSE("GPL and additional rights");
* \returns
* If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
*/
-static int mga_driver_device_is_agp(drm_device_t * dev)
+static int mga_driver_device_is_agp(struct drm_device * dev)
{
const struct pci_dev *const pdev = dev->pdev;
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 6b0c53193506..49253affa475 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -65,7 +65,7 @@ typedef struct drm_mga_freelist {
struct drm_mga_freelist *next;
struct drm_mga_freelist *prev;
drm_mga_age_t age;
- drm_buf_t *buf;
+ struct drm_buf *buf;
} drm_mga_freelist_t;
typedef struct {
@@ -157,10 +157,10 @@ extern int mga_dma_init(DRM_IOCTL_ARGS);
extern int mga_dma_flush(DRM_IOCTL_ARGS);
extern int mga_dma_reset(DRM_IOCTL_ARGS);
extern int mga_dma_buffers(DRM_IOCTL_ARGS);
-extern int mga_driver_load(drm_device_t *dev, unsigned long flags);
-extern int mga_driver_unload(drm_device_t * dev);
-extern void mga_driver_lastclose(drm_device_t * dev);
-extern int mga_driver_dma_quiescent(drm_device_t * dev);
+extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
+extern int mga_driver_unload(struct drm_device * dev);
+extern void mga_driver_lastclose(struct drm_device * dev);
+extern int mga_driver_dma_quiescent(struct drm_device * dev);
extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
@@ -168,7 +168,7 @@ extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
-extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
/* mga_warp.c */
extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
@@ -176,12 +176,12 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
extern int mga_warp_init(drm_mga_private_t * dev_priv);
/* mga_irq.c */
-extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mga_driver_irq_preinstall(drm_device_t * dev);
-extern void mga_driver_irq_postinstall(drm_device_t * dev);
-extern void mga_driver_irq_uninstall(drm_device_t * dev);
+extern void mga_driver_irq_preinstall(struct drm_device * dev);
+extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern void mga_driver_irq_uninstall(struct drm_device * dev);
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index eb9644024172..9302cb8f0f83 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -37,7 +37,7 @@
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *) arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
int status;
int handled = 0;
@@ -78,7 +78,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
}
-int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
{
unsigned int cur_vblank;
int ret = 0;
@@ -96,7 +96,7 @@ int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
unsigned int cur_fence;
@@ -115,7 +115,7 @@ int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-void mga_driver_irq_preinstall(drm_device_t * dev)
+void mga_driver_irq_preinstall(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -125,7 +125,7 @@ void mga_driver_irq_preinstall(drm_device_t * dev)
MGA_WRITE(MGA_ICLEAR, ~0);
}
-void mga_driver_irq_postinstall(drm_device_t * dev)
+void mga_driver_irq_postinstall(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -135,7 +135,7 @@ void mga_driver_irq_postinstall(drm_device_t * dev)
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
}
-void mga_driver_irq_uninstall(drm_device_t * dev)
+void mga_driver_irq_uninstall(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
if (!dev_priv)
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 2837e669183a..d448b0aef33c 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -42,7 +42,7 @@
*/
static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
- drm_clip_rect_t * box)
+ struct drm_clip_rect * box)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -480,12 +480,12 @@ static int mga_verify_blit(drm_mga_private_t * dev_priv,
*
*/
-static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
+static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int nbox = sarea_priv->nbox;
int i;
DMA_LOCALS;
@@ -500,7 +500,7 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
ADVANCE_DMA();
for (i = 0; i < nbox; i++) {
- drm_clip_rect_t *box = &pbox[i];
+ struct drm_clip_rect *box = &pbox[i];
u32 height = box->y2 - box->y1;
DRM_DEBUG(" from=%d,%d to=%d,%d\n",
@@ -568,12 +568,12 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
FLUSH_DMA();
}
-static void mga_dma_dispatch_swap(drm_device_t * dev)
+static void mga_dma_dispatch_swap(struct drm_device * dev)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int nbox = sarea_priv->nbox;
int i;
DMA_LOCALS;
@@ -598,7 +598,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev)
MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
for (i = 0; i < nbox; i++) {
- drm_clip_rect_t *box = &pbox[i];
+ struct drm_clip_rect *box = &pbox[i];
u32 height = box->y2 - box->y1;
u32 start = box->y1 * dev_priv->front_pitch;
@@ -622,7 +622,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev)
DRM_DEBUG("%s... done.\n", __FUNCTION__);
}
-static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -669,7 +669,7 @@ static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
FLUSH_DMA();
}
-static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
unsigned int start, unsigned int end)
{
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -718,7 +718,7 @@ static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
/* This copies a 64 byte aligned agp region to the frambuffer with a
* standard blit, the ioctl needs to do checking.
*/
-static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
unsigned int dstorg, unsigned int length)
{
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -766,12 +766,12 @@ static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
FLUSH_DMA();
}
-static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
+static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
{
drm_mga_private_t *dev_priv = dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int nbox = sarea_priv->nbox;
u32 scandir = 0, i;
DMA_LOCALS;
@@ -880,8 +880,8 @@ static int mga_dma_vertex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_vertex_t vertex;
@@ -920,8 +920,8 @@ static int mga_dma_indices(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_indices_t indices;
@@ -959,9 +959,9 @@ static int mga_dma_indices(DRM_IOCTL_ARGS)
static int mga_dma_iload(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_mga_private_t *dev_priv = dev->dev_private;
- drm_buf_t *buf;
+ struct drm_buf *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_iload_t iload;
DRM_DEBUG("\n");
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 1014602c43a7..b163ed09bd81 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -81,7 +81,7 @@ static u32 r128_cce_microcode[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static int R128_READ_PLL(drm_device_t * dev, int addr)
+static int R128_READ_PLL(struct drm_device * dev, int addr)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -271,7 +271,7 @@ static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
/* Reset the engine. This will stop the CCE if it is running.
*/
-static int r128_do_engine_reset(drm_device_t * dev)
+static int r128_do_engine_reset(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
@@ -308,7 +308,7 @@ static int r128_do_engine_reset(drm_device_t * dev)
return 0;
}
-static void r128_cce_init_ring_buffer(drm_device_t * dev,
+static void r128_cce_init_ring_buffer(struct drm_device * dev,
drm_r128_private_t * dev_priv)
{
u32 ring_start;
@@ -347,7 +347,7 @@ static void r128_cce_init_ring_buffer(drm_device_t * dev,
R128_WRITE(R128_BUS_CNTL, tmp);
}
-static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
+static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
{
drm_r128_private_t *dev_priv;
@@ -456,8 +456,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
(dev_priv->span_offset >> 5));
- DRM_GETSAREA();
-
+ dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
dev->dev_private = (void *)dev_priv;
@@ -585,7 +584,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
return 0;
}
-int r128_do_cleanup_cce(drm_device_t * dev)
+int r128_do_cleanup_cce(struct drm_device * dev)
{
/* Make sure interrupts are disabled here because the uninstall ioctl
@@ -770,11 +769,11 @@ int r128_fullscreen(DRM_IOCTL_ARGS)
#define R128_BUFFER_FREE 0
#if 0
-static int r128_freelist_init(drm_device_t * dev)
+static int r128_freelist_init(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
- drm_buf_t *buf;
+ struct drm_buf *buf;
drm_r128_buf_priv_t *buf_priv;
drm_r128_freelist_t *entry;
int i;
@@ -816,12 +815,12 @@ static int r128_freelist_init(drm_device_t * dev)
}
#endif
-static drm_buf_t *r128_freelist_get(drm_device_t * dev)
+static struct drm_buf *r128_freelist_get(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv;
- drm_buf_t *buf;
+ struct drm_buf *buf;
int i, t;
/* FIXME: Optimize -- use freelist code */
@@ -854,13 +853,13 @@ static drm_buf_t *r128_freelist_get(drm_device_t * dev)
return NULL;
}
-void r128_freelist_reset(drm_device_t * dev)
+void r128_freelist_reset(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int i;
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
buf_priv->age = 0;
}
@@ -887,10 +886,10 @@ int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
return DRM_ERR(EBUSY);
}
-static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+static int r128_cce_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d)
{
int i;
- drm_buf_t *buf;
+ struct drm_buf *buf;
for (i = d->granted_count; i < d->request_count; i++) {
buf = r128_freelist_get(dev);
@@ -914,10 +913,10 @@ static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
int r128_cce_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int ret = 0;
- drm_dma_t __user *argp = (void __user *)data;
- drm_dma_t d;
+ struct drm_dma __user *argp = (void __user *)data;
+ struct drm_dma d;
LOCK_TEST_WITH_RETURN(dev, filp);
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 6e8af313f2b4..e94a39c6e327 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -153,7 +153,7 @@ typedef struct drm_r128_sarea {
/* The current cliprects, or a subset thereof.
*/
- drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS];
unsigned int nbox;
/* Counters for client-side throttling of rendering clients.
@@ -161,7 +161,7 @@ typedef struct drm_r128_sarea {
unsigned int last_frame;
unsigned int last_dispatch;
- drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
+ struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
unsigned int tex_age[R128_NR_TEX_HEAPS];
int ctx_owner;
int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 9086835686dc..72249fb2fd1c 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -57,7 +57,7 @@
typedef struct drm_r128_freelist {
unsigned int age;
- drm_buf_t *buf;
+ struct drm_buf *buf;
struct drm_r128_freelist *next;
struct drm_r128_freelist *prev;
} drm_r128_freelist_t;
@@ -118,7 +118,7 @@ typedef struct drm_r128_private {
drm_local_map_t *cce_ring;
drm_local_map_t *ring_rptr;
drm_local_map_t *agp_textures;
- drm_ati_pcigart_info gart_info;
+ struct drm_ati_pcigart_info gart_info;
} drm_r128_private_t;
typedef struct drm_r128_buf_priv {
@@ -142,21 +142,21 @@ extern int r128_engine_reset(DRM_IOCTL_ARGS);
extern int r128_fullscreen(DRM_IOCTL_ARGS);
extern int r128_cce_buffers(DRM_IOCTL_ARGS);
-extern void r128_freelist_reset(drm_device_t * dev);
+extern void r128_freelist_reset(struct drm_device * dev);
extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
-extern int r128_do_cleanup_cce(drm_device_t * dev);
+extern int r128_do_cleanup_cce(struct drm_device * dev);
-extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
-extern void r128_driver_irq_preinstall(drm_device_t * dev);
-extern void r128_driver_irq_postinstall(drm_device_t * dev);
-extern void r128_driver_irq_uninstall(drm_device_t * dev);
-extern void r128_driver_lastclose(drm_device_t * dev);
-extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void r128_driver_irq_preinstall(struct drm_device * dev);
+extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern void r128_driver_irq_uninstall(struct drm_device * dev);
+extern void r128_driver_lastclose(struct drm_device * dev);
+extern void r128_driver_preclose(struct drm_device * dev, DRMFILE filp);
extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 87f8ca2b0685..c76fdca7662d 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -37,7 +37,7 @@
irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *) arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
int status;
@@ -54,7 +54,7 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
}
-int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
{
unsigned int cur_vblank;
int ret = 0;
@@ -72,7 +72,7 @@ int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-void r128_driver_irq_preinstall(drm_device_t * dev)
+void r128_driver_irq_preinstall(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
@@ -82,7 +82,7 @@ void r128_driver_irq_preinstall(drm_device_t * dev)
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
}
-void r128_driver_irq_postinstall(drm_device_t * dev)
+void r128_driver_irq_postinstall(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
@@ -90,7 +90,7 @@ void r128_driver_irq_postinstall(drm_device_t * dev)
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
}
-void r128_driver_irq_uninstall(drm_device_t * dev)
+void r128_driver_irq_uninstall(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
if (!dev_priv)
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 17b11e7d8f32..7b334fb7d649 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -38,7 +38,7 @@
*/
static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
- drm_clip_rect_t * boxes, int count)
+ struct drm_clip_rect * boxes, int count)
{
u32 aux_sc_cntl = 0x00000000;
RING_LOCALS;
@@ -352,13 +352,13 @@ static void r128_print_dirty(const char *msg, unsigned int flags)
(flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
}
-static void r128_cce_dispatch_clear(drm_device_t * dev,
+static void r128_cce_dispatch_clear(struct drm_device * dev,
drm_r128_clear_t * clear)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
unsigned int flags = clear->flags;
int i;
RING_LOCALS;
@@ -458,12 +458,12 @@ static void r128_cce_dispatch_clear(drm_device_t * dev,
}
}
-static void r128_cce_dispatch_swap(drm_device_t * dev)
+static void r128_cce_dispatch_swap(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int i;
RING_LOCALS;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -524,7 +524,7 @@ static void r128_cce_dispatch_swap(drm_device_t * dev)
ADVANCE_RING();
}
-static void r128_cce_dispatch_flip(drm_device_t * dev)
+static void r128_cce_dispatch_flip(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -567,7 +567,7 @@ static void r128_cce_dispatch_flip(drm_device_t * dev)
ADVANCE_RING();
}
-static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -637,8 +637,8 @@ static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
sarea_priv->nbox = 0;
}
-static void r128_cce_dispatch_indirect(drm_device_t * dev,
- drm_buf_t * buf, int start, int end)
+static void r128_cce_dispatch_indirect(struct drm_device * dev,
+ struct drm_buf * buf, int start, int end)
{
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -692,8 +692,8 @@ static void r128_cce_dispatch_indirect(drm_device_t * dev,
dev_priv->sarea_priv->last_dispatch++;
}
-static void r128_cce_dispatch_indices(drm_device_t * dev,
- drm_buf_t * buf,
+static void r128_cce_dispatch_indices(struct drm_device * dev,
+ struct drm_buf * buf,
int start, int end, int count)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -777,11 +777,11 @@ static void r128_cce_dispatch_indices(drm_device_t * dev,
}
static int r128_cce_dispatch_blit(DRMFILE filp,
- drm_device_t * dev, drm_r128_blit_t * blit)
+ struct drm_device * dev, drm_r128_blit_t * blit)
{
drm_r128_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_r128_buf_priv_t *buf_priv;
u32 *data;
int dword_shift, dwords;
@@ -887,7 +887,7 @@ static int r128_cce_dispatch_blit(DRMFILE filp,
* have hardware stencil support.
*/
-static int r128_cce_dispatch_write_span(drm_device_t * dev,
+static int r128_cce_dispatch_write_span(struct drm_device * dev,
drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -983,7 +983,7 @@ static int r128_cce_dispatch_write_span(drm_device_t * dev,
return 0;
}
-static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1105,7 +1105,7 @@ static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
return 0;
}
-static int r128_cce_dispatch_read_span(drm_device_t * dev,
+static int r128_cce_dispatch_read_span(struct drm_device * dev,
drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1148,7 +1148,7 @@ static int r128_cce_dispatch_read_span(drm_device_t * dev,
return 0;
}
-static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
drm_r128_depth_t * depth)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1220,7 +1220,7 @@ static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
* Polygon stipple
*/
-static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
{
drm_r128_private_t *dev_priv = dev->dev_private;
int i;
@@ -1269,7 +1269,7 @@ static int r128_cce_clear(DRM_IOCTL_ARGS)
return 0;
}
-static int r128_do_init_pageflip(drm_device_t * dev)
+static int r128_do_init_pageflip(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n");
@@ -1288,7 +1288,7 @@ static int r128_do_init_pageflip(drm_device_t * dev)
return 0;
}
-static int r128_do_cleanup_pageflip(drm_device_t * dev)
+static int r128_do_cleanup_pageflip(struct drm_device * dev)
{
drm_r128_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n");
@@ -1354,8 +1354,8 @@ static int r128_cce_vertex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_r128_buf_priv_t *buf_priv;
drm_r128_vertex_t vertex;
@@ -1413,8 +1413,8 @@ static int r128_cce_indices(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_r128_buf_priv_t *buf_priv;
drm_r128_indices_t elts;
int count;
@@ -1483,7 +1483,7 @@ static int r128_cce_indices(DRM_IOCTL_ARGS)
static int r128_cce_blit(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
drm_r128_blit_t blit;
int ret;
@@ -1571,8 +1571,8 @@ static int r128_cce_indirect(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_r128_buf_priv_t *buf_priv;
drm_r128_indirect_t indirect;
#if 0
@@ -1675,7 +1675,7 @@ static int r128_getparam(DRM_IOCTL_ARGS)
return 0;
}
-void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void r128_driver_preclose(struct drm_device * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1685,7 +1685,7 @@ void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
}
}
-void r128_driver_lastclose(drm_device_t * dev)
+void r128_driver_lastclose(struct drm_device * dev)
{
r128_do_cleanup_cce(dev);
}
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index 032a022ec6a8..4e5aca6ba59a 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -55,7 +55,7 @@ static const int r300_cliprect_cntl[4] = {
static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t *cmdbuf, int n)
{
- drm_clip_rect_t box;
+ struct drm_clip_rect box;
int nr;
int i;
RING_LOCALS;
@@ -148,15 +148,16 @@ void r300_init_reg_flags(void)
/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
- ADD_RANGE(0x2080, 1);
+ ADD_RANGE(R300_VAP_CNTL, 1);
ADD_RANGE(R300_SE_VTE_CNTL, 2);
ADD_RANGE(0x2134, 2);
- ADD_RANGE(0x2140, 1);
+ ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
ADD_RANGE(0x21DC, 1);
- ADD_RANGE(0x221C, 1);
- ADD_RANGE(0x2220, 4);
- ADD_RANGE(0x2288, 1);
+ ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
+ ADD_RANGE(R300_VAP_CLIP_X_0, 4);
+ ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
+ ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
ADD_RANGE(R300_GB_ENABLE, 1);
@@ -168,13 +169,13 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_RE_POINTSIZE, 1);
ADD_RANGE(0x4230, 3);
ADD_RANGE(R300_RE_LINE_CNT, 1);
- ADD_RANGE(0x4238, 1);
+ ADD_RANGE(R300_RE_UNK4238, 1);
ADD_RANGE(0x4260, 3);
- ADD_RANGE(0x4274, 4);
- ADD_RANGE(0x4288, 5);
- ADD_RANGE(0x42A0, 1);
+ ADD_RANGE(R300_RE_SHADE, 4);
+ ADD_RANGE(R300_RE_POLYGON_MODE, 5);
+ ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
- ADD_RANGE(0x42B4, 1);
+ ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
ADD_RANGE(R300_RE_CULL_CNTL, 1);
ADD_RANGE(0x42C0, 2);
ADD_RANGE(R300_RS_CNTL_0, 2);
@@ -190,22 +191,22 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_PFS_INSTR1_0, 64);
ADD_RANGE(R300_PFS_INSTR2_0, 64);
ADD_RANGE(R300_PFS_INSTR3_0, 64);
- ADD_RANGE(0x4BC0, 1);
- ADD_RANGE(0x4BC8, 3);
+ ADD_RANGE(R300_RE_FOG_STATE, 1);
+ ADD_RANGE(R300_FOG_COLOR_R, 3);
ADD_RANGE(R300_PP_ALPHA_TEST, 2);
ADD_RANGE(0x4BD8, 1);
ADD_RANGE(R300_PFS_PARAM_0_X, 64);
ADD_RANGE(0x4E00, 1);
ADD_RANGE(R300_RB3D_CBLEND, 2);
ADD_RANGE(R300_RB3D_COLORMASK, 1);
- ADD_RANGE(0x4E10, 3);
+ ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
ADD_RANGE(0x4E50, 9);
ADD_RANGE(0x4E88, 1);
ADD_RANGE(0x4EA0, 2);
ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
- ADD_RANGE(0x4F10, 4);
+ ADD_RANGE(R300_RB3D_ZSTENCIL_FORMAT, 4);
ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
ADD_RANGE(0x4F28, 1);
@@ -224,7 +225,7 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
/* Sporadic registers used as primitives are emitted */
- ADD_RANGE(0x4f18, 1);
+ ADD_RANGE(R300_RB3D_ZCACHE_CTLSTAT, 1);
ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
@@ -692,9 +693,9 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
BEGIN_RING(6);
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
- OUT_RING(0xa);
- OUT_RING(CP_PACKET0(0x4f18, 0));
- OUT_RING(0x3);
+ OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
+ OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
+ OUT_RING(R300_RB3D_ZCACHE_UNKNOWN_03);
OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
OUT_RING(0x0);
ADVANCE_RING();
@@ -705,7 +706,7 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
* The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
* be careful about how this function is called.
*/
-static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -766,8 +767,8 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
}
BEGIN_RING(2);
- OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0));
- OUT_RING(dev_priv->scratch_ages[header.scratch.reg]);
+ OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
+ OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
ADVANCE_RING();
return 0;
@@ -778,14 +779,14 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
* commands on the DMA ring buffer.
* Called by the ioctl handler function radeon_cp_cmdbuf.
*/
-int r300_do_cp_cmdbuf(drm_device_t *dev,
+int r300_do_cp_cmdbuf(struct drm_device *dev,
DRMFILE filp,
- drm_file_t *filp_priv,
+ struct drm_file *filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf = NULL;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf = NULL;
int emit_dispatch_age = 0;
int ret = 0;
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index ecda760ae8c0..3ae57ecc7afd 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -47,12 +47,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28
/*
-This file contains registers and constants for the R300. They have been
-found mostly by examining command buffers captured using glxtest, as well
-as by extrapolating some known registers and constants from the R200.
-
-I am fairly certain that they are correct unless stated otherwise in comments.
-*/
+ * This file contains registers and constants for the R300. They have been
+ * found mostly by examining command buffers captured using glxtest, as well
+ * as by extrapolating some known registers and constants from the R200.
+ * I am fairly certain that they are correct unless stated otherwise
+ * in comments.
+ */
#define R300_SE_VPORT_XSCALE 0x1D98
#define R300_SE_VPORT_XOFFSET 0x1D9C
@@ -61,49 +61,60 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_SE_VPORT_ZSCALE 0x1DA8
#define R300_SE_VPORT_ZOFFSET 0x1DAC
-/* This register is written directly and also starts data section in many 3d CP_PACKET3's */
-#define R300_VAP_VF_CNTL 0x2084
-# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0
-# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0)
-# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0)
-# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0)
-# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0)
-# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0)
-# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0)
-# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0)
-# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0)
-# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0)
-# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0)
-# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0)
-
-# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4
- /* State based - direct writes to registers trigger vertex generation */
-# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4)
-# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4)
-# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4)
-# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4)
-
- /* I don't think I saw these three used.. */
-# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6
-# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9
-# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10
-
- /* index size - when not set the indices are assumed to be 16 bit */
-# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11)
- /* number of vertices */
-# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16
+/*
+ * Vertex Array Processing (VAP) Control
+ * Stolen from r200 code from Christoph Brill (It's a guess!)
+ */
+#define R300_VAP_CNTL 0x2080
+
+/* This register is written directly and also starts data section
+ * in many 3d CP_PACKET3's
+ */
+#define R300_VAP_VF_CNTL 0x2084
+# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0
+# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0)
+# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0)
+# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0)
+
+# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4
+ /* State based - direct writes to registers trigger vertex
+ generation */
+# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4)
+
+ /* I don't think I saw these three used.. */
+# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6
+# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9
+# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10
+
+ /* index size - when not set the indices are assumed to be 16 bit */
+# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11)
+ /* number of vertices */
+# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16
/* BEGIN: Wild guesses */
#define R300_VAP_OUTPUT_VTX_FMT_0 0x2090
# define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0)
# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1)
-# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */
-# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */
-# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */
-# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */
+# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094
+ /* each of the following is 3 bits wide, specifies number
+ of components */
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
@@ -112,7 +123,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
-/* END */
+/* END: Wild guesses */
#define R300_SE_VTE_CNTL 0x20b0
# define R300_VPORT_X_SCALE_ENA 0x00000001
@@ -128,43 +139,54 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_VTX_ST_DENORMALIZED 0x00001000
/* BEGIN: Vertex data assembly - lots of uncertainties */
+
+/* gap */
+
+#define R300_VAP_CNTL_STATUS 0x2140
+# define R300_VC_NO_SWAP (0 << 0)
+# define R300_VC_16BIT_SWAP (1 << 0)
+# define R300_VC_32BIT_SWAP (2 << 0)
+# define R300_VAP_TCL_BYPASS (1 << 8)
+
/* gap */
+
/* Where do we get our vertex data?
-//
-// Vertex data either comes either from immediate mode registers or from
-// vertex arrays.
-// There appears to be no mixed mode (though we can force the pitch of
-// vertex arrays to 0, effectively reusing the same element over and over
-// again).
-//
-// Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
-// if these registers influence vertex array processing.
-//
-// Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
-//
-// In both cases, vertex attributes are then passed through INPUT_ROUTE.
-
-// Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
-// into the vertex processor's input registers.
-// The first word routes the first input, the second word the second, etc.
-// The corresponding input is routed into the register with the given index.
-// The list is ended by a word with INPUT_ROUTE_END set.
-//
-// Always set COMPONENTS_4 in immediate mode. */
+ *
+ * Vertex data either comes either from immediate mode registers or from
+ * vertex arrays.
+ * There appears to be no mixed mode (though we can force the pitch of
+ * vertex arrays to 0, effectively reusing the same element over and over
+ * again).
+ *
+ * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+ * if these registers influence vertex array processing.
+ *
+ * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+ *
+ * In both cases, vertex attributes are then passed through INPUT_ROUTE.
+ *
+ * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+ * into the vertex processor's input registers.
+ * The first word routes the first input, the second word the second, etc.
+ * The corresponding input is routed into the register with the given index.
+ * The list is ended by a word with INPUT_ROUTE_END set.
+ *
+ * Always set COMPONENTS_4 in immediate mode.
+ */
#define R300_VAP_INPUT_ROUTE_0_0 0x2150
# define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0)
# define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0)
# define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0)
# define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0)
-# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */
+# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */
# define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8
-# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */
+# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */
# define R300_VAP_INPUT_ROUTE_END (1 << 13)
-# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */
-# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */
-# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */
-# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */
+# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */
#define R300_VAP_INPUT_ROUTE_0_1 0x2154
#define R300_VAP_INPUT_ROUTE_0_2 0x2158
#define R300_VAP_INPUT_ROUTE_0_3 0x215C
@@ -174,10 +196,12 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_VAP_INPUT_ROUTE_0_7 0x216C
/* gap */
+
/* Notes:
-// - always set up to produce at least two attributes:
-// if vertex program uses only position, fglrx will set normal, too
-// - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal */
+ * - always set up to produce at least two attributes:
+ * if vertex program uses only position, fglrx will set normal, too
+ * - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal.
+ */
#define R300_VAP_INPUT_CNTL_0 0x2180
# define R300_INPUT_CNTL_0_COLOR 0x00000001
#define R300_VAP_INPUT_CNTL_1 0x2184
@@ -186,20 +210,22 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_INPUT_CNTL_COLOR 0x00000004
# define R300_INPUT_CNTL_TC0 0x00000400
# define R300_INPUT_CNTL_TC1 0x00000800
-# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
-# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
-# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
-# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
-# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
-# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
+# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
+# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
+# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
+# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
+# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
+# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
/* gap */
+
/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
-// are set to a swizzling bit pattern, other words are 0.
-//
-// In immediate mode, the pattern is always set to xyzw. In vertex array
-// mode, the swizzling pattern is e.g. used to set zw components in texture
-// coordinates with only tweo components. */
+ * are set to a swizzling bit pattern, other words are 0.
+ *
+ * In immediate mode, the pattern is always set to xyzw. In vertex array
+ * mode, the swizzling pattern is e.g. used to set zw components in texture
+ * coordinates with only tweo components.
+ */
#define R300_VAP_INPUT_ROUTE_1_0 0x21E0
# define R300_INPUT_ROUTE_SELECT_X 0
# define R300_INPUT_ROUTE_SELECT_Y 1
@@ -208,11 +234,11 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_INPUT_ROUTE_SELECT_ZERO 4
# define R300_INPUT_ROUTE_SELECT_ONE 5
# define R300_INPUT_ROUTE_SELECT_MASK 7
-# define R300_INPUT_ROUTE_X_SHIFT 0
-# define R300_INPUT_ROUTE_Y_SHIFT 3
-# define R300_INPUT_ROUTE_Z_SHIFT 6
-# define R300_INPUT_ROUTE_W_SHIFT 9
-# define R300_INPUT_ROUTE_ENABLE (15 << 12)
+# define R300_INPUT_ROUTE_X_SHIFT 0
+# define R300_INPUT_ROUTE_Y_SHIFT 3
+# define R300_INPUT_ROUTE_Z_SHIFT 6
+# define R300_INPUT_ROUTE_W_SHIFT 9
+# define R300_INPUT_ROUTE_ENABLE (15 << 12)
#define R300_VAP_INPUT_ROUTE_1_1 0x21E4
#define R300_VAP_INPUT_ROUTE_1_2 0x21E8
#define R300_VAP_INPUT_ROUTE_1_3 0x21EC
@@ -221,79 +247,107 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_VAP_INPUT_ROUTE_1_6 0x21F8
#define R300_VAP_INPUT_ROUTE_1_7 0x21FC
-/* END */
+/* END: Vertex data assembly */
/* gap */
-/* BEGIN: Upload vertex program and data
-// The programmable vertex shader unit has a memory bank of unknown size
-// that can be written to in 16 byte units by writing the address into
-// UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
-//
-// Pointers into the memory bank are always in multiples of 16 bytes.
-//
-// The memory bank is divided into areas with fixed meaning.
-//
-// Starting at address UPLOAD_PROGRAM: Vertex program instructions.
-// Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
-// whereas the difference between known addresses suggests size 512.
-//
-// Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
-// Native reported limits and the VPI layout suggest size 256, whereas
-// difference between known addresses suggests size 512.
-//
-// At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
-// floating point pointsize. The exact purpose of this state is uncertain,
-// as there is also the R300_RE_POINTSIZE register.
-//
-// Multiple vertex programs and parameter sets can be loaded at once,
-// which could explain the size discrepancy. */
+
+/* BEGIN: Upload vertex program and data */
+
+/*
+ * The programmable vertex shader unit has a memory bank of unknown size
+ * that can be written to in 16 byte units by writing the address into
+ * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+ *
+ * Pointers into the memory bank are always in multiples of 16 bytes.
+ *
+ * The memory bank is divided into areas with fixed meaning.
+ *
+ * Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+ * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+ * whereas the difference between known addresses suggests size 512.
+ *
+ * Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+ * Native reported limits and the VPI layout suggest size 256, whereas
+ * difference between known addresses suggests size 512.
+ *
+ * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+ * floating point pointsize. The exact purpose of this state is uncertain,
+ * as there is also the R300_RE_POINTSIZE register.
+ *
+ * Multiple vertex programs and parameter sets can be loaded at once,
+ * which could explain the size discrepancy.
+ */
#define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200
# define R300_PVS_UPLOAD_PROGRAM 0x00000000
# define R300_PVS_UPLOAD_PARAMETERS 0x00000200
# define R300_PVS_UPLOAD_POINTSIZE 0x00000406
+
/* gap */
+
#define R300_VAP_PVS_UPLOAD_DATA 0x2208
-/* END */
+
+/* END: Upload vertex program and data */
/* gap */
+
/* I do not know the purpose of this register. However, I do know that
-// it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
-// for normal rendering. */
+ * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+ * for normal rendering.
+ */
#define R300_VAP_UNKNOWN_221C 0x221C
# define R300_221C_NORMAL 0x00000000
# define R300_221C_CLEAR 0x0001C000
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_CLIP_X_0 0x2220
+#define R300_VAP_CLIP_X_1 0x2224
+#define R300_VAP_CLIP_Y_0 0x2228
+#define R300_VAP_CLIP_Y_1 0x2230
+
/* gap */
+
/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
-// rendering commands and overwriting vertex program parameters.
-// Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
-// avoids bugs caused by still running shaders reading bad data from memory. */
-#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
+ * rendering commands and overwriting vertex program parameters.
+ * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+ * avoids bugs caused by still running shaders reading bad data from memory.
+ */
+#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
/* Absolutely no clue what this register is about. */
#define R300_VAP_UNKNOWN_2288 0x2288
-# define R300_2288_R300 0x00750000 /* -- nh */
-# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
+# define R300_2288_R300 0x00750000 /* -- nh */
+# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
/* gap */
+
/* Addresses are relative to the vertex program instruction area of the
-// memory bank. PROGRAM_END points to the last instruction of the active
-// program
-//
-// The meaning of the two UNKNOWN fields is obviously not known. However,
-// experiments so far have shown that both *must* point to an instruction
-// inside the vertex program, otherwise the GPU locks up.
-// fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
-// CNTL_1_UNKNOWN points to instruction where last write to position takes place.
-// Most likely this is used to ignore rest of the program in cases where group of verts arent visible.
-// For some reason this "section" is sometimes accepted other instruction that have
-// no relationship with position calculations.
-*/
+ * memory bank. PROGRAM_END points to the last instruction of the active
+ * program
+ *
+ * The meaning of the two UNKNOWN fields is obviously not known. However,
+ * experiments so far have shown that both *must* point to an instruction
+ * inside the vertex program, otherwise the GPU locks up.
+ *
+ * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
+ * position takes place.
+ *
+ * Most likely this is used to ignore rest of the program in cases
+ * where group of verts arent visible. For some reason this "section"
+ * is sometimes accepted other instruction that have no relationship with
+ * position calculations.
+ */
#define R300_VAP_PVS_CNTL_1 0x22D0
# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
# define R300_PVS_CNTL_1_POS_END_SHIFT 10
# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20
-/* Addresses are relative to the vertex program parameters area. */
+/* Addresses are relative the the vertex program parameters area. */
#define R300_VAP_PVS_CNTL_2 0x22D4
# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16
@@ -302,23 +356,26 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
-// immediate vertices */
+ * immediate vertices
+ */
#define R300_VAP_VTX_COLOR_R 0x2464
#define R300_VAP_VTX_COLOR_G 0x2468
#define R300_VAP_VTX_COLOR_B 0x246C
-#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
+#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
#define R300_VAP_VTX_POS_0_Y_1 0x2494
-#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
-#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
+#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
+#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
#define R300_VAP_VTX_POS_0_Y_2 0x24A4
#define R300_VAP_VTX_POS_0_Z_2 0x24A8
-#define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */
+/* write 0 to indicate end of packet? */
+#define R300_VAP_VTX_END_OF_PKT 0x24AC
/* gap */
/* These are values from r300_reg/r300_reg.h - they are known to be correct
- and are here so we can use one register file instead of several
- - Vladimir */
+ * and are here so we can use one register file instead of several
+ * - Vladimir
+ */
#define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000
# define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0)
# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1)
@@ -341,14 +398,16 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
/* UNK30 seems to enables point to quad transformation on textures
- (or something closely related to that).
- This bit is rather fatal at the time being due to lackings at pixel shader side */
+ * (or something closely related to that).
+ * This bit is rather fatal at the time being due to lackings at pixel
+ * shader side
+ */
#define R300_GB_ENABLE 0x4008
# define R300_GB_POINT_STUFF_ENABLE (1<<0)
# define R300_GB_LINE_STUFF_ENABLE (1<<1)
# define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2)
# define R300_GB_STENCIL_AUTO_ENABLE (1<<4)
-# define R300_GB_UNK30 (1<<30)
+# define R300_GB_UNK31 (1<<31)
/* each of the following is 2 bits wide */
#define R300_GB_TEX_REPLICATE 0
#define R300_GB_TEX_ST 1
@@ -383,11 +442,13 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_GB_MSPOS1__MS_Y5_SHIFT 20
# define R300_GB_MSPOS1__MSBD1 24
+
#define R300_GB_TILE_CONFIG 0x4018
# define R300_GB_TILE_ENABLE (1<<0)
# define R300_GB_TILE_PIPE_COUNT_RV300 0
# define R300_GB_TILE_PIPE_COUNT_R300 (3<<1)
# define R300_GB_TILE_PIPE_COUNT_R420 (7<<1)
+# define R300_GB_TILE_PIPE_COUNT_RV410 (3<<1)
# define R300_GB_TILE_SIZE_8 0
# define R300_GB_TILE_SIZE_16 (1<<4)
# define R300_GB_TILE_SIZE_32 (2<<4)
@@ -442,17 +503,18 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_GB_W_SELECT_1 (1<<4)
#define R300_GB_AA_CONFIG 0x4020
+# define R300_AA_DISABLE 0x00
# define R300_AA_ENABLE 0x01
# define R300_AA_SUBSAMPLES_2 0
# define R300_AA_SUBSAMPLES_3 (1<<1)
# define R300_AA_SUBSAMPLES_4 (2<<1)
# define R300_AA_SUBSAMPLES_6 (3<<1)
-/* END */
-
/* gap */
+
/* Zero to flush caches. */
#define R300_TX_CNTL 0x4100
+#define R300_TX_FLUSH 0x0
/* The upper enable bits are guessed, based on fglrx reported limits. */
#define R300_TX_ENABLE 0x4104
@@ -474,24 +536,25 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_ENABLE_15 (1 << 15)
/* The pointsize is given in multiples of 6. The pointsize can be
-// enormous: Clear() renders a single point that fills the entire
-// framebuffer. */
+ * enormous: Clear() renders a single point that fills the entire
+ * framebuffer.
+ */
#define R300_RE_POINTSIZE 0x421C
# define R300_POINTSIZE_Y_SHIFT 0
-# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */
+# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */
# define R300_POINTSIZE_X_SHIFT 16
-# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */
+# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */
# define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6)
/* The line width is given in multiples of 6.
- In default mode lines are classified as vertical lines.
- HO: horizontal
- VE: vertical or horizontal
- HO & VE: no classification
-*/
+ * In default mode lines are classified as vertical lines.
+ * HO: horizontal
+ * VE: vertical or horizontal
+ * HO & VE: no classification
+ */
#define R300_RE_LINE_CNT 0x4234
# define R300_LINESIZE_SHIFT 0
-# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */
+# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */
# define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6)
# define R300_LINE_CNT_HO (1 << 16)
# define R300_LINE_CNT_VE (1 << 17)
@@ -499,6 +562,9 @@ I am fairly certain that they are correct unless stated otherwise in comments.
/* Some sort of scale or clamp value for texcoordless textures. */
#define R300_RE_UNK4238 0x4238
+/* Something shade related */
+#define R300_RE_SHADE 0x4274
+
#define R300_RE_SHADE_MODEL 0x4278
# define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa
# define R300_RE_SHADE_MODEL_FLAT 0x39595
@@ -513,24 +579,31 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_PM_BACK_LINE (1 << 7)
# define R300_PM_BACK_FILL (1 << 8)
+/* Fog parameters */
+#define R300_RE_FOG_SCALE 0x4294
+#define R300_RE_FOG_START 0x4298
+
/* Not sure why there are duplicate of factor and constant values.
- My best guess so far is that there are seperate zbiases for test and write.
- Ordering might be wrong.
- Some of the tests indicate that fgl has a fallback implementation of zbias
- via pixel shaders. */
+ * My best guess so far is that there are seperate zbiases for test and write.
+ * Ordering might be wrong.
+ * Some of the tests indicate that fgl has a fallback implementation of zbias
+ * via pixel shaders.
+ */
+#define R300_RE_ZBIAS_CNTL 0x42A0 /* GUESS */
#define R300_RE_ZBIAS_T_FACTOR 0x42A4
#define R300_RE_ZBIAS_T_CONSTANT 0x42A8
#define R300_RE_ZBIAS_W_FACTOR 0x42AC
#define R300_RE_ZBIAS_W_CONSTANT 0x42B0
/* This register needs to be set to (1<<1) for RV350 to correctly
- perform depth test (see --vb-triangles in r300_demo)
- Don't know about other chips. - Vladimir
- This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
- My guess is that there are two bits for each zbias primitive (FILL, LINE, POINT).
- One to enable depth test and one for depth write.
- Yet this doesnt explain why depth writes work ...
- */
+ * perform depth test (see --vb-triangles in r300_demo)
+ * Don't know about other chips. - Vladimir
+ * This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ * My guess is that there are two bits for each zbias primitive
+ * (FILL, LINE, POINT).
+ * One to enable depth test and one for depth write.
+ * Yet this doesnt explain why depth writes work ...
+ */
#define R300_RE_OCCLUSION_CNTL 0x42B4
# define R300_OCCLUSION_ON (1<<1)
@@ -540,30 +613,38 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FRONT_FACE_CCW (0 << 2)
# define R300_FRONT_FACE_CW (1 << 2)
-/* BEGIN: Rasterization / Interpolators - many guesses
-// 0_UNKNOWN_18 has always been set except for clear operations.
-// TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
-// on the vertex program, *not* the fragment program) */
+
+/* BEGIN: Rasterization / Interpolators - many guesses */
+
+/* 0_UNKNOWN_18 has always been set except for clear operations.
+ * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+ * on the vertex program, *not* the fragment program)
+ */
#define R300_RS_CNTL_0 0x4300
# define R300_RS_CNTL_TC_CNT_SHIFT 2
# define R300_RS_CNTL_TC_CNT_MASK (7 << 2)
-# define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */
+ /* number of color interpolators used */
+# define R300_RS_CNTL_CI_CNT_SHIFT 7
# define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18)
-/* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */
+ /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n
+ register. */
#define R300_RS_CNTL_1 0x4304
/* gap */
+
/* Only used for texture coordinates.
-// Use the source field to route texture coordinate input from the vertex program
-// to the desired interpolator. Note that the source field is relative to the
-// outputs the vertex program *actually* writes. If a vertex program only writes
-// texcoord[1], this will be source index 0.
-// Set INTERP_USED on all interpolators that produce data used by the
-// fragment program. INTERP_USED looks like a swizzling mask, but
-// I haven't seen it used that way.
-//
-// Note: The _UNKNOWN constants are always set in their respective register.
-// I don't know if this is necessary. */
+ * Use the source field to route texture coordinate input from the
+ * vertex program to the desired interpolator. Note that the source
+ * field is relative to the outputs the vertex program *actually*
+ * writes. If a vertex program only writes texcoord[1], this will
+ * be source index 0.
+ * Set INTERP_USED on all interpolators that produce data used by
+ * the fragment program. INTERP_USED looks like a swizzling mask,
+ * but I haven't seen it used that way.
+ *
+ * Note: The _UNKNOWN constants are always set in their respective
+ * register. I don't know if this is necessary.
+ */
#define R300_RS_INTERP_0 0x4310
#define R300_RS_INTERP_1 0x4314
# define R300_RS_INTERP_1_UNKNOWN 0x40
@@ -580,54 +661,63 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_RS_INTERP_USED 0x00D10000
/* These DWORDs control how vertex data is routed into fragment program
-// registers, after interpolators. */
+ * registers, after interpolators.
+ */
#define R300_RS_ROUTE_0 0x4330
#define R300_RS_ROUTE_1 0x4334
#define R300_RS_ROUTE_2 0x4338
-#define R300_RS_ROUTE_3 0x433C /* GUESS */
-#define R300_RS_ROUTE_4 0x4340 /* GUESS */
-#define R300_RS_ROUTE_5 0x4344 /* GUESS */
-#define R300_RS_ROUTE_6 0x4348 /* GUESS */
-#define R300_RS_ROUTE_7 0x434C /* GUESS */
+#define R300_RS_ROUTE_3 0x433C /* GUESS */
+#define R300_RS_ROUTE_4 0x4340 /* GUESS */
+#define R300_RS_ROUTE_5 0x4344 /* GUESS */
+#define R300_RS_ROUTE_6 0x4348 /* GUESS */
+#define R300_RS_ROUTE_7 0x434C /* GUESS */
# define R300_RS_ROUTE_SOURCE_INTERP_0 0
# define R300_RS_ROUTE_SOURCE_INTERP_1 1
# define R300_RS_ROUTE_SOURCE_INTERP_2 2
# define R300_RS_ROUTE_SOURCE_INTERP_3 3
# define R300_RS_ROUTE_SOURCE_INTERP_4 4
-# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */
-# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */
-# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */
-# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */
+# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */
+# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */
# define R300_RS_ROUTE_DEST_SHIFT 6
-# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */
+# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */
/* Special handling for color: When the fragment program uses color,
-// the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
-// color register index. */
+ * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+ * color register index.
+ *
+ * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any
+ * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state.
+ * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly
+ * correct or not. - Oliver.
+ */
# define R300_RS_ROUTE_0_COLOR (1 << 14)
# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17
-# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */
+# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */
/* As above, but for secondary color */
# define R300_RS_ROUTE_1_COLOR1 (1 << 14)
# define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
# define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17)
# define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11)
-/* END */
-
-/* BEGIN: Scissors and cliprects
-// There are four clipping rectangles. Their corner coordinates are inclusive.
-// Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
-// on whether the pixel is inside cliprects 0-3, respectively. For example,
-// if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
-// the number 3 (binary 0011).
-// Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
-// the pixel is rasterized.
-//
-// In addition to this, there is a scissors rectangle. Only pixels inside the
-// scissors rectangle are drawn. (coordinates are inclusive)
-//
-// For some reason, the top-left corner of the framebuffer is at (1440, 1440)
-// for the purpose of clipping and scissors. */
+/* END: Rasterization / Interpolators - many guesses */
+
+/* BEGIN: Scissors and cliprects */
+
+/* There are four clipping rectangles. Their corner coordinates are inclusive.
+ * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+ * on whether the pixel is inside cliprects 0-3, respectively. For example,
+ * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+ * the number 3 (binary 0011).
+ * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+ * the pixel is rasterized.
+ *
+ * In addition to this, there is a scissors rectangle. Only pixels inside the
+ * scissors rectangle are drawn. (coordinates are inclusive)
+ *
+ * For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+ * for the purpose of clipping and scissors.
+ */
#define R300_RE_CLIPRECT_TL_0 0x43B0
#define R300_RE_CLIPRECT_BR_0 0x43B4
#define R300_RE_CLIPRECT_TL_1 0x43B8
@@ -661,6 +751,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_CLIP_3210 (1 << 15)
/* gap */
+
#define R300_RE_SCISSORS_TL 0x43E0
#define R300_RE_SCISSORS_BR 0x43E4
# define R300_SCISSORS_OFFSET 1440
@@ -668,12 +759,15 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_SCISSORS_X_MASK (0x1FFF << 0)
# define R300_SCISSORS_Y_SHIFT 13
# define R300_SCISSORS_Y_MASK (0x1FFF << 13)
-/* END */
+/* END: Scissors and cliprects */
-/* BEGIN: Texture specification
-// The texture specification dwords are grouped by meaning and not by texture unit.
-// This means that e.g. the offset for texture image unit N is found in register
-// TX_OFFSET_0 + (4*N) */
+/* BEGIN: Texture specification */
+
+/*
+ * The texture specification dwords are grouped by meaning and not by texture
+ * unit. This means that e.g. the offset for texture image unit N is found in
+ * register TX_OFFSET_0 + (4*N)
+ */
#define R300_TX_FILTER_0 0x4400
# define R300_TX_REPEAT 0
# define R300_TX_MIRRORED 1
@@ -697,13 +791,14 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11)
/* NOTE: NEAREST doesnt seem to exist.
- Im not seting MAG_FILTER_MASK and (3 << 11) on for all
- anisotropy modes because that would void selected mag filter */
-# define R300_TX_MIN_FILTER_ANISO_NEAREST ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-# define R300_TX_MIN_FILTER_ANISO_LINEAR ((0 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST ((1 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR ((2 << 13) /*|R300_TX_MAG_FILTER_MASK|(3<<11)*/)
-# define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) )
+ * Im not seting MAG_FILTER_MASK and (3 << 11) on for all
+ * anisotropy modes because that would void selected mag filter
+ */
+# define R300_TX_MIN_FILTER_ANISO_NEAREST (0 << 13)
+# define R300_TX_MIN_FILTER_ANISO_LINEAR (0 << 13)
+# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13)
+# define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (2 << 13)
+# define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) )
# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21)
# define R300_TX_MAX_ANISO_2_TO_1 (2 << 21)
# define R300_TX_MAX_ANISO_4_TO_1 (4 << 21)
@@ -734,10 +829,10 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_HEIGHTMASK_SHIFT 11
# define R300_TX_HEIGHTMASK_MASK (2047 << 11)
# define R300_TX_UNK23 (1 << 23)
-# define R300_TX_SIZE_SHIFT 26 /* largest of width, height */
-# define R300_TX_SIZE_MASK (15 << 26)
-# define R300_TX_SIZE_PROJECTED (1<<30)
-# define R300_TX_SIZE_TXPITCH_EN (1<<31)
+# define R300_TX_MAX_MIP_LEVEL_SHIFT 26
+# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 26)
+# define R300_TX_SIZE_PROJECTED (1<<30)
+# define R300_TX_SIZE_TXPITCH_EN (1<<31)
#define R300_TX_FORMAT_0 0x44C0
/* The interpretation of the format word by Wladimir van der Laan */
/* The X, Y, Z and W refer to the layout of the components.
@@ -761,11 +856,11 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_FORMAT_DXT1 0xF
# define R300_TX_FORMAT_DXT3 0x10
# define R300_TX_FORMAT_DXT5 0x11
-# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */
-# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */
-# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */
-# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */
- /* 0x16 - some 16 bit green format.. ?? */
+# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */
+# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */
+# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */
+# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */
+ /* 0x16 - some 16 bit green format.. ?? */
# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */
# define R300_TX_FORMAT_CUBIC_MAP (1 << 26)
@@ -793,23 +888,26 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_FORMAT_W 3
# define R300_TX_FORMAT_ZERO 4
# define R300_TX_FORMAT_ONE 5
-# define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */
-# define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */
+ /* 2.0*Z, everything above 1.0 is set to 0.0 */
+# define R300_TX_FORMAT_CUT_Z 6
+ /* 2.0*W, everything above 1.0 is set to 0.0 */
+# define R300_TX_FORMAT_CUT_W 7
# define R300_TX_FORMAT_B_SHIFT 18
# define R300_TX_FORMAT_G_SHIFT 15
# define R300_TX_FORMAT_R_SHIFT 12
# define R300_TX_FORMAT_A_SHIFT 9
/* Convenience macro to take care of layout and swizzling */
-# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) (\
- ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
- | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
- | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
- | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
- | (R300_TX_FORMAT_##FMT) \
- )
- /* These can be ORed with result of R300_EASY_TX_FORMAT() */
- /* We don't really know what they do. Take values from a constant color ? */
+# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) ( \
+ ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
+ | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
+ | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
+ | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
+ | (R300_TX_FORMAT_##FMT) \
+ )
+ /* These can be ORed with result of R300_EASY_TX_FORMAT()
+ We don't really know what they do. Take values from a
+ constant color ? */
# define R300_TX_FORMAT_CONST_X (1<<5)
# define R300_TX_FORMAT_CONST_Y (2<<5)
# define R300_TX_FORMAT_CONST_Z (4<<5)
@@ -819,7 +917,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */
#define R300_TX_OFFSET_0 0x4540
-/* BEGIN: Guess from R200 */
+ /* BEGIN: Guess from R200 */
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0)
# define R300_TXO_ENDIAN_WORD_SWAP (2 << 0)
@@ -828,53 +926,61 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TXO_MICRO_TILE (1 << 3)
# define R300_TXO_OFFSET_MASK 0xffffffe0
# define R300_TXO_OFFSET_SHIFT 5
-/* END */
-#define R300_TX_CHROMA_KEY_0 0x4580 /* 32 bit chroma key */
-#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
-
-/* END */
-
-/* BEGIN: Fragment program instruction set
-// Fragment programs are written directly into register space.
-// There are separate instruction streams for texture instructions and ALU
-// instructions.
-// In order to synchronize these streams, the program is divided into up
-// to 4 nodes. Each node begins with a number of TEX operations, followed
-// by a number of ALU operations.
-// The first node can have zero TEX ops, all subsequent nodes must have at least
-// one TEX ops.
-// All nodes must have at least one ALU op.
-//
-// The index of the last node is stored in PFS_CNTL_0: A value of 0 means
-// 1 node, a value of 3 means 4 nodes.
-// The total amount of instructions is defined in PFS_CNTL_2. The offsets are
-// offsets into the respective instruction streams, while *_END points to the
-// last instruction relative to this offset. */
+ /* END: Guess from R200 */
+
+/* 32 bit chroma key */
+#define R300_TX_CHROMA_KEY_0 0x4580
+/* ff00ff00 == { 0, 1.0, 0, 1.0 } */
+#define R300_TX_BORDER_COLOR_0 0x45C0
+
+/* END: Texture specification */
+
+/* BEGIN: Fragment program instruction set */
+
+/* Fragment programs are written directly into register space.
+ * There are separate instruction streams for texture instructions and ALU
+ * instructions.
+ * In order to synchronize these streams, the program is divided into up
+ * to 4 nodes. Each node begins with a number of TEX operations, followed
+ * by a number of ALU operations.
+ * The first node can have zero TEX ops, all subsequent nodes must have at
+ * least
+ * one TEX ops.
+ * All nodes must have at least one ALU op.
+ *
+ * The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+ * 1 node, a value of 3 means 4 nodes.
+ * The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+ * offsets into the respective instruction streams, while *_END points to the
+ * last instruction relative to this offset.
+ */
#define R300_PFS_CNTL_0 0x4600
# define R300_PFS_CNTL_LAST_NODES_SHIFT 0
# define R300_PFS_CNTL_LAST_NODES_MASK (3 << 0)
# define R300_PFS_CNTL_FIRST_NODE_HAS_TEX (1 << 3)
#define R300_PFS_CNTL_1 0x4604
/* There is an unshifted value here which has so far always been equal to the
-// index of the highest used temporary register. */
+ * index of the highest used temporary register.
+ */
#define R300_PFS_CNTL_2 0x4608
# define R300_PFS_CNTL_ALU_OFFSET_SHIFT 0
# define R300_PFS_CNTL_ALU_OFFSET_MASK (63 << 0)
# define R300_PFS_CNTL_ALU_END_SHIFT 6
-# define R300_PFS_CNTL_ALU_END_MASK (63 << 0)
+# define R300_PFS_CNTL_ALU_END_MASK (63 << 6)
# define R300_PFS_CNTL_TEX_OFFSET_SHIFT 12
-# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */
+# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */
# define R300_PFS_CNTL_TEX_END_SHIFT 18
-# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */
+# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */
/* gap */
+
/* Nodes are stored backwards. The last active node is always stored in
-// PFS_NODE_3.
-// Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
-// first node is stored in NODE_2, the second node is stored in NODE_3.
-//
-// Offsets are relative to the master offset from PFS_CNTL_2.
-// LAST_NODE is set for the last node, and only for the last node. */
+ * PFS_NODE_3.
+ * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+ * first node is stored in NODE_2, the second node is stored in NODE_3.
+ *
+ * Offsets are relative to the master offset from PFS_CNTL_2.
+ */
#define R300_PFS_NODE_0 0x4610
#define R300_PFS_NODE_1 0x4614
#define R300_PFS_NODE_2 0x4618
@@ -887,91 +993,98 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12)
# define R300_PFS_NODE_TEX_END_SHIFT 17
# define R300_PFS_NODE_TEX_END_MASK (31 << 17)
-/*# define R300_PFS_NODE_LAST_NODE (1 << 22) */
# define R300_PFS_NODE_OUTPUT_COLOR (1 << 22)
# define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23)
/* TEX
-// As far as I can tell, texture instructions cannot write into output
-// registers directly. A subsequent ALU instruction is always necessary,
-// even if it's just MAD o0, r0, 1, 0 */
+ * As far as I can tell, texture instructions cannot write into output
+ * registers directly. A subsequent ALU instruction is always necessary,
+ * even if it's just MAD o0, r0, 1, 0
+ */
#define R300_PFS_TEXI_0 0x4620
-# define R300_FPITX_SRC_SHIFT 0
-# define R300_FPITX_SRC_MASK (31 << 0)
-# define R300_FPITX_SRC_CONST (1 << 5) /* GUESS */
-# define R300_FPITX_DST_SHIFT 6
-# define R300_FPITX_DST_MASK (31 << 6)
-# define R300_FPITX_IMAGE_SHIFT 11
-# define R300_FPITX_IMAGE_MASK (15 << 11) /* GUESS based on layout and native limits */
+# define R300_FPITX_SRC_SHIFT 0
+# define R300_FPITX_SRC_MASK (31 << 0)
+ /* GUESS */
+# define R300_FPITX_SRC_CONST (1 << 5)
+# define R300_FPITX_DST_SHIFT 6
+# define R300_FPITX_DST_MASK (31 << 6)
+# define R300_FPITX_IMAGE_SHIFT 11
+ /* GUESS based on layout and native limits */
+# define R300_FPITX_IMAGE_MASK (15 << 11)
/* Unsure if these are opcodes, or some kind of bitfield, but this is how
* they were set when I checked
*/
-# define R300_FPITX_OPCODE_SHIFT 15
-# define R300_FPITX_OP_TEX 1
-# define R300_FPITX_OP_KIL 2
-# define R300_FPITX_OP_TXP 3
-# define R300_FPITX_OP_TXB 4
+# define R300_FPITX_OPCODE_SHIFT 15
+# define R300_FPITX_OP_TEX 1
+# define R300_FPITX_OP_KIL 2
+# define R300_FPITX_OP_TXP 3
+# define R300_FPITX_OP_TXB 4
+# define R300_FPITX_OPCODE_MASK (7 << 15)
/* ALU
-// The ALU instructions register blocks are enumerated according to the order
-// in which fglrx. I assume there is space for 64 instructions, since
-// each block has space for a maximum of 64 DWORDs, and this matches reported
-// native limits.
-//
-// The basic functional block seems to be one MAD for each color and alpha,
-// and an adder that adds all components after the MUL.
-// - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
-// - DP4: Use OUTC_DP4, OUTA_DP4
-// - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
-// - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
-// - CMP: If ARG2 < 0, return ARG1, else return ARG0
-// - FLR: use FRC+MAD
-// - XPD: use MAD+MAD
-// - SGE, SLT: use MAD+CMP
-// - RSQ: use ABS modifier for argument
-// - Use OUTC_REPL_ALPHA to write results of an alpha-only operation (e.g. RCP)
-// into color register
-// - apparently, there's no quick DST operation
-// - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
-// - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
-// - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
-//
-// Operand selection
-// First stage selects three sources from the available registers and
-// constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
-// fglrx sorts the three source fields: Registers before constants,
-// lower indices before higher indices; I do not know whether this is necessary.
-// fglrx fills unused sources with "read constant 0"
-// According to specs, you cannot select more than two different constants.
-//
-// Second stage selects the operands from the sources. This is defined in
-// INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
-// zero and one.
-// Swizzling and negation happens in this stage, as well.
-//
-// Important: Color and alpha seem to be mostly separate, i.e. their sources
-// selection appears to be fully independent (the register storage is probably
-// physically split into a color and an alpha section).
-// However (because of the apparent physical split), there is some interaction
-// WRT swizzling. If, for example, you want to load an R component into an
-// Alpha operand, this R component is taken from a *color* source, not from
-// an alpha source. The corresponding register doesn't even have to appear in
-// the alpha sources list. (I hope this alll makes sense to you)
-//
-// Destination selection
-// The destination register index is in FPI1 (color) and FPI3 (alpha) together
-// with enable bits.
-// There are separate enable bits for writing into temporary registers
-// (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* /DSTA_OUTPUT).
-// You can write to both at once, or not write at all (the same index
-// must be used for both).
-//
-// Note: There is a special form for LRP
-// - Argument order is the same as in ARB_fragment_program.
-// - Operation is MAD
-// - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
-// - Set FPI0/FPI2_SPECIAL_LRP
-// Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD */
+ * The ALU instructions register blocks are enumerated according to the order
+ * in which fglrx. I assume there is space for 64 instructions, since
+ * each block has space for a maximum of 64 DWORDs, and this matches reported
+ * native limits.
+ *
+ * The basic functional block seems to be one MAD for each color and alpha,
+ * and an adder that adds all components after the MUL.
+ * - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+ * - DP4: Use OUTC_DP4, OUTA_DP4
+ * - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+ * - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+ * - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
+ * - CMP: If ARG2 < 0, return ARG1, else return ARG0
+ * - FLR: use FRC+MAD
+ * - XPD: use MAD+MAD
+ * - SGE, SLT: use MAD+CMP
+ * - RSQ: use ABS modifier for argument
+ * - Use OUTC_REPL_ALPHA to write results of an alpha-only operation
+ * (e.g. RCP) into color register
+ * - apparently, there's no quick DST operation
+ * - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+ * - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+ * - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+ *
+ * Operand selection
+ * First stage selects three sources from the available registers and
+ * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+ * fglrx sorts the three source fields: Registers before constants,
+ * lower indices before higher indices; I do not know whether this is
+ * necessary.
+ *
+ * fglrx fills unused sources with "read constant 0"
+ * According to specs, you cannot select more than two different constants.
+ *
+ * Second stage selects the operands from the sources. This is defined in
+ * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+ * zero and one.
+ * Swizzling and negation happens in this stage, as well.
+ *
+ * Important: Color and alpha seem to be mostly separate, i.e. their sources
+ * selection appears to be fully independent (the register storage is probably
+ * physically split into a color and an alpha section).
+ * However (because of the apparent physical split), there is some interaction
+ * WRT swizzling. If, for example, you want to load an R component into an
+ * Alpha operand, this R component is taken from a *color* source, not from
+ * an alpha source. The corresponding register doesn't even have to appear in
+ * the alpha sources list. (I hope this all makes sense to you)
+ *
+ * Destination selection
+ * The destination register index is in FPI1 (color) and FPI3 (alpha)
+ * together with enable bits.
+ * There are separate enable bits for writing into temporary registers
+ * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_*
+ * /DSTA_OUTPUT). You can write to both at once, or not write at all (the
+ * same index must be used for both).
+ *
+ * Note: There is a special form for LRP
+ * - Argument order is the same as in ARB_fragment_program.
+ * - Operation is MAD
+ * - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+ * - Set FPI0/FPI2_SPECIAL_LRP
+ * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD
+ */
#define R300_PFS_INSTR1_0 0x46C0
# define R300_FPI1_SRC0C_SHIFT 0
# define R300_FPI1_SRC0C_MASK (31 << 0)
@@ -982,6 +1095,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI1_SRC2C_SHIFT 12
# define R300_FPI1_SRC2C_MASK (31 << 12)
# define R300_FPI1_SRC2C_CONST (1 << 17)
+# define R300_FPI1_SRC_MASK 0x0003ffff
# define R300_FPI1_DSTC_SHIFT 18
# define R300_FPI1_DSTC_MASK (31 << 18)
# define R300_FPI1_DSTC_REG_MASK_SHIFT 23
@@ -1003,6 +1117,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI3_SRC2A_SHIFT 12
# define R300_FPI3_SRC2A_MASK (31 << 12)
# define R300_FPI3_SRC2A_CONST (1 << 17)
+# define R300_FPI3_SRC_MASK 0x0003ffff
# define R300_FPI3_DSTA_SHIFT 18
# define R300_FPI3_DSTA_MASK (31 << 18)
# define R300_FPI3_DSTA_REG (1 << 23)
@@ -1028,7 +1143,8 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI0_ARGC_SRC1C_LRP 15
# define R300_FPI0_ARGC_ZERO 20
# define R300_FPI0_ARGC_ONE 21
-# define R300_FPI0_ARGC_HALF 22 /* GUESS */
+ /* GUESS */
+# define R300_FPI0_ARGC_HALF 22
# define R300_FPI0_ARGC_SRC0C_YZX 23
# define R300_FPI0_ARGC_SRC1C_YZX 24
# define R300_FPI0_ARGC_SRC2C_YZX 25
@@ -1057,6 +1173,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI0_OUTC_DP4 (2 << 23)
# define R300_FPI0_OUTC_MIN (4 << 23)
# define R300_FPI0_OUTC_MAX (5 << 23)
+# define R300_FPI0_OUTC_CMPH (7 << 23)
# define R300_FPI0_OUTC_CMP (8 << 23)
# define R300_FPI0_OUTC_FRC (9 << 23)
# define R300_FPI0_OUTC_REPL_ALPHA (10 << 23)
@@ -1079,20 +1196,23 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI2_ARGA_SRC1A_LRP 15
# define R300_FPI2_ARGA_ZERO 16
# define R300_FPI2_ARGA_ONE 17
-# define R300_FPI2_ARGA_HALF 18 /* GUESS */
-
+ /* GUESS */
+# define R300_FPI2_ARGA_HALF 18
# define R300_FPI2_ARG0A_SHIFT 0
# define R300_FPI2_ARG0A_MASK (31 << 0)
# define R300_FPI2_ARG0A_NEG (1 << 5)
-# define R300_FPI2_ARG0A_ABS (1 << 6) /* GUESS */
+ /* GUESS */
+# define R300_FPI2_ARG0A_ABS (1 << 6)
# define R300_FPI2_ARG1A_SHIFT 7
# define R300_FPI2_ARG1A_MASK (31 << 7)
# define R300_FPI2_ARG1A_NEG (1 << 12)
-# define R300_FPI2_ARG1A_ABS (1 << 13) /* GUESS */
+ /* GUESS */
+# define R300_FPI2_ARG1A_ABS (1 << 13)
# define R300_FPI2_ARG2A_SHIFT 14
# define R300_FPI2_ARG2A_MASK (31 << 14)
# define R300_FPI2_ARG2A_NEG (1 << 19)
-# define R300_FPI2_ARG2A_ABS (1 << 20) /* GUESS */
+ /* GUESS */
+# define R300_FPI2_ARG2A_ABS (1 << 20)
# define R300_FPI2_SPECIAL_LRP (1 << 21)
# define R300_FPI2_OUTA_MAD (0 << 23)
# define R300_FPI2_OUTA_DP4 (1 << 23)
@@ -1106,9 +1226,19 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI2_OUTA_RSQ (11 << 23)
# define R300_FPI2_OUTA_SAT (1 << 30)
# define R300_FPI2_UNKNOWN_31 (1 << 31)
-/* END */
+/* END: Fragment program instruction set */
+
+/* Fog state and color */
+#define R300_RE_FOG_STATE 0x4BC0
+# define R300_FOG_ENABLE (1 << 0)
+# define R300_FOG_MODE_LINEAR (0 << 1)
+# define R300_FOG_MODE_EXP (1 << 1)
+# define R300_FOG_MODE_EXP2 (2 << 1)
+# define R300_FOG_MODE_MASK (3 << 1)
+#define R300_FOG_COLOR_R 0x4BC8
+#define R300_FOG_COLOR_G 0x4BCC
+#define R300_FOG_COLOR_B 0x4BD0
-/* gap */
#define R300_PP_ALPHA_TEST 0x4BD4
# define R300_REF_ALPHA_MASK 0x000000ff
# define R300_ALPHA_TEST_FAIL (0 << 8)
@@ -1123,6 +1253,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_ALPHA_TEST_ENABLE (1 << 11)
/* gap */
+
/* Fragment program parameters in 7.16 floating point */
#define R300_PFS_PARAM_0_X 0x4C00
#define R300_PFS_PARAM_0_Y 0x4C04
@@ -1135,45 +1266,48 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_PFS_PARAM_31_W 0x4DFC
/* Notes:
-// - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in the application
-// - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND are set to the same
-// function (both registers are always set up completely in any case)
-// - Most blend flags are simply copied from R200 and not tested yet */
+ * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in
+ * the application
+ * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND
+ * are set to the same
+ * function (both registers are always set up completely in any case)
+ * - Most blend flags are simply copied from R200 and not tested yet
+ */
#define R300_RB3D_CBLEND 0x4E04
#define R300_RB3D_ABLEND 0x4E08
- /* the following only appear in CBLEND */
+/* the following only appear in CBLEND */
# define R300_BLEND_ENABLE (1 << 0)
# define R300_BLEND_UNKNOWN (3 << 1)
# define R300_BLEND_NO_SEPARATE (1 << 3)
- /* the following are shared between CBLEND and ABLEND */
+/* the following are shared between CBLEND and ABLEND */
# define R300_FCN_MASK (3 << 12)
# define R300_COMB_FCN_ADD_CLAMP (0 << 12)
# define R300_COMB_FCN_ADD_NOCLAMP (1 << 12)
# define R300_COMB_FCN_SUB_CLAMP (2 << 12)
# define R300_COMB_FCN_SUB_NOCLAMP (3 << 12)
-# define R300_SRC_BLEND_GL_ZERO (32 << 16)
-# define R300_SRC_BLEND_GL_ONE (33 << 16)
-# define R300_SRC_BLEND_GL_SRC_COLOR (34 << 16)
-# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
-# define R300_SRC_BLEND_GL_DST_COLOR (36 << 16)
-# define R300_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
-# define R300_SRC_BLEND_GL_SRC_ALPHA (38 << 16)
-# define R300_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
-# define R300_SRC_BLEND_GL_DST_ALPHA (40 << 16)
-# define R300_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
-# define R300_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16)
-# define R300_SRC_BLEND_MASK (63 << 16)
-# define R300_DST_BLEND_GL_ZERO (32 << 24)
-# define R300_DST_BLEND_GL_ONE (33 << 24)
-# define R300_DST_BLEND_GL_SRC_COLOR (34 << 24)
-# define R300_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
-# define R300_DST_BLEND_GL_DST_COLOR (36 << 24)
-# define R300_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
-# define R300_DST_BLEND_GL_SRC_ALPHA (38 << 24)
-# define R300_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
-# define R300_DST_BLEND_GL_DST_ALPHA (40 << 24)
-# define R300_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
-# define R300_DST_BLEND_MASK (63 << 24)
+# define R300_COMB_FCN_MIN (4 << 12)
+# define R300_COMB_FCN_MAX (5 << 12)
+# define R300_COMB_FCN_RSUB_CLAMP (6 << 12)
+# define R300_COMB_FCN_RSUB_NOCLAMP (7 << 12)
+# define R300_BLEND_GL_ZERO (32)
+# define R300_BLEND_GL_ONE (33)
+# define R300_BLEND_GL_SRC_COLOR (34)
+# define R300_BLEND_GL_ONE_MINUS_SRC_COLOR (35)
+# define R300_BLEND_GL_DST_COLOR (36)
+# define R300_BLEND_GL_ONE_MINUS_DST_COLOR (37)
+# define R300_BLEND_GL_SRC_ALPHA (38)
+# define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA (39)
+# define R300_BLEND_GL_DST_ALPHA (40)
+# define R300_BLEND_GL_ONE_MINUS_DST_ALPHA (41)
+# define R300_BLEND_GL_SRC_ALPHA_SATURATE (42)
+# define R300_BLEND_GL_CONST_COLOR (43)
+# define R300_BLEND_GL_ONE_MINUS_CONST_COLOR (44)
+# define R300_BLEND_GL_CONST_ALPHA (45)
+# define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA (46)
+# define R300_BLEND_MASK (63)
+# define R300_SRC_BLEND_SHIFT (16)
+# define R300_DST_BLEND_SHIFT (24)
+#define R300_RB3D_BLEND_COLOR 0x4E10
#define R300_RB3D_COLORMASK 0x4E0C
# define R300_COLORMASK0_B (1<<0)
# define R300_COLORMASK0_G (1<<1)
@@ -1181,41 +1315,49 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_COLORMASK0_A (1<<3)
/* gap */
+
#define R300_RB3D_COLOROFFSET0 0x4E28
-# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */
-#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */
-#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */
-#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */
+# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */
+#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */
+#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */
+#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */
+
/* gap */
+
/* Bit 16: Larger tiles
-// Bit 17: 4x2 tiles
-// Bit 18: Extremely weird tile like, but some pixels duplicated? */
+ * Bit 17: 4x2 tiles
+ * Bit 18: Extremely weird tile like, but some pixels duplicated?
+ */
#define R300_RB3D_COLORPITCH0 0x4E38
-# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
-# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
-# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
-# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
-# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
-# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
+# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
+# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
+# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
# define R300_COLOR_FORMAT_RGB565 (2 << 22)
# define R300_COLOR_FORMAT_ARGB8888 (3 << 22)
-#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */
-#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
-#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
+#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */
+#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
+#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
/* gap */
+
/* Guess by Vladimir.
-// Set to 0A before 3D operations, set to 02 afterwards. */
+ * Set to 0A before 3D operations, set to 02 afterwards.
+ */
#define R300_RB3D_DSTCACHE_CTLSTAT 0x4E4C
-# define R300_RB3D_DSTCACHE_02 0x00000002
-# define R300_RB3D_DSTCACHE_0A 0x0000000A
+# define R300_RB3D_DSTCACHE_UNKNOWN_02 0x00000002
+# define R300_RB3D_DSTCACHE_UNKNOWN_0A 0x0000000A
/* gap */
-/* There seems to be no "write only" setting, so use Z-test = ALWAYS for this. */
-/* Bit (1<<8) is the "test" bit. so plain write is 6 - vd */
+/* There seems to be no "write only" setting, so use Z-test = ALWAYS
+ * for this.
+ * Bit (1<<8) is the "test" bit. so plain write is 6 - vd
+ */
#define R300_RB3D_ZSTENCIL_CNTL_0 0x4F00
-# define R300_RB3D_Z_DISABLED_1 0x00000010 /* GUESS */
-# define R300_RB3D_Z_DISABLED_2 0x00000014 /* GUESS */
+# define R300_RB3D_Z_DISABLED_1 0x00000010
+# define R300_RB3D_Z_DISABLED_2 0x00000014
# define R300_RB3D_Z_TEST 0x00000012
# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
# define R300_RB3D_Z_WRITE_ONLY 0x00000006
@@ -1226,7 +1368,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_RB3D_STENCIL_ENABLE 0x00000001
#define R300_RB3D_ZSTENCIL_CNTL_1 0x4F04
- /* functions */
+ /* functions */
# define R300_ZS_NEVER 0
# define R300_ZS_LESS 1
# define R300_ZS_LEQUAL 2
@@ -1236,7 +1378,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_ZS_NOTEQUAL 6
# define R300_ZS_ALWAYS 7
# define R300_ZS_MASK 7
- /* operations */
+ /* operations */
# define R300_ZS_KEEP 0
# define R300_ZS_ZERO 1
# define R300_ZS_REPLACE 2
@@ -1245,9 +1387,8 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_ZS_INVERT 5
# define R300_ZS_INCR_WRAP 6
# define R300_ZS_DECR_WRAP 7
-
- /* front and back refer to operations done for front
- and back faces, i.e. separate stencil function support */
+ /* front and back refer to operations done for front
+ and back faces, i.e. separate stencil function support */
# define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT 0
# define R300_RB3D_ZS1_FRONT_FUNC_SHIFT 3
# define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT 6
@@ -1269,45 +1410,64 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_RB3D_ZSTENCIL_FORMAT 0x4F10
# define R300_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
# define R300_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+ /* 16 bit format or some aditional bit ? */
+# define R300_DEPTH_FORMAT_UNK32 (32 << 0)
+
+#define R300_RB3D_EARLY_Z 0x4F14
+# define R300_EARLY_Z_DISABLE (0 << 0)
+# define R300_EARLY_Z_ENABLE (1 << 0)
+
+/* gap */
+
+#define R300_RB3D_ZCACHE_CTLSTAT 0x4F18 /* GUESS */
+# define R300_RB3D_ZCACHE_UNKNOWN_01 0x1
+# define R300_RB3D_ZCACHE_UNKNOWN_03 0x3
/* gap */
+
#define R300_RB3D_DEPTHOFFSET 0x4F20
#define R300_RB3D_DEPTHPITCH 0x4F24
-# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
-# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
-# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
-# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
-# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
-# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
-
-/* BEGIN: Vertex program instruction set
-// Every instruction is four dwords long:
-// DWORD 0: output and opcode
-// DWORD 1: first argument
-// DWORD 2: second argument
-// DWORD 3: third argument
-//
-// Notes:
-// - ABS r, a is implemented as MAX r, a, -a
-// - MOV is implemented as ADD to zero
-// - XPD is implemented as MUL + MAD
-// - FLR is implemented as FRC + ADD
-// - apparently, fglrx tries to schedule instructions so that there is at least
-// one instruction between the write to a temporary and the first read
-// from said temporary; however, violations of this scheduling are allowed
-// - register indices seem to be unrelated with OpenGL aliasing to conventional state
-// - only one attribute and one parameter can be loaded at a time; however, the
-// same attribute/parameter can be used for more than one argument
-// - the second software argument for POW is the third hardware argument (no idea why)
-// - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
-//
-// There is some magic surrounding LIT:
-// The single argument is replicated across all three inputs, but swizzled:
-// First argument: xyzy
-// Second argument: xyzx
-// Third argument: xyzw
-// Whenever the result is used later in the fragment program, fglrx forces x and w
-// to be 1.0 in the input selection; I don't know whether this is strictly necessary */
+# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
+# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
+# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
+# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+
+/* BEGIN: Vertex program instruction set */
+
+/* Every instruction is four dwords long:
+ * DWORD 0: output and opcode
+ * DWORD 1: first argument
+ * DWORD 2: second argument
+ * DWORD 3: third argument
+ *
+ * Notes:
+ * - ABS r, a is implemented as MAX r, a, -a
+ * - MOV is implemented as ADD to zero
+ * - XPD is implemented as MUL + MAD
+ * - FLR is implemented as FRC + ADD
+ * - apparently, fglrx tries to schedule instructions so that there is at
+ * least one instruction between the write to a temporary and the first
+ * read from said temporary; however, violations of this scheduling are
+ * allowed
+ * - register indices seem to be unrelated with OpenGL aliasing to
+ * conventional state
+ * - only one attribute and one parameter can be loaded at a time; however,
+ * the same attribute/parameter can be used for more than one argument
+ * - the second software argument for POW is the third hardware argument
+ * (no idea why)
+ * - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
+ *
+ * There is some magic surrounding LIT:
+ * The single argument is replicated across all three inputs, but swizzled:
+ * First argument: xyzy
+ * Second argument: xyzx
+ * Third argument: xyzw
+ * Whenever the result is used later in the fragment program, fglrx forces
+ * x and w to be 1.0 in the input selection; I don't know whether this is
+ * strictly necessary
+ */
#define R300_VPI_OUT_OP_DOT (1 << 0)
#define R300_VPI_OUT_OP_MUL (2 << 0)
#define R300_VPI_OUT_OP_ADD (3 << 0)
@@ -1318,26 +1478,33 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_VPI_OUT_OP_MIN (8 << 0)
#define R300_VPI_OUT_OP_SGE (9 << 0)
#define R300_VPI_OUT_OP_SLT (10 << 0)
-#define R300_VPI_OUT_OP_UNK12 (12 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+ /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+#define R300_VPI_OUT_OP_UNK12 (12 << 0)
+#define R300_VPI_OUT_OP_ARL (13 << 0)
#define R300_VPI_OUT_OP_EXP (65 << 0)
#define R300_VPI_OUT_OP_LOG (66 << 0)
-#define R300_VPI_OUT_OP_UNK67 (67 << 0) /* Used in fog computations, scalar(scalar) */
+ /* Used in fog computations, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK67 (67 << 0)
#define R300_VPI_OUT_OP_LIT (68 << 0)
#define R300_VPI_OUT_OP_POW (69 << 0)
#define R300_VPI_OUT_OP_RCP (70 << 0)
#define R300_VPI_OUT_OP_RSQ (72 << 0)
-#define R300_VPI_OUT_OP_UNK73 (73 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+ /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK73 (73 << 0)
#define R300_VPI_OUT_OP_EX2 (75 << 0)
#define R300_VPI_OUT_OP_LG2 (76 << 0)
#define R300_VPI_OUT_OP_MAD_2 (128 << 0)
-#define R300_VPI_OUT_OP_UNK129 (129 << 0) /* all temps, vector(scalar, vector, vector) */
+ /* all temps, vector(scalar, vector, vector) */
+#define R300_VPI_OUT_OP_UNK129 (129 << 0)
#define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8)
+#define R300_VPI_OUT_REG_CLASS_ADDR (1 << 8)
#define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8)
#define R300_VPI_OUT_REG_CLASS_MASK (31 << 8)
#define R300_VPI_OUT_REG_INDEX_SHIFT 13
-#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */
+ /* GUESS based on fglrx native limits */
+#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13)
#define R300_VPI_OUT_WRITE_X (1 << 20)
#define R300_VPI_OUT_WRITE_Y (1 << 21)
@@ -1348,14 +1515,16 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0)
#define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0)
#define R300_VPI_IN_REG_CLASS_NONE (9 << 0)
-#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */
+#define R300_VPI_IN_REG_CLASS_MASK (31 << 0)
#define R300_VPI_IN_REG_INDEX_SHIFT 5
-#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */
+ /* GUESS based on fglrx native limits */
+#define R300_VPI_IN_REG_INDEX_MASK (255 << 5)
/* The R300 can select components from the input register arbitrarily.
-// Use the following constants, shifted by the component shift you
-// want to select */
+ * Use the following constants, shifted by the component shift you
+ * want to select
+ */
#define R300_VPI_IN_SELECT_X 0
#define R300_VPI_IN_SELECT_Y 1
#define R300_VPI_IN_SELECT_Z 2
@@ -1373,11 +1542,11 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_VPI_IN_NEG_Y (1 << 26)
#define R300_VPI_IN_NEG_Z (1 << 27)
#define R300_VPI_IN_NEG_W (1 << 28)
-/* END */
+/* END: Vertex program instruction set */
-//BEGIN: Packet 3 commands
+/* BEGIN: Packet 3 commands */
-// A primitive emission dword.
+/* A primitive emission dword. */
#define R300_PRIM_TYPE_NONE (0 << 0)
#define R300_PRIM_TYPE_POINT (1 << 0)
#define R300_PRIM_TYPE_LINE (2 << 0)
@@ -1389,7 +1558,8 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_PRIM_TYPE_RECT_LIST (8 << 0)
#define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
#define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
-#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) // GUESS (based on r200)
+ /* GUESS (based on r200) */
+#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0)
#define R300_PRIM_TYPE_LINE_LOOP (12 << 0)
#define R300_PRIM_TYPE_QUADS (13 << 0)
#define R300_PRIM_TYPE_QUAD_STRIP (14 << 0)
@@ -1399,37 +1569,58 @@ I am fairly certain that they are correct unless stated otherwise in comments.
#define R300_PRIM_WALK_LIST (2 << 4)
#define R300_PRIM_WALK_RING (3 << 4)
#define R300_PRIM_WALK_MASK (3 << 4)
-#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) // GUESS (based on r200)
-#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) // GUESS
+ /* GUESS (based on r200) */
+#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6)
+#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6)
#define R300_PRIM_NUM_VERTICES_SHIFT 16
+#define R300_PRIM_NUM_VERTICES_MASK 0xffff
-// Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
-// Two parameter dwords:
-// 0. The first parameter appears to be always 0
-// 1. The second parameter is a standard primitive emission dword.
+/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+ * Two parameter dwords:
+ * 0. The first parameter appears to be always 0
+ * 1. The second parameter is a standard primitive emission dword.
+ */
#define R300_PACKET3_3D_DRAW_VBUF 0x00002800
-// Specify the full set of vertex arrays as (address, stride).
-// The first parameter is the number of vertex arrays specified.
-// The rest of the command is a variable length list of blocks, where
-// each block is three dwords long and specifies two arrays.
-// The first dword of a block is split into two words, the lower significant
-// word refers to the first array, the more significant word to the second
-// array in the block.
-// The low byte of each word contains the size of an array entry in dwords,
-// the high byte contains the stride of the array.
-// The second dword of a block contains the pointer to the first array,
-// the third dword of a block contains the pointer to the second array.
-// Note that if the total number of arrays is odd, the third dword of
-// the last block is omitted.
+/* Specify the full set of vertex arrays as (address, stride).
+ * The first parameter is the number of vertex arrays specified.
+ * The rest of the command is a variable length list of blocks, where
+ * each block is three dwords long and specifies two arrays.
+ * The first dword of a block is split into two words, the lower significant
+ * word refers to the first array, the more significant word to the second
+ * array in the block.
+ * The low byte of each word contains the size of an array entry in dwords,
+ * the high byte contains the stride of the array.
+ * The second dword of a block contains the pointer to the first array,
+ * the third dword of a block contains the pointer to the second array.
+ * Note that if the total number of arrays is odd, the third dword of
+ * the last block is omitted.
+ */
#define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00
#define R300_PACKET3_INDX_BUFFER 0x00003300
# define R300_EB_UNK1_SHIFT 24
# define R300_EB_UNK1 (0x80<<24)
# define R300_EB_UNK2 0x0810
+#define R300_PACKET3_3D_DRAW_VBUF_2 0x00003400
#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600
-//END
+/* END: Packet 3 commands */
+
+
+/* Color formats for 2d packets
+ */
+#define R300_CP_COLOR_FORMAT_CI8 2
+#define R300_CP_COLOR_FORMAT_ARGB1555 3
+#define R300_CP_COLOR_FORMAT_RGB565 4
+#define R300_CP_COLOR_FORMAT_ARGB8888 6
+#define R300_CP_COLOR_FORMAT_RGB332 7
+#define R300_CP_COLOR_FORMAT_RGB8 9
+#define R300_CP_COLOR_FORMAT_ARGB4444 15
+
+/*
+ * CP type-3 packets
+ */
+#define R300_CP_CMD_BITBLT_MULTI 0xC0009B00
-#endif /* _R300_REG_H */
+#endif /* _R300_REG_H */
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 68338389d836..af5790f8fd53 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -36,7 +36,7 @@
#define RADEON_FIFO_DEBUG 0
-static int radeon_do_cleanup_cp(drm_device_t * dev);
+static int radeon_do_cleanup_cp(struct drm_device * dev);
/* CP microcode (from ATI) */
static const u32 R200_cp_microcode[][2] = {
@@ -816,7 +816,7 @@ static const u32 R300_cp_microcode[][2] = {
{0000000000, 0000000000},
};
-static int RADEON_READ_PLL(drm_device_t * dev, int addr)
+static int RADEON_READ_PLL(struct drm_device * dev, int addr)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1066,7 +1066,7 @@ static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
/* Reset the engine. This will stop the CP if it is running.
*/
-static int radeon_do_engine_reset(drm_device_t * dev)
+static int radeon_do_engine_reset(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
@@ -1122,7 +1122,7 @@ static int radeon_do_engine_reset(drm_device_t * dev)
return 0;
}
-static void radeon_cp_init_ring_buffer(drm_device_t * dev,
+static void radeon_cp_init_ring_buffer(struct drm_device * dev,
drm_radeon_private_t * dev_priv)
{
u32 ring_start, cur_read_ptr;
@@ -1174,7 +1174,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
} else
#endif
{
- drm_sg_mem_t *entry = dev->sg;
+ struct drm_sg_mem *entry = dev->sg;
unsigned long tmp_ofs, page_ofs;
tmp_ofs = dev_priv->ring_rptr->offset -
@@ -1384,7 +1384,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
}
}
-static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1420,6 +1420,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
return DRM_ERR(EINVAL);
}
+ /* Enable vblank on CRTC1 for older X servers
+ */
+ dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
+
switch(init->func) {
case RADEON_INIT_R200_CP:
dev_priv->microcode_version = UCODE_R200;
@@ -1501,13 +1505,13 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
RADEON_ROUND_MODE_TRUNC |
RADEON_ROUND_PREC_8TH_PIX);
- DRM_GETSAREA();
dev_priv->ring_offset = init->ring_offset;
dev_priv->ring_rptr_offset = init->ring_rptr_offset;
dev_priv->buffers_offset = init->buffers_offset;
dev_priv->gart_textures_offset = init->gart_textures_offset;
+ dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
radeon_do_cleanup_cp(dev);
@@ -1731,7 +1735,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
return 0;
}
-static int radeon_do_cleanup_cp(drm_device_t * dev)
+static int radeon_do_cleanup_cp(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n");
@@ -1787,7 +1791,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
*
* Charl P. Botha <http://cpbotha.net>
*/
-static int radeon_do_resume_cp(drm_device_t * dev)
+static int radeon_do_resume_cp(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1914,7 +1918,7 @@ int radeon_cp_stop(DRM_IOCTL_ARGS)
return 0;
}
-void radeon_do_release(drm_device_t * dev)
+void radeon_do_release(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int i, ret;
@@ -2042,12 +2046,12 @@ int radeon_fullscreen(DRM_IOCTL_ARGS)
* they can't get the lock.
*/
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv;
- drm_buf_t *buf;
+ struct drm_buf *buf;
int i, t;
int start;
@@ -2082,12 +2086,12 @@ drm_buf_t *radeon_freelist_get(drm_device_t * dev)
}
#if 0
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv;
- drm_buf_t *buf;
+ struct drm_buf *buf;
int i, t;
int start;
u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
@@ -2116,15 +2120,15 @@ drm_buf_t *radeon_freelist_get(drm_device_t * dev)
}
#endif
-void radeon_freelist_reset(drm_device_t * dev)
+void radeon_freelist_reset(struct drm_device * dev)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_radeon_private_t *dev_priv = dev->dev_private;
int i;
dev_priv->last_buf = 0;
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
buf_priv->age = 0;
}
@@ -2166,11 +2170,11 @@ int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
return DRM_ERR(EBUSY);
}
-static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
- drm_dma_t * d)
+static int radeon_cp_get_buffers(DRMFILE filp, struct drm_device * dev,
+ struct drm_dma * d)
{
int i;
- drm_buf_t *buf;
+ struct drm_buf *buf;
for (i = d->granted_count; i < d->request_count; i++) {
buf = radeon_freelist_get(dev);
@@ -2194,10 +2198,10 @@ static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
int radeon_cp_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int ret = 0;
- drm_dma_t __user *argp = (void __user *)data;
- drm_dma_t d;
+ struct drm_dma __user *argp = (void __user *)data;
+ struct drm_dma d;
LOCK_TEST_WITH_RETURN(dev, filp);
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 66c4b6fed04f..5a8e23f916fc 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -417,7 +417,7 @@ typedef struct {
/* The current cliprects, or a subset thereof.
*/
- drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS];
unsigned int nbox;
/* Counters for client-side throttling of rendering clients.
@@ -426,7 +426,7 @@ typedef struct {
unsigned int last_dispatch;
unsigned int last_clear;
- drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
+ struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
1];
unsigned int tex_age[RADEON_NR_TEX_HEAPS];
int ctx_owner;
@@ -604,7 +604,7 @@ typedef struct drm_radeon_cmd_buffer {
int bufsz;
char __user *buf;
int nbox;
- drm_clip_rect_t __user *boxes;
+ struct drm_clip_rect __user *boxes;
} drm_radeon_cmd_buffer_t;
typedef struct drm_radeon_tex_image {
@@ -655,6 +655,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_GART_TEX_HANDLE 10
#define RADEON_PARAM_SCRATCH_OFFSET 11
#define RADEON_PARAM_CARD_TYPE 12
+#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */
typedef struct drm_radeon_getparam {
int param;
@@ -708,7 +709,7 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */
-
+#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */
/* 1.14: Clients can allocate/free a surface
*/
typedef struct drm_radeon_surface_alloc {
@@ -721,4 +722,7 @@ typedef struct drm_radeon_surface_free {
unsigned int address;
} drm_radeon_surface_free_t;
+#define DRM_RADEON_VBLANK_CRTC1 1
+#define DRM_RADEON_VBLANK_CRTC2 2
+
#endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 2eb652ec6745..349ac3d3b848 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -60,7 +60,7 @@ static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
- DRIVER_IRQ_VBL,
+ DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.load = radeon_driver_load,
.firstopen = radeon_driver_firstopen,
@@ -70,6 +70,7 @@ static struct drm_driver driver = {
.lastclose = radeon_driver_lastclose,
.unload = radeon_driver_unload,
.vblank_wait = radeon_driver_vblank_wait,
+ .vblank_wait2 = radeon_driver_vblank_wait2,
.dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 54f49ef4bef0..3b3d9357201c 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -97,9 +97,10 @@
* new packet type)
* 1.26- Add support for variable size PCI(E) gart aperture
* 1.27- Add support for IGP GART
+ * 1.28- Add support for VBL on CRTC2
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 27
+#define DRIVER_MINOR 28
#define DRIVER_PATCHLEVEL 0
/*
@@ -154,7 +155,7 @@ enum radeon_chip_flags {
typedef struct drm_radeon_freelist {
unsigned int age;
- drm_buf_t *buf;
+ struct drm_buf *buf;
struct drm_radeon_freelist *next;
struct drm_radeon_freelist *prev;
} drm_radeon_freelist_t;
@@ -277,13 +278,16 @@ typedef struct drm_radeon_private {
/* SW interrupt */
wait_queue_head_t swi_queue;
atomic_t swi_emitted;
+ int vblank_crtc;
+ uint32_t irq_enable_reg;
+ int irq_enabled;
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
unsigned long pcigart_offset;
unsigned int pcigart_offset_set;
- drm_ati_pcigart_info gart_info;
+ struct drm_ati_pcigart_info gart_info;
u32 scratch_ages[5];
@@ -299,7 +303,7 @@ typedef struct drm_radeon_kcmd_buffer {
int bufsz;
char *buf;
int nbox;
- drm_clip_rect_t __user *boxes;
+ struct drm_clip_rect __user *boxes;
} drm_radeon_kcmd_buffer_t;
extern int radeon_no_wb;
@@ -332,8 +336,8 @@ extern int radeon_engine_reset(DRM_IOCTL_ARGS);
extern int radeon_fullscreen(DRM_IOCTL_ARGS);
extern int radeon_cp_buffers(DRM_IOCTL_ARGS);
-extern void radeon_freelist_reset(drm_device_t * dev);
-extern drm_buf_t *radeon_freelist_get(drm_device_t * dev);
+extern void radeon_freelist_reset(struct drm_device * dev);
+extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
@@ -353,29 +357,33 @@ extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap);
extern int radeon_irq_emit(DRM_IOCTL_ARGS);
extern int radeon_irq_wait(DRM_IOCTL_ARGS);
-extern void radeon_do_release(drm_device_t * dev);
-extern int radeon_driver_vblank_wait(drm_device_t * dev,
+extern void radeon_do_release(struct drm_device * dev);
+extern int radeon_driver_vblank_wait(struct drm_device * dev,
unsigned int *sequence);
+extern int radeon_driver_vblank_wait2(struct drm_device * dev,
+ unsigned int *sequence);
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
-extern void radeon_driver_irq_preinstall(drm_device_t * dev);
-extern void radeon_driver_irq_postinstall(drm_device_t * dev);
-extern void radeon_driver_irq_uninstall(drm_device_t * dev);
+extern void radeon_driver_irq_preinstall(struct drm_device * dev);
+extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+extern int radeon_vblank_crtc_get(struct drm_device *dev);
+extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
extern int radeon_driver_unload(struct drm_device *dev);
extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
-extern void radeon_driver_lastclose(drm_device_t * dev);
-extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
+extern void radeon_driver_preclose(struct drm_device * dev, DRMFILE filp);
+extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
+extern void radeon_driver_lastclose(struct drm_device * dev);
+extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
/* r300_cmdbuf.c */
extern void r300_init_reg_flags(void);
-extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
- drm_file_t * filp_priv,
+extern int r300_do_cp_cmdbuf(struct drm_device * dev, DRMFILE filp,
+ struct drm_file * filp_priv,
drm_radeon_kcmd_buffer_t * cmdbuf);
/* Flags for stats.boxes
@@ -496,12 +504,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
+# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
# define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_CRTC_VBLANK_STAT (1 << 0)
# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
+# define RADEON_CRTC2_VBLANK_STAT (1 << 9)
+# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9)
# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
# define RADEON_SW_INT_TEST (1 << 25)
# define RADEON_SW_INT_TEST_ACK (1 << 25)
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 3ff0baa2fbfa..ad8a0ac7182e 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -64,7 +64,7 @@ static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *) arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
u32 stat;
@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
* outside the DRM
*/
stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT));
+ RADEON_CRTC_VBLANK_STAT |
+ RADEON_CRTC2_VBLANK_STAT));
if (!stat)
return IRQ_NONE;
+ stat &= dev_priv->irq_enable_reg;
+
/* SW interrupt */
if (stat & RADEON_SW_INT_TEST) {
DRM_WAKEUP(&dev_priv->swi_queue);
}
/* VBLANK interrupt */
- if (stat & RADEON_CRTC_VBLANK_STAT) {
- atomic_inc(&dev->vbl_received);
+ if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+ int vblank_crtc = dev_priv->vblank_crtc;
+
+ if ((vblank_crtc &
+ (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+ (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+ if (stat & RADEON_CRTC_VBLANK_STAT)
+ atomic_inc(&dev->vbl_received);
+ if (stat & RADEON_CRTC2_VBLANK_STAT)
+ atomic_inc(&dev->vbl_received2);
+ } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+ (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+ ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+ (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+ atomic_inc(&dev->vbl_received);
+
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
}
@@ -92,7 +109,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_HANDLED;
}
-static int radeon_emit_irq(drm_device_t * dev)
+static int radeon_emit_irq(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int ret;
@@ -110,7 +127,7 @@ static int radeon_emit_irq(drm_device_t * dev)
return ret;
}
-static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
+static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
return ret;
}
-int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence,
+ int crtc)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
unsigned int cur_vblank;
int ret = 0;
-
+ int ack = 0;
+ atomic_t *counter;
if (!dev_priv) {
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
+ if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+ counter = &dev->vbl_received;
+ ack |= RADEON_CRTC_VBLANK_STAT;
+ } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+ counter = &dev->vbl_received2;
+ ack |= RADEON_CRTC2_VBLANK_STAT;
+ } else
+ return DRM_ERR(EINVAL);
+
+ radeon_acknowledge_irqs(dev_priv, ack);
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
* using vertical blanks...
*/
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
+ (((cur_vblank = atomic_read(counter))
- *sequence) <= (1 << 23)));
*sequence = cur_vblank;
@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
+int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+{
+ return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+}
+
+int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+{
+ return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+}
+
/* Needs the lock as it touches the ring.
*/
int radeon_irq_emit(DRM_IOCTL_ARGS)
@@ -204,9 +242,24 @@ int radeon_irq_wait(DRM_IOCTL_ARGS)
return radeon_wait_irq(dev, irqwait.irq_seq);
}
+static void radeon_enable_interrupt(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+
+ dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+ if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+ dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+
+ if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+ dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+ dev_priv->irq_enabled = 1;
+}
+
/* drm_dma.h hooks
*/
-void radeon_driver_irq_preinstall(drm_device_t * dev)
+void radeon_driver_irq_preinstall(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
@@ -216,10 +269,11 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)
/* Clear bits if they're already high */
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT));
+ RADEON_CRTC_VBLANK_STAT |
+ RADEON_CRTC2_VBLANK_STAT));
}
-void radeon_driver_irq_postinstall(drm_device_t * dev)
+void radeon_driver_irq_postinstall(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
@@ -227,18 +281,48 @@ void radeon_driver_irq_postinstall(drm_device_t * dev)
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
- /* Turn on SW and VBL ints */
- RADEON_WRITE(RADEON_GEN_INT_CNTL,
- RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
+ radeon_enable_interrupt(dev);
}
-void radeon_driver_irq_uninstall(drm_device_t * dev)
+void radeon_driver_irq_uninstall(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
if (!dev_priv)
return;
+ dev_priv->irq_enabled = 0;
+
/* Disable *all* interrupts */
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
}
+
+
+int radeon_vblank_crtc_get(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+ u32 flag;
+ u32 value;
+
+ flag = RADEON_READ(RADEON_GEN_INT_CNTL);
+ value = 0;
+
+ if (flag & RADEON_CRTC_VBLANK_MASK)
+ value |= DRM_RADEON_VBLANK_CRTC1;
+
+ if (flag & RADEON_CRTC2_VBLANK_MASK)
+ value |= DRM_RADEON_VBLANK_CRTC2;
+ return value;
+}
+
+int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+ if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+ DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->vblank_crtc = (unsigned int)value;
+ radeon_enable_interrupt(dev);
+ return 0;
+}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 98c5f1d3a8e7..3ddf86f2abf0 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -39,7 +39,7 @@
static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
u32 *offset)
{
u64 off = *offset;
@@ -90,7 +90,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
int id, u32 *data)
{
switch (id) {
@@ -264,7 +264,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
dev_priv,
- drm_file_t *filp_priv,
+ struct drm_file *filp_priv,
drm_radeon_kcmd_buffer_t *
cmdbuf,
unsigned int *cmdsz)
@@ -421,7 +421,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
*/
static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
- drm_clip_rect_t * box)
+ struct drm_clip_rect * box)
{
RING_LOCALS;
@@ -439,7 +439,7 @@ static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
/* Emit 1.1 state
*/
static int radeon_emit_state(drm_radeon_private_t * dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
drm_radeon_context_regs_t * ctx,
drm_radeon_texture_regs_t * tex,
unsigned int dirty)
@@ -608,7 +608,7 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv,
/* Emit 1.2 state
*/
static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
drm_radeon_state_t * state)
{
RING_LOCALS;
@@ -844,7 +844,7 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
* CP command dispatch functions
*/
-static void radeon_cp_dispatch_clear(drm_device_t * dev,
+static void radeon_cp_dispatch_clear(struct drm_device * dev,
drm_radeon_clear_t * clear,
drm_radeon_clear_rect_t * depth_boxes)
{
@@ -852,7 +852,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
unsigned int flags = clear->flags;
u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
int i;
@@ -1335,12 +1335,12 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
ADVANCE_RING();
}
-static void radeon_cp_dispatch_swap(drm_device_t * dev)
+static void radeon_cp_dispatch_swap(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
int nbox = sarea_priv->nbox;
- drm_clip_rect_t *pbox = sarea_priv->boxes;
+ struct drm_clip_rect *pbox = sarea_priv->boxes;
int i;
RING_LOCALS;
DRM_DEBUG("\n");
@@ -1412,10 +1412,10 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
ADVANCE_RING();
}
-static void radeon_cp_dispatch_flip(drm_device_t * dev)
+static void radeon_cp_dispatch_flip(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
+ struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
? dev_priv->front_offset : dev_priv->back_offset;
RING_LOCALS;
@@ -1491,8 +1491,8 @@ typedef struct {
unsigned int vc_format;
} drm_radeon_tcl_prim_t;
-static void radeon_cp_dispatch_vertex(drm_device_t * dev,
- drm_buf_t * buf,
+static void radeon_cp_dispatch_vertex(struct drm_device * dev,
+ struct drm_buf * buf,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1537,7 +1537,7 @@ static void radeon_cp_dispatch_vertex(drm_device_t * dev,
} while (i < nbox);
}
-static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -1554,8 +1554,8 @@ static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
buf->used = 0;
}
-static void radeon_cp_dispatch_indirect(drm_device_t * dev,
- drm_buf_t * buf, int start, int end)
+static void radeon_cp_dispatch_indirect(struct drm_device * dev,
+ struct drm_buf * buf, int start, int end)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -1588,8 +1588,8 @@ static void radeon_cp_dispatch_indirect(drm_device_t * dev,
}
}
-static void radeon_cp_dispatch_indices(drm_device_t * dev,
- drm_buf_t * elt_buf,
+static void radeon_cp_dispatch_indices(struct drm_device * dev,
+ struct drm_buf * elt_buf,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1647,13 +1647,13 @@ static void radeon_cp_dispatch_indices(drm_device_t * dev,
#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
static int radeon_cp_dispatch_texture(DRMFILE filp,
- drm_device_t * dev,
+ struct drm_device * dev,
drm_radeon_texture_t * tex,
drm_radeon_tex_image_t * image)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
- drm_buf_t *buf;
+ struct drm_file *filp_priv;
+ struct drm_buf *buf;
u32 format;
u32 *buffer;
const u8 __user *data;
@@ -1881,7 +1881,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
return 0;
}
-static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int i;
@@ -2134,7 +2134,7 @@ static int radeon_cp_clear(DRM_IOCTL_ARGS)
/* Not sure why this isn't set all the time:
*/
-static int radeon_do_init_pageflip(drm_device_t * dev)
+static int radeon_do_init_pageflip(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -2206,10 +2206,10 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_vertex_t vertex;
drm_radeon_tcl_prim_t prim;
@@ -2289,10 +2289,10 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_indices_t elts;
drm_radeon_tcl_prim_t prim;
int count;
@@ -2438,8 +2438,8 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_indirect_t indirect;
RING_LOCALS;
@@ -2507,10 +2507,10 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_radeon_vertex2_t vertex;
int i;
unsigned char laststate;
@@ -2603,7 +2603,7 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
}
static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
- drm_file_t * filp_priv,
+ struct drm_file * filp_priv,
drm_radeon_cmd_header_t header,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
@@ -2728,8 +2728,8 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
return 0;
}
-static int radeon_emit_packet3(drm_device_t * dev,
- drm_file_t * filp_priv,
+static int radeon_emit_packet3(struct drm_device * dev,
+ struct drm_file * filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2754,16 +2754,16 @@ static int radeon_emit_packet3(drm_device_t * dev,
return 0;
}
-static int radeon_emit_packet3_cliprect(drm_device_t *dev,
- drm_file_t *filp_priv,
+static int radeon_emit_packet3_cliprect(struct drm_device *dev,
+ struct drm_file *filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf,
int orig_nbox)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_clip_rect_t box;
+ struct drm_clip_rect box;
unsigned int cmdsz;
int ret;
- drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+ struct drm_clip_rect __user *boxes = cmdbuf->boxes;
int i = 0;
RING_LOCALS;
@@ -2816,7 +2816,7 @@ static int radeon_emit_packet3_cliprect(drm_device_t *dev,
return 0;
}
-static int radeon_emit_wait(drm_device_t * dev, int flags)
+static int radeon_emit_wait(struct drm_device * dev, int flags)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -2849,9 +2849,9 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf = NULL;
+ struct drm_file *filp_priv;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf = NULL;
int idx;
drm_radeon_kcmd_buffer_t cmdbuf;
drm_radeon_cmd_header_t header;
@@ -3085,6 +3085,9 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
else
value = RADEON_CARD_PCI;
break;
+ case RADEON_PARAM_VBLANK_CRTC:
+ value = radeon_vblank_crtc_get(dev);
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", param.param);
return DRM_ERR(EINVAL);
@@ -3102,7 +3105,7 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_file_t *filp_priv;
+ struct drm_file *filp_priv;
drm_radeon_setparam_t sp;
struct drm_radeon_driver_file_fields *radeon_priv;
@@ -3141,6 +3144,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
break;
+ case RADEON_SETPARAM_VBLANK_CRTC:
+ return radeon_vblank_crtc_set(dev, sp.value);
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", sp.param);
return DRM_ERR(EINVAL);
@@ -3156,7 +3162,7 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/
-void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(struct drm_device *dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3167,7 +3173,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
}
}
-void radeon_driver_lastclose(drm_device_t * dev)
+void radeon_driver_lastclose(struct drm_device *dev)
{
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3180,7 +3186,7 @@ void radeon_driver_lastclose(drm_device_t * dev)
radeon_do_release(dev);
}
-int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
+int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_driver_file_fields *radeon_priv;
@@ -3202,7 +3208,7 @@ int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
return 0;
}
-void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(struct drm_device *dev, struct drm_file *filp_priv)
{
struct drm_radeon_driver_file_fields *radeon_priv =
filp_priv->driver_priv;
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index b94fab556809..18c7235f6b73 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -32,7 +32,7 @@
#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */
#define SAVAGE_FREELIST_DEBUG 0
-static int savage_do_cleanup_bci(drm_device_t *dev);
+static int savage_do_cleanup_bci(struct drm_device *dev);
static int
savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
@@ -203,11 +203,11 @@ uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
/*
* Freelist management
*/
-static int savage_freelist_init(drm_device_t * dev)
+static int savage_freelist_init(struct drm_device * dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *buf;
drm_savage_buf_priv_t *entry;
int i;
DRM_DEBUG("count=%d\n", dma->buf_count);
@@ -236,7 +236,7 @@ static int savage_freelist_init(drm_device_t * dev)
return 0;
}
-static drm_buf_t *savage_freelist_get(drm_device_t * dev)
+static struct drm_buf *savage_freelist_get(struct drm_device * dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
@@ -269,7 +269,7 @@ static drm_buf_t *savage_freelist_get(drm_device_t * dev)
return NULL;
}
-void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf)
{
drm_savage_private_t *dev_priv = dev->dev_private;
drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
@@ -535,7 +535,7 @@ static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
}
-int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+int savage_driver_load(struct drm_device *dev, unsigned long chipset)
{
drm_savage_private_t *dev_priv;
@@ -558,7 +558,7 @@ int savage_driver_load(drm_device_t *dev, unsigned long chipset)
* in drm_addmap. Therefore we add them manually before the maps are
* initialized, and tear them down on last close.
*/
-int savage_driver_firstopen(drm_device_t *dev)
+int savage_driver_firstopen(struct drm_device *dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
unsigned long mmio_base, fb_base, fb_size, aperture_base;
@@ -655,7 +655,7 @@ int savage_driver_firstopen(drm_device_t *dev)
/*
* Delete MTRRs and free device-private data.
*/
-void savage_driver_lastclose(drm_device_t *dev)
+void savage_driver_lastclose(struct drm_device *dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
int i;
@@ -667,7 +667,7 @@ void savage_driver_lastclose(drm_device_t *dev)
dev_priv->mtrr[i].size, DRM_MTRR_WC);
}
-int savage_driver_unload(drm_device_t *dev)
+int savage_driver_unload(struct drm_device *dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
@@ -676,7 +676,7 @@ int savage_driver_unload(drm_device_t *dev)
return 0;
}
-static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
+static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init)
{
drm_savage_private_t *dev_priv = dev->dev_private;
@@ -711,7 +711,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
dev_priv->texture_offset = init->texture_offset;
dev_priv->texture_size = init->texture_size;
- DRM_GETSAREA();
+ dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
savage_do_cleanup_bci(dev);
@@ -898,7 +898,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
return 0;
}
-static int savage_do_cleanup_bci(drm_device_t * dev)
+static int savage_do_cleanup_bci(struct drm_device * dev)
{
drm_savage_private_t *dev_priv = dev->dev_private;
@@ -1007,9 +1007,9 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS)
* DMA buffer management
*/
-static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
+static int savage_bci_get_buffers(DRMFILE filp, struct drm_device *dev, struct drm_dma *d)
{
- drm_buf_t *buf;
+ struct drm_buf *buf;
int i;
for (i = d->granted_count; i < d->request_count; i++) {
@@ -1034,13 +1034,13 @@ static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
int savage_bci_buffers(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_device_dma_t *dma = dev->dma;
- drm_dma_t d;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_dma d;
int ret = 0;
LOCK_TEST_WITH_RETURN(dev, filp);
- DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *) data, sizeof(d));
+ DRM_COPY_FROM_USER_IOCTL(d, (struct drm_dma __user *) data, sizeof(d));
/* Please don't send us buffers.
*/
@@ -1064,14 +1064,14 @@ int savage_bci_buffers(DRM_IOCTL_ARGS)
ret = savage_bci_get_buffers(filp, dev, &d);
}
- DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *) data, d, sizeof(d));
+ DRM_COPY_TO_USER_IOCTL((struct drm_dma __user *) data, d, sizeof(d));
return ret;
}
-void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
+void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
drm_savage_private_t *dev_priv = dev->dev_private;
int i;
@@ -1085,7 +1085,7 @@ void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
/*i830_flush_queue(dev); */
for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
+ struct drm_buf *buf = dma->buflist[i];
drm_savage_buf_priv_t *buf_priv = buf->dev_private;
if (buf->filp == filp && buf_priv &&
diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
index e1148e8e7994..8a576ef01821 100644
--- a/drivers/char/drm/savage_drm.h
+++ b/drivers/char/drm/savage_drm.h
@@ -47,7 +47,7 @@
typedef struct _drm_savage_sarea {
/* LRU lists for texture memory in agp space and on the card.
*/
- drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
+ struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
1];
unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
@@ -113,7 +113,7 @@ typedef struct drm_savage_cmdbuf {
unsigned int vb_size; /* size of client vertex buffer in bytes */
unsigned int vb_stride; /* stride of vertices in 32bit words */
/* boxes in client's address space */
- drm_clip_rect_t __user *box_addr;
+ struct drm_clip_rect __user *box_addr;
unsigned int nbox; /* number of clipping boxes */
} drm_savage_cmdbuf_t;
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index 8f04b3d82292..5fd54de4280e 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -58,7 +58,7 @@ typedef struct drm_savage_buf_priv {
struct drm_savage_buf_priv *next;
struct drm_savage_buf_priv *prev;
drm_savage_age_t age;
- drm_buf_t *buf;
+ struct drm_buf *buf;
} drm_savage_buf_priv_t;
typedef struct drm_savage_dma_page {
@@ -192,7 +192,7 @@ typedef struct drm_savage_private {
/* Err, there is a macro wait_event in include/linux/wait.h.
* Avoid unwanted macro expansion. */
void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
- const drm_clip_rect_t * pbox);
+ const struct drm_clip_rect * pbox);
void (*dma_flush) (struct drm_savage_private * dev_priv);
} drm_savage_private_t;
@@ -203,22 +203,22 @@ extern int savage_bci_buffers(DRM_IOCTL_ARGS);
/* BCI functions */
extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
unsigned int flags);
-extern void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+extern void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf);
extern void savage_dma_reset(drm_savage_private_t * dev_priv);
extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);
extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,
unsigned int n);
-extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int savage_driver_firstopen(drm_device_t *dev);
-extern void savage_driver_lastclose(drm_device_t *dev);
-extern int savage_driver_unload(drm_device_t *dev);
-extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
+extern int savage_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int savage_driver_firstopen(struct drm_device *dev);
+extern void savage_driver_lastclose(struct drm_device *dev);
+extern int savage_driver_unload(struct drm_device *dev);
+extern void savage_reclaim_buffers(struct drm_device * dev, DRMFILE filp);
/* state functions */
extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
- const drm_clip_rect_t * pbox);
+ const struct drm_clip_rect * pbox);
extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
- const drm_clip_rect_t * pbox);
+ const struct drm_clip_rect * pbox);
#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
index 1ca1e9cb5a33..77497841478a 100644
--- a/drivers/char/drm/savage_state.c
+++ b/drivers/char/drm/savage_state.c
@@ -27,7 +27,7 @@
#include "savage_drv.h"
void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
- const drm_clip_rect_t * pbox)
+ const struct drm_clip_rect * pbox)
{
uint32_t scstart = dev_priv->state.s3d.new_scstart;
uint32_t scend = dev_priv->state.s3d.new_scend;
@@ -53,7 +53,7 @@ void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
}
void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
- const drm_clip_rect_t * pbox)
+ const struct drm_clip_rect * pbox)
{
uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
@@ -277,7 +277,7 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t * cmd_header,
- const drm_buf_t * dmabuf)
+ const struct drm_buf * dmabuf)
{
unsigned char reorder = 0;
unsigned int prim = cmd_header->prim.prim;
@@ -536,7 +536,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t * cmd_header,
const uint16_t *idx,
- const drm_buf_t * dmabuf)
+ const struct drm_buf * dmabuf)
{
unsigned char reorder = 0;
unsigned int prim = cmd_header->idx.prim;
@@ -792,7 +792,7 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t * cmd_header,
const drm_savage_cmd_header_t *data,
unsigned int nbox,
- const drm_clip_rect_t *boxes)
+ const struct drm_clip_rect *boxes)
{
unsigned int flags = cmd_header->clear0.flags;
unsigned int clear_cmd;
@@ -861,7 +861,7 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
}
static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
- unsigned int nbox, const drm_clip_rect_t *boxes)
+ unsigned int nbox, const struct drm_clip_rect *boxes)
{
unsigned int swap_cmd;
unsigned int i;
@@ -892,11 +892,11 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t *start,
const drm_savage_cmd_header_t *end,
- const drm_buf_t * dmabuf,
+ const struct drm_buf * dmabuf,
const unsigned int *vtxbuf,
unsigned int vb_size, unsigned int vb_stride,
unsigned int nbox,
- const drm_clip_rect_t *boxes)
+ const struct drm_clip_rect *boxes)
{
unsigned int i, j;
int ret;
@@ -957,13 +957,13 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_savage_private_t *dev_priv = dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_buf_t *dmabuf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf *dmabuf;
drm_savage_cmdbuf_t cmdbuf;
drm_savage_cmd_header_t *kcmd_addr = NULL;
drm_savage_cmd_header_t *first_draw_cmd;
unsigned int *kvb_addr = NULL;
- drm_clip_rect_t *kbox_addr = NULL;
+ struct drm_clip_rect *kbox_addr = NULL;
unsigned int i, j;
int ret = 0;
@@ -1019,7 +1019,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
cmdbuf.vb_addr = kvb_addr;
}
if (cmdbuf.nbox) {
- kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
+ kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(struct drm_clip_rect),
DRM_MEM_DRIVER);
if (kbox_addr == NULL) {
ret = DRM_ERR(ENOMEM);
@@ -1027,7 +1027,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
}
if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
- cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
+ cmdbuf.nbox * sizeof(struct drm_clip_rect))) {
ret = DRM_ERR(EFAULT);
goto done;
}
@@ -1158,7 +1158,7 @@ done:
/* If we didn't need to allocate them, these'll be NULL */
drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
- drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+ drm_free(kbox_addr, cmdbuf.nbox * sizeof(struct drm_clip_rect),
DRM_MEM_DRIVER);
return ret;
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 690e0af8e7c2..1912f5857051 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -35,7 +35,7 @@ static struct pci_device_id pciidlist[] = {
sisdrv_PCI_IDS
};
-static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
+static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
{
drm_sis_private_t *dev_priv;
int ret;
@@ -54,7 +54,7 @@ static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
return ret;
}
-static int sis_driver_unload(drm_device_t *dev)
+static int sis_driver_unload(struct drm_device *dev)
{
drm_sis_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 70d4ede75fe8..5630df874353 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -46,6 +46,7 @@ enum sis_family {
#include "drm_sman.h"
+
#define SIS_BASE (dev_priv->mmio)
#define SIS_READ(reg) DRM_READ32(SIS_BASE, reg);
#define SIS_WRITE(reg, val) DRM_WRITE32(SIS_BASE, reg, val);
@@ -53,7 +54,7 @@ enum sis_family {
typedef struct drm_sis_private {
drm_local_map_t *mmio;
unsigned int idle_fault;
- drm_sman_t sman;
+ struct drm_sman sman;
unsigned int chipset;
int vram_initialized;
int agp_initialized;
@@ -61,9 +62,9 @@ typedef struct drm_sis_private {
unsigned long agp_offset;
} drm_sis_private_t;
-extern int sis_idle(drm_device_t *dev);
-extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void sis_lastclose(drm_device_t *dev);
+extern int sis_idle(struct drm_device *dev);
+extern void sis_reclaim_buffers_locked(struct drm_device *dev, struct file *filp);
+extern void sis_lastclose(struct drm_device *dev);
extern drm_ioctl_desc_t sis_ioctls[];
extern int sis_max_ioctl;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index d26f5dbb7853..441bbdbf1510 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -94,7 +94,7 @@ static int sis_fb_init(DRM_IOCTL_ARGS)
mutex_lock(&dev->struct_mutex);
#if defined(CONFIG_FB_SIS)
{
- drm_sman_mm_t sman_mm;
+ struct drm_sman_mm sman_mm;
sman_mm.private = (void *)0xFFFFFFFF;
sman_mm.allocate = sis_sman_mm_allocate;
sman_mm.free = sis_sman_mm_free;
@@ -123,14 +123,14 @@ static int sis_fb_init(DRM_IOCTL_ARGS)
return 0;
}
-static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
+static int sis_drm_alloc(struct drm_device *dev, struct drm_file * priv,
unsigned long data, int pool)
{
drm_sis_private_t *dev_priv = dev->dev_private;
drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
drm_sis_mem_t mem;
int retval = 0;
- drm_memblock_item_t *item;
+ struct drm_memblock_item *item;
DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
@@ -229,12 +229,12 @@ static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
return sis_drm_alloc(dev, priv, data, AGP_TYPE);
}
-static drm_local_map_t *sis_reg_init(drm_device_t *dev)
+static drm_local_map_t *sis_reg_init(struct drm_device *dev)
{
- drm_map_list_t *entry;
+ struct drm_map_list *entry;
drm_local_map_t *map;
- list_for_each_entry(entry, &dev->maplist->head, head) {
+ list_for_each_entry(entry, &dev->maplist, head) {
map = entry->map;
if (!map)
continue;
@@ -245,7 +245,7 @@ static drm_local_map_t *sis_reg_init(drm_device_t *dev)
return NULL;
}
-int sis_idle(drm_device_t *dev)
+int sis_idle(struct drm_device *dev)
{
drm_sis_private_t *dev_priv = dev->dev_private;
uint32_t idle_reg;
@@ -314,10 +314,10 @@ void sis_lastclose(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex);
}
-void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void sis_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
{
drm_sis_private_t *dev_priv = dev->dev_private;
- drm_file_t *priv = filp->private_data;
+ struct drm_file *priv = filp->private_data;
mutex_lock(&dev->struct_mutex);
if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 13a9c5ca4593..7ff2b623c2d4 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -151,7 +151,7 @@ static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
}
-int via_dma_cleanup(drm_device_t * dev)
+int via_dma_cleanup(struct drm_device * dev)
{
if (dev->dev_private) {
drm_via_private_t *dev_priv =
@@ -169,7 +169,7 @@ int via_dma_cleanup(drm_device_t * dev)
return 0;
}
-static int via_initialize(drm_device_t * dev,
+static int via_initialize(struct drm_device * dev,
drm_via_private_t * dev_priv,
drm_via_dma_init_t * init)
{
@@ -262,7 +262,7 @@ static int via_dma_init(DRM_IOCTL_ARGS)
return retcode;
}
-static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd)
{
drm_via_private_t *dev_priv;
uint32_t *vb;
@@ -316,7 +316,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
return 0;
}
-int via_driver_dma_quiescent(drm_device_t * dev)
+int via_driver_dma_quiescent(struct drm_device * dev)
{
drm_via_private_t *dev_priv = dev->dev_private;
@@ -356,7 +356,7 @@ static int via_cmdbuffer(DRM_IOCTL_ARGS)
return 0;
}
-static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
+static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
drm_via_cmdbuffer_t * cmd)
{
drm_via_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 2881a06b6f55..fdb8609dd76f 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -207,7 +207,7 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
*/
static void
-via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
+via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
{
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -289,7 +289,7 @@ via_alloc_desc_pages(drm_via_sg_info_t *vsg)
}
static void
-via_abort_dmablit(drm_device_t *dev, int engine)
+via_abort_dmablit(struct drm_device *dev, int engine)
{
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -297,7 +297,7 @@ via_abort_dmablit(drm_device_t *dev, int engine)
}
static void
-via_dmablit_engine_off(drm_device_t *dev, int engine)
+via_dmablit_engine_off(struct drm_device *dev, int engine)
{
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -314,7 +314,7 @@ via_dmablit_engine_off(drm_device_t *dev, int engine)
*/
void
-via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)
+via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
{
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
@@ -433,7 +433,7 @@ via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_que
*/
static int
-via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine)
+via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
{
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -466,7 +466,7 @@ static void
via_dmablit_timer(unsigned long data)
{
drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
- drm_device_t *dev = blitq->dev;
+ struct drm_device *dev = blitq->dev;
int engine = (int)
(blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
@@ -502,7 +502,7 @@ static void
via_dmablit_workqueue(struct work_struct *work)
{
drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
- drm_device_t *dev = blitq->dev;
+ struct drm_device *dev = blitq->dev;
unsigned long irqsave;
drm_via_sg_info_t *cur_sg;
int cur_released;
@@ -545,7 +545,7 @@ via_dmablit_workqueue(struct work_struct *work)
void
-via_init_dmablit(drm_device_t *dev)
+via_init_dmablit(struct drm_device *dev)
{
int i,j;
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -582,7 +582,7 @@ via_init_dmablit(drm_device_t *dev)
static int
-via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
{
int draw = xfer->to_fb;
int ret = 0;
@@ -730,7 +730,7 @@ via_dmablit_release_slot(drm_via_blitq_t *blitq)
static int
-via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
+via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)
{
drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
drm_via_sg_info_t *vsg;
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h
index f4036cd5d0e0..6f6a513d5147 100644
--- a/drivers/char/drm/via_dmablit.h
+++ b/drivers/char/drm/via_dmablit.h
@@ -59,7 +59,7 @@ typedef struct _drm_via_sg_info {
} drm_via_sg_info_t;
typedef struct _drm_via_blitq {
- drm_device_t *dev;
+ struct drm_device *dev;
uint32_t cur_blit_handle;
uint32_t done_blit_handle;
unsigned serviced;
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index e4ee97d7156f..8f53c76062e9 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -40,7 +40,7 @@
#define VIA_NR_XVMC_LOCKS 5
#define VIA_MAX_CACHELINE_SIZE 64
#define XVMCLOCKPTR(saPriv,lockNo) \
- ((volatile drm_hw_lock_t *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
+ ((volatile struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
(VIA_MAX_CACHELINE_SIZE - 1)) & \
~(VIA_MAX_CACHELINE_SIZE - 1)) + \
VIA_MAX_CACHELINE_SIZE*(lockNo)))
@@ -182,7 +182,7 @@ typedef struct _drm_via_tex_region {
typedef struct _drm_via_sarea {
unsigned int dirty;
unsigned int nbox;
- drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS];
+ struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS];
drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
int texAge; /* last time texture was uploaded */
int ctxOwner; /* last context to upload state */
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index b46ca8e6306d..576711564a11 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -87,7 +87,7 @@ typedef struct drm_via_private {
uint32_t irq_pending_mask;
int *irq_map;
unsigned int idle_fault;
- drm_sman_t sman;
+ struct drm_sman sman;
int vram_initialized;
int agp_initialized;
unsigned long vram_offset;
@@ -123,31 +123,31 @@ extern int via_wait_irq(DRM_IOCTL_ARGS);
extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
extern int via_dma_blit( DRM_IOCTL_ARGS );
-extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int via_driver_unload(drm_device_t *dev);
+extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int via_driver_unload(struct drm_device *dev);
-extern int via_init_context(drm_device_t * dev, int context);
-extern int via_final_context(drm_device_t * dev, int context);
+extern int via_init_context(struct drm_device * dev, int context);
+extern int via_final_context(struct drm_device * dev, int context);
-extern int via_do_cleanup_map(drm_device_t * dev);
-extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int via_do_cleanup_map(struct drm_device * dev);
+extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
-extern void via_driver_irq_preinstall(drm_device_t * dev);
-extern void via_driver_irq_postinstall(drm_device_t * dev);
-extern void via_driver_irq_uninstall(drm_device_t * dev);
+extern void via_driver_irq_preinstall(struct drm_device * dev);
+extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern void via_driver_irq_uninstall(struct drm_device * dev);
-extern int via_dma_cleanup(drm_device_t * dev);
+extern int via_dma_cleanup(struct drm_device * dev);
extern void via_init_command_verifier(void);
-extern int via_driver_dma_quiescent(drm_device_t * dev);
+extern int via_driver_dma_quiescent(struct drm_device * dev);
extern void via_init_futex(drm_via_private_t * dev_priv);
extern void via_cleanup_futex(drm_via_private_t * dev_priv);
extern void via_release_futex(drm_via_private_t * dev_priv, int context);
-extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void via_lastclose(drm_device_t *dev);
+extern void via_reclaim_buffers_locked(struct drm_device *dev, struct file *filp);
+extern void via_lastclose(struct drm_device *dev);
-extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
-extern void via_init_dmablit(drm_device_t *dev);
+extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
+extern void via_init_dmablit(struct drm_device *dev);
#endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 1ac5941ad237..8dc99b5fbab6 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -98,7 +98,7 @@ static unsigned time_diff(struct timeval *now, struct timeval *then)
irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
{
- drm_device_t *dev = (drm_device_t *) arg;
+ struct drm_device *dev = (struct drm_device *) arg;
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
int handled = 0;
@@ -163,7 +163,7 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
}
}
-int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
unsigned int cur_vblank;
@@ -191,7 +191,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
}
static int
-via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequence,
unsigned int *sequence)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -244,7 +244,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
* drm_dma.h hooks
*/
-void via_driver_irq_preinstall(drm_device_t * dev)
+void via_driver_irq_preinstall(struct drm_device * dev)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
@@ -293,7 +293,7 @@ void via_driver_irq_preinstall(drm_device_t * dev)
}
}
-void via_driver_irq_postinstall(drm_device_t * dev)
+void via_driver_irq_postinstall(struct drm_device * dev)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
@@ -312,7 +312,7 @@ void via_driver_irq_postinstall(drm_device_t * dev)
}
}
-void via_driver_irq_uninstall(drm_device_t * dev)
+void via_driver_irq_uninstall(struct drm_device * dev)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 4e3fc072aa3b..7fb9d2a2cce2 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -25,13 +25,13 @@
#include "via_drm.h"
#include "via_drv.h"
-static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
+static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
{
drm_via_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
- DRM_GETSAREA();
+ dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
dev->dev_private = (void *)dev_priv;
@@ -68,7 +68,7 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
return 0;
}
-int via_do_cleanup_map(drm_device_t * dev)
+int via_do_cleanup_map(struct drm_device * dev)
{
via_dma_cleanup(dev);
@@ -95,7 +95,7 @@ int via_map_init(DRM_IOCTL_ARGS)
return -EINVAL;
}
-int via_driver_load(drm_device_t *dev, unsigned long chipset)
+int via_driver_load(struct drm_device *dev, unsigned long chipset)
{
drm_via_private_t *dev_priv;
int ret = 0;
@@ -115,7 +115,7 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset)
return ret;
}
-int via_driver_unload(drm_device_t *dev)
+int via_driver_unload(struct drm_device *dev)
{
drm_via_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 2fcf0577a7aa..85d56acd9d82 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -127,7 +127,7 @@ int via_mem_alloc(DRM_IOCTL_ARGS)
drm_via_mem_t mem;
int retval = 0;
- drm_memblock_item_t *item;
+ struct drm_memblock_item *item;
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
unsigned long tmpSize;
@@ -188,10 +188,10 @@ int via_mem_free(DRM_IOCTL_ARGS)
}
-void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void via_reclaim_buffers_locked(struct drm_device * dev, struct file *filp)
{
drm_via_private_t *dev_priv = dev->dev_private;
- drm_file_t *priv = filp->private_data;
+ struct drm_file *priv = filp->private_data;
mutex_lock(&dev->struct_mutex);
if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 2e7e08078287..832d48356e91 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -252,10 +252,9 @@ eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
unsigned long offset,
unsigned long size,
- drm_device_t * dev)
+ struct drm_device * dev)
{
- struct list_head *list;
- drm_map_list_t *r_list;
+ struct drm_map_list *r_list;
drm_local_map_t *map = seq->map_cache;
if (map && map->offset <= offset
@@ -263,8 +262,7 @@ static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
return map;
}
- list_for_each(list, &dev->maplist->head) {
- r_list = (drm_map_list_t *) list;
+ list_for_each_entry(r_list, &dev->maplist, head) {
map = r_list->map;
if (!map)
continue;
@@ -964,7 +962,7 @@ via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
int
via_verify_command_stream(const uint32_t * buf, unsigned int size,
- drm_device_t * dev, int agp)
+ struct drm_device * dev, int agp)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -1039,7 +1037,7 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size,
}
int
-via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
unsigned int size)
{
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index b77f59df0278..28b50296a7bd 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -47,7 +47,7 @@ typedef struct {
drm_via_sequence_t unfinished;
int agp_texture;
int multitex;
- drm_device_t *dev;
+ struct drm_device *dev;
drm_local_map_t *map_cache;
uint32_t vertex_count;
int agp;
@@ -55,8 +55,8 @@ typedef struct {
} drm_via_state_t;
extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
- drm_device_t * dev, int agp);
-extern int via_parse_command_stream(drm_device_t *dev, const uint32_t *buf,
+ struct drm_device * dev, int agp);
+extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
unsigned int size);
#endif
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index d1bfbaa2aa02..74cd5118af57 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1121,8 +1121,6 @@ static void change_speed(struct esp_struct *info)
/*
* Set up parity check flag
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
if (I_INPCK(info->tty))
info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
@@ -1920,11 +1918,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
unsigned long flags;
- if ( (tty->termios->c_cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_speed(info);
spin_lock_irqsave(&info->lock, flags);
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 8ea02755b1c9..8facf3e25c49 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -43,16 +43,6 @@ static int gs_debug;
#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__)
-#define NEW_WRITE_LOCKING 1
-#if NEW_WRITE_LOCKING
-#define DECL /* Nothing */
-#define LOCKIT mutex_lock(& port->port_write_mutex);
-#define RELEASEIT mutex_unlock(&port->port_write_mutex);
-#else
-#define DECL unsigned long flags;
-#define LOCKIT save_flags (flags);cli ()
-#define RELEASEIT restore_flags (flags)
-#endif
#define RS_EVENT_WRITE_WAKEUP 1
@@ -62,7 +52,6 @@ module_param(gs_debug, int, 0644);
void gs_put_char(struct tty_struct * tty, unsigned char ch)
{
struct gs_port *port;
- DECL
func_enter ();
@@ -75,11 +64,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
if (! (port->flags & ASYNC_INITIALIZED)) return;
/* Take a lock on the serial tranmit buffer! */
- LOCKIT;
+ mutex_lock(& port->port_write_mutex);
if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
- RELEASEIT;
+ mutex_unlock(&port->port_write_mutex);
return;
}
@@ -87,13 +76,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
port->xmit_head &= SERIAL_XMIT_SIZE - 1;
port->xmit_cnt++; /* Characters in buffer */
- RELEASEIT;
+ mutex_unlock(&port->port_write_mutex);
func_exit ();
}
-#ifdef NEW_WRITE_LOCKING
-
/*
> Problems to take into account are:
> -1- Interrupts that empty part of the buffer.
@@ -166,90 +153,6 @@ int gs_write(struct tty_struct * tty,
func_exit ();
return total;
}
-#else
-/*
-> Problems to take into account are:
-> -1- Interrupts that empty part of the buffer.
-> -2- page faults on the access to userspace.
-> -3- Other processes that are also trying to do a "write".
-*/
-
-int gs_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- struct gs_port *port;
- int c, total = 0;
- int t;
- unsigned long flags;
-
- func_enter ();
-
- /* The standard serial driver returns 0 in this case.
- That sounds to me as "No error, I just didn't get to writing any
- bytes. Feel free to try again."
- The "official" way to write n bytes from buf is:
-
- for (nwritten = 0;nwritten < n;nwritten += rv) {
- rv = write (fd, buf+nwritten, n-nwritten);
- if (rv < 0) break; // Error: bail out. //
- }
-
- which will loop endlessly in this case. The manual page for write
- agrees with me. In practise almost everybody writes
- "write (fd, buf,n);" but some people might have had to deal with
- incomplete writes in the past and correctly implemented it by now...
- */
-
- if (!tty) return -EIO;
-
- port = tty->driver_data;
- if (!port || !port->xmit_buf)
- return -EIO;
-
- local_save_flags(flags);
- while (1) {
- cli();
- c = count;
-
- /* This is safe because we "OWN" the "head". Noone else can
- change the "head": we own the port_write_mutex. */
- /* Don't overrun the end of the buffer */
- t = SERIAL_XMIT_SIZE - port->xmit_head;
- if (t < c) c = t;
-
- /* This is safe because the xmit_cnt can only decrease. This
- would increase "t", so we might copy too little chars. */
- /* Don't copy past the "head" of the buffer */
- t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
- if (t < c) c = t;
-
- /* Can't copy more? break out! */
- if (c <= 0) {
- local_restore_flags(flags);
- break;
- }
- memcpy(port->xmit_buf + port->xmit_head, buf, c);
- port->xmit_head = ((port->xmit_head + c) &
- (SERIAL_XMIT_SIZE-1));
- port->xmit_cnt += c;
- local_restore_flags(flags);
- buf += c;
- count -= c;
- total += c;
- }
-
- if (port->xmit_cnt &&
- !tty->stopped &&
- !tty->hw_stopped &&
- !(port->flags & GS_TX_INTEN)) {
- port->flags |= GS_TX_INTEN;
- port->rd->enable_tx_interrupts (port);
- }
- func_exit ();
- return total;
-}
-
-#endif
@@ -737,23 +640,6 @@ void gs_set_termios (struct tty_struct * tty,
gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
}
- /* This is an optimization that is only allowed for dumb cards */
- /* Smart cards require knowledge of iflags and oflags too: that
- might change hardware cooking mode.... */
- if (old_termios) {
- if( (tiosp->c_iflag == old_termios->c_iflag)
- && (tiosp->c_oflag == old_termios->c_oflag)
- && (tiosp->c_cflag == old_termios->c_cflag)
- && (tiosp->c_lflag == old_termios->c_lflag)
- && (tiosp->c_line == old_termios->c_line)
- && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) {
- gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n");
- return /* 0 */;
- }
- } else
- gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: "
- "no optimization\n");
-
if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n");
if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n");
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 9e1fc02967ff..69f0a2993af0 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -173,7 +173,6 @@ static void gen_rtc_interrupt(unsigned long arg)
static ssize_t gen_rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- DECLARE_WAITQUEUE(wait, current);
unsigned long data;
ssize_t retval;
@@ -183,18 +182,10 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
return -EAGAIN;
- add_wait_queue(&gen_rtc_wait, &wait);
- retval = -ERESTARTSYS;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- data = xchg(&gen_rtc_irq_data, 0);
- if (data)
- break;
- if (signal_pending(current))
- goto out;
- schedule();
- }
+ retval = wait_event_interruptible(gen_rtc_wait,
+ (data = xchg(&gen_rtc_irq_data, 0)));
+ if (retval)
+ goto out;
/* first test allows optimizer to nuke this case for 32-bit machines */
if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
@@ -206,10 +197,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
retval = put_user(data, (unsigned long __user *)buf) ?:
sizeof(unsigned long);
}
- out:
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&gen_rtc_wait, &wait);
-
+out:
return retval;
}
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 322bc5f7d86b..83c1151ec7a2 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -674,11 +674,12 @@ static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
* calling hvc_poll() who determines whether a console adapter support
* interrupts.
*/
-int khvcd(void *unused)
+static int khvcd(void *unused)
{
int poll_mask;
struct hvc_struct *hp;
+ set_freezable();
__set_current_state(TASK_RUNNING);
do {
poll_mask = 0;
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 4ae9811d1a6c..753f46052b87 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -296,12 +296,10 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw,
(BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
== BIOS_CNTL_LOCK_ENABLE_MASK) {
static __initdata /*const*/ char warning[] =
- KERN_WARNING PFX "Firmware space is locked read-only. "
- KERN_WARNING PFX "If you can't or\n don't want to "
- KERN_WARNING PFX "disable this in firmware setup, and "
- KERN_WARNING PFX "if\n you are certain that your "
- KERN_WARNING PFX "system has a functional\n RNG, try"
- KERN_WARNING PFX "using the 'no_fwh_detect' option.\n";
+ KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+ KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+ KERN_WARNING PFX "you are certain that your system has a functional\n"
+ KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
if (no_fwh_detect)
return -ENODEV;
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
index dd761a1e4f08..61ef013b8445 100644
--- a/drivers/char/ip2/i2ellis.c
+++ b/drivers/char/ip2/i2ellis.c
@@ -43,8 +43,6 @@ static void iiEnableMailIrqIIEX(i2eBordStrPtr);
static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
-static void ii2DelayTimer(unsigned int);
-static void ii2DelayWakeup(unsigned long id);
static void ii2Nop(void);
//***************
@@ -55,8 +53,6 @@ static int ii2Safe; // Safe I/O address for delay routine
static int iiDelayed; // Set when the iiResetDelay function is
// called. Cleared when ANY board is reset.
-static struct timer_list * pDelayTimer; // Used by iiDelayTimer
-static wait_queue_head_t pDelayWait; // Used by iiDelayTimer
static rwlock_t Dl_spinlock;
//********
@@ -86,9 +82,6 @@ static rwlock_t Dl_spinlock;
static void
iiEllisInit(void)
{
- pDelayTimer = kmalloc ( sizeof (struct timer_list), GFP_KERNEL );
- init_timer(pDelayTimer);
- init_waitqueue_head(&pDelayWait);
LOCK_INIT(&Dl_spinlock);
}
@@ -106,7 +99,6 @@ iiEllisInit(void)
static void
iiEllisCleanup(void)
{
- kfree(pDelayTimer);
}
//******************************************************************************
@@ -560,19 +552,6 @@ iiInitialize(i2eBordStrPtr pB)
COMPLETE(pB, I2EE_GOOD);
}
-//=======================================================
-// Delay Routines
-//
-// iiDelayIO
-// iiNop
-//=======================================================
-
-static void
-ii2DelayWakeup(unsigned long id)
-{
- wake_up_interruptible ( &pDelayWait );
-}
-
//******************************************************************************
// Function: ii2DelayTimer(mseconds)
// Parameters: mseconds - number of milliseconds to delay
@@ -594,28 +573,7 @@ ii2DelayWakeup(unsigned long id)
static void
ii2DelayTimer(unsigned int mseconds)
{
- wait_queue_t wait;
-
- init_waitqueue_entry(&wait, current);
-
- init_timer ( pDelayTimer );
-
- add_wait_queue(&pDelayWait, &wait);
-
- set_current_state( TASK_INTERRUPTIBLE );
-
- pDelayTimer->expires = jiffies + ( mseconds + 9 ) / 10;
- pDelayTimer->function = ii2DelayWakeup;
- pDelayTimer->data = 0;
-
- add_timer ( pDelayTimer );
-
- schedule();
-
- set_current_state( TASK_RUNNING );
- remove_wait_queue(&pDelayWait, &wait);
-
- del_timer ( pDelayTimer );
+ msleep_interruptible(mseconds);
}
#if 0
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index b894f67fdf14..0baa8fab4ea7 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -2,11 +2,9 @@
# IPMI device configuration
#
-menu "IPMI"
- depends on HAS_IOMEM
-
-config IPMI_HANDLER
+menuconfig IPMI_HANDLER
tristate 'IPMI top-level message handler'
+ depends on HAS_IOMEM
help
This enables the central IPMI message handler, required for IPMI
to work.
@@ -18,9 +16,10 @@ config IPMI_HANDLER
If unsure, say N.
+if IPMI_HANDLER
+
config IPMI_PANIC_EVENT
bool 'Generate a panic event to all BMCs on a panic'
- depends on IPMI_HANDLER
help
When a panic occurs, this will cause the IPMI message handler to
generate an IPMI event describing the panic to each interface
@@ -40,14 +39,12 @@ config IPMI_PANIC_STRING
config IPMI_DEVICE_INTERFACE
tristate 'Device interface for IPMI'
- depends on IPMI_HANDLER
help
This provides an IOCTL interface to the IPMI message handler so
userland processes may use IPMI. It supports poll() and select().
config IPMI_SI
tristate 'IPMI System Interface handler'
- depends on IPMI_HANDLER
help
Provides a driver for System Interfaces (KCS, SMIC, BT).
Currently, only KCS and SMIC are supported. If
@@ -55,15 +52,13 @@ config IPMI_SI
config IPMI_WATCHDOG
tristate 'IPMI Watchdog Timer'
- depends on IPMI_HANDLER
help
This enables the IPMI watchdog timer.
config IPMI_POWEROFF
tristate 'IPMI Poweroff'
- depends on IPMI_HANDLER
help
This enables a function to power off the system with IPMI if
the IPMI management controller is capable of this.
-endmenu
+endif # IPMI_HANDLER
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e02893b7b300..b86186de7f07 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -679,7 +679,7 @@ static int ipmi_poweroff_init (void)
{
int rv;
- printk ("Copyright (C) 2004 MontaVista Software -"
+ printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -"
" IPMI Powerdown via sys_reboot.\n");
if (poweroff_powercycle)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 78e1b962fe35..4edfdda0cf99 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2857,7 +2857,7 @@ static int try_smi_init(struct smi_info *new_smi)
mutex_unlock(&smi_infos_lock);
- printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
+ printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
return 0;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 761f77740d67..77a7a4a06620 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -171,9 +171,6 @@ static struct pci_driver isicom_driver = {
static int prev_card = 3; /* start servicing isi_card[0] */
static struct tty_driver *isicom_normal;
-static DECLARE_COMPLETION(isi_timerdone);
-static char re_schedule = 1;
-
static void isicom_tx(unsigned long _data);
static void isicom_start(struct tty_struct *tty);
@@ -187,7 +184,7 @@ static signed char linuxb_to_isib[] = {
struct isi_board {
unsigned long base;
- unsigned char irq;
+ int irq;
unsigned char port_count;
unsigned short status;
unsigned short port_status; /* each bit for each port */
@@ -227,7 +224,7 @@ static struct isi_port isi_ports[PORT_COUNT];
* it wants to talk.
*/
-static inline int WaitTillCardIsFree(u16 base)
+static inline int WaitTillCardIsFree(unsigned long base)
{
unsigned int count = 0;
unsigned int a = in_atomic(); /* do we run under spinlock? */
@@ -243,17 +240,18 @@ static inline int WaitTillCardIsFree(u16 base)
static int lock_card(struct isi_board *card)
{
- char retries;
unsigned long base = card->base;
+ unsigned int retries, a;
- for (retries = 0; retries < 100; retries++) {
+ for (retries = 0; retries < 10; retries++) {
spin_lock_irqsave(&card->card_lock, card->flags);
- if (inw(base + 0xe) & 0x1) {
- return 1;
- } else {
- spin_unlock_irqrestore(&card->card_lock, card->flags);
- udelay(1000); /* 1ms */
+ for (a = 0; a < 10; a++) {
+ if (inw(base + 0xe) & 0x1)
+ return 1;
+ udelay(10);
}
+ spin_unlock_irqrestore(&card->card_lock, card->flags);
+ msleep(10);
}
printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
card->base);
@@ -261,23 +259,6 @@ static int lock_card(struct isi_board *card)
return 0; /* Failed to acquire the card! */
}
-static int lock_card_at_interrupt(struct isi_board *card)
-{
- unsigned char retries;
- unsigned long base = card->base;
-
- for (retries = 0; retries < 200; retries++) {
- spin_lock_irqsave(&card->card_lock, card->flags);
-
- if (inw(base + 0xe) & 0x1)
- return 1;
- else
- spin_unlock_irqrestore(&card->card_lock, card->flags);
- }
- /* Failing in interrupt is an acceptable event */
- return 0; /* Failed to acquire the card! */
-}
-
static void unlock_card(struct isi_board *card)
{
spin_unlock_irqrestore(&card->card_lock, card->flags);
@@ -415,7 +396,9 @@ static inline int __isicom_paranoia_check(struct isi_port const *port,
static void isicom_tx(unsigned long _data)
{
- short count = (BOARD_COUNT-1), card, base;
+ unsigned long flags, base;
+ unsigned int retries;
+ short count = (BOARD_COUNT-1), card;
short txcount, wrd, residue, word_count, cnt;
struct isi_port *port;
struct tty_struct *tty;
@@ -435,32 +418,34 @@ static void isicom_tx(unsigned long _data)
count = isi_card[card].port_count;
port = isi_card[card].ports;
base = isi_card[card].base;
+
+ spin_lock_irqsave(&isi_card[card].card_lock, flags);
+ for (retries = 0; retries < 100; retries++) {
+ if (inw(base + 0xe) & 0x1)
+ break;
+ udelay(2);
+ }
+ if (retries >= 100)
+ goto unlock;
+
for (;count > 0;count--, port++) {
- if (!lock_card_at_interrupt(&isi_card[card]))
- continue;
/* port not active or tx disabled to force flow control */
if (!(port->flags & ASYNC_INITIALIZED) ||
!(port->status & ISI_TXOK))
- unlock_card(&isi_card[card]);
continue;
tty = port->tty;
-
- if (tty == NULL) {
- unlock_card(&isi_card[card]);
+ if (tty == NULL)
continue;
- }
txcount = min_t(short, TX_SIZE, port->xmit_cnt);
- if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
- unlock_card(&isi_card[card]);
+ if (txcount <= 0 || tty->stopped || tty->hw_stopped)
continue;
- }
- if (!(inw(base + 0x02) & (1 << port->channel))) {
- unlock_card(&isi_card[card]);
+
+ if (!(inw(base + 0x02) & (1 << port->channel)))
continue;
- }
+
pr_dbg("txing %d bytes, port%d.\n", txcount,
port->channel + 1);
outw((port->channel << isi_card[card].shift_count) | txcount,
@@ -508,16 +493,12 @@ static void isicom_tx(unsigned long _data)
port->status &= ~ISI_TXOK;
if (port->xmit_cnt <= WAKEUP_CHARS)
tty_wakeup(tty);
- unlock_card(&isi_card[card]);
}
+unlock:
+ spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
/* schedule another tx for hopefully in about 10ms */
sched_again:
- if (!re_schedule) {
- complete(&isi_timerdone);
- return;
- }
-
mod_timer(&tx, jiffies + msecs_to_jiffies(10));
}
@@ -1749,17 +1730,13 @@ static unsigned int card_count;
static int __devinit isicom_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- unsigned int ioaddr, signature, index;
+ unsigned int signature, index;
int retval = -EPERM;
- u8 pciirq;
struct isi_board *board = NULL;
if (card_count >= BOARD_COUNT)
goto err;
- ioaddr = pci_resource_start(pdev, 3);
- /* i.e at offset 0x1c in the PCI configuration register space. */
- pciirq = pdev->irq;
dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
/* allot the first empty slot in the array */
@@ -1770,8 +1747,8 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
}
board->index = index;
- board->base = ioaddr;
- board->irq = pciirq;
+ board->base = pci_resource_start(pdev, 3);
+ board->irq = pdev->irq;
card_count++;
pci_set_drvdata(pdev, board);
@@ -1901,9 +1878,7 @@ error:
static void __exit isicom_exit(void)
{
- re_schedule = 0;
-
- wait_for_completion_timeout(&isi_timerdone, HZ);
+ del_timer_sync(&tx);
pci_unregister_driver(&isicom_driver);
tty_unregister_driver(isicom_normal);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 7b279d1de4a2..3c66f402f9d7 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1753,9 +1753,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
return;
tiosp = tty->termios;
- if ((tiosp->c_cflag == old->c_cflag) &&
- (tiosp->c_iflag == old->c_iflag))
- return;
stli_mkasyport(portp, &aport, tiosp);
stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
@@ -2166,14 +2163,10 @@ static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigne
cdkhdr_t __iomem *hdrp;
cdkctrl_t __iomem *cp;
unsigned char __iomem *bits;
- unsigned long flags;
-
- spin_lock_irqsave(&brd_lock, flags);
if (test_bit(ST_CMDING, &portp->state)) {
printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
(int) cmd);
- spin_unlock_irqrestore(&brd_lock, flags);
return;
}
@@ -2194,7 +2187,6 @@ static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigne
writeb(readb(bits) | portp->portbit, bits);
set_bit(ST_CMDING, &portp->state);
EBRDDISABLE(brdp);
- spin_unlock_irqrestore(&brd_lock, flags);
}
static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
@@ -3218,13 +3210,13 @@ static int stli_initecp(struct stlibrd *brdp)
goto err;
}
+ brdp->iosize = ECP_IOSIZE;
+
if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
retval = -EIO;
goto err;
}
- brdp->iosize = ECP_IOSIZE;
-
/*
* Based on the specific board type setup the common vars to access
* and enable shared memory. Set all board specific information now
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 90965b4def5c..2ce0af1bd588 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -24,6 +24,7 @@
* 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
*/
+#include <linux/consolemap.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/tty.h>
@@ -308,10 +309,9 @@ static void applkey(struct vc_data *vc, int key, char mode)
* Many other routines do put_queue, but I think either
* they produce ASCII, or they produce some user-assigned
* string, and in both cases we might assume that it is
- * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
- * but we need only 16 bits here
+ * in utf-8 already.
*/
-static void to_utf8(struct vc_data *vc, ushort c)
+static void to_utf8(struct vc_data *vc, uint c)
{
if (c < 0x80)
/* 0******* */
@@ -320,11 +320,21 @@ static void to_utf8(struct vc_data *vc, ushort c)
/* 110***** 10****** */
put_queue(vc, 0xc0 | (c >> 6));
put_queue(vc, 0x80 | (c & 0x3f));
- } else {
+ } else if (c < 0x10000) {
+ if (c >= 0xD800 && c < 0xE000)
+ return;
+ if (c == 0xFFFF)
+ return;
/* 1110**** 10****** 10****** */
put_queue(vc, 0xe0 | (c >> 12));
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
put_queue(vc, 0x80 | (c & 0x3f));
+ } else if (c < 0x110000) {
+ /* 11110*** 10****** 10****** 10****** */
+ put_queue(vc, 0xf0 | (c >> 18));
+ put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
+ put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
+ put_queue(vc, 0x80 | (c & 0x3f));
}
}
@@ -393,7 +403,7 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
return d;
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, d);
+ to_utf8(vc, conv_8bit_to_uni(d));
else if (d < 0x100)
put_queue(vc, d);
@@ -407,7 +417,7 @@ static void fn_enter(struct vc_data *vc)
{
if (diacr) {
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, diacr);
+ to_utf8(vc, conv_8bit_to_uni(diacr));
else if (diacr < 0x100)
put_queue(vc, diacr);
diacr = 0;
@@ -617,7 +627,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
return;
}
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, value);
+ to_utf8(vc, conv_8bit_to_uni(value));
else if (value < 0x100)
put_queue(vc, value);
}
@@ -775,7 +785,7 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
/* kludge */
if (up_flag && shift_state != old_state && npadch != -1) {
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, npadch & 0xffff);
+ to_utf8(vc, npadch);
else
put_queue(vc, npadch & 0xff);
npadch = -1;
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4e6fb9651a16..71c8cd7fa15f 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -67,25 +67,13 @@ extern int pmu_device_init(void);
#ifdef CONFIG_PROC_FS
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
{
- struct miscdevice *p;
- loff_t off = 0;
-
mutex_lock(&misc_mtx);
- list_for_each_entry(p, &misc_list, list) {
- if (*pos == off++)
- return p;
- }
- return NULL;
+ return seq_list_start(&misc_list, *pos);
}
static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct list_head *n = ((struct miscdevice *)v)->list.next;
-
- ++*pos;
-
- return (n != &misc_list) ? list_entry(n, struct miscdevice, list)
- : NULL;
+ return seq_list_next(v, &misc_list, pos);
}
static void misc_seq_stop(struct seq_file *seq, void *v)
@@ -95,7 +83,7 @@ static void misc_seq_stop(struct seq_file *seq, void *v)
static int misc_seq_show(struct seq_file *seq, void *v)
{
- const struct miscdevice *p = v;
+ const struct miscdevice *p = list_entry(v, struct miscdevice, list);
seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : "");
return 0;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index e0d35c20c04f..ed76f0a127fd 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -1405,7 +1405,6 @@ static int moxaCard;
static struct mon_str moxaLog;
static int moxaFuncTout = HZ / 2;
-static void moxadelay(int);
static void moxafunc(void __iomem *, int, ushort);
static void wait_finish(void __iomem *);
static void low_water_check(void __iomem *);
@@ -2404,10 +2403,10 @@ void MoxaPortSendBreak(int port, int ms100)
ofsAddr = moxa_ports[port].tableAddr;
if (ms100) {
moxafunc(ofsAddr, FC_SendBreak, Magic_code);
- moxadelay(ms100 * (HZ / 10));
+ msleep(ms100 * 10);
} else {
moxafunc(ofsAddr, FC_SendBreak, Magic_code);
- moxadelay(HZ / 4); /* 250 ms */
+ msleep(250);
}
moxafunc(ofsAddr, FC_StopBreak, Magic_code);
}
@@ -2476,18 +2475,6 @@ static int moxa_set_serial_info(struct moxa_port *info,
/*****************************************************************************
* Static local functions: *
*****************************************************************************/
-/*
- * moxadelay - delays a specified number ticks
- */
-static void moxadelay(int tick)
-{
- unsigned long st, et;
-
- st = jiffies;
- et = st + tick;
- while (time_before(jiffies, et));
-}
-
static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
{
@@ -2535,7 +2522,7 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
return -EFAULT;
baseAddr = moxa_boards[cardno].basemem;
writeb(HW_reset, baseAddr + Control_reg); /* reset */
- moxadelay(1); /* delay 10 ms */
+ msleep(10);
for (i = 0; i < 4096; i++)
writeb(0, baseAddr + i); /* clear fix page */
for (i = 0; i < len; i++)
@@ -2713,7 +2700,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
for (i = 0; i < 100; i++) {
if (readw(baseAddr + C218_key) == keycode)
break;
- moxadelay(1); /* delay 10 ms */
+ msleep(10);
}
if (readw(baseAddr + C218_key) != keycode) {
return (-1);
@@ -2725,7 +2712,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
for (i = 0; i < 100; i++) {
if (readw(baseAddr + C218_key) == keycode)
break;
- moxadelay(1); /* delay 10 ms */
+ msleep(10);
}
retry++;
} while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
@@ -2736,7 +2723,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
for (i = 0; i < 100; i++) {
if (readw(baseAddr + Magic_no) == Magic_code)
break;
- moxadelay(1); /* delay 10 ms */
+ msleep(10);
}
if (readw(baseAddr + Magic_no) != Magic_code) {
return (-1);
@@ -2746,7 +2733,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
for (i = 0; i < 100; i++) {
if (readw(baseAddr + Magic_no) == Magic_code)
break;
- moxadelay(1); /* delay 10 ms */
+ msleep(10);
}
if (readw(baseAddr + Magic_no) != Magic_code) {
return (-1);
@@ -2788,7 +2775,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
for (i = 0; i < 10; i++) {
if (readw(baseAddr + C320_key) == C320_KeyCode)
break;
- moxadelay(1);
+ msleep(10);
}
if (readw(baseAddr + C320_key) != C320_KeyCode)
return (-1);
@@ -2799,7 +2786,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
for (i = 0; i < 10; i++) {
if (readw(baseAddr + C320_key) == C320_KeyCode)
break;
- moxadelay(1);
+ msleep(10);
}
retry++;
} while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
@@ -2809,7 +2796,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
for (i = 0; i < 600; i++) {
if (readw(baseAddr + Magic_no) == Magic_code)
break;
- moxadelay(1);
+ msleep(10);
}
if (readw(baseAddr + Magic_no) != Magic_code)
return (-100);
@@ -2828,7 +2815,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
for (i = 0; i < 500; i++) {
if (readw(baseAddr + Magic_no) == Magic_code)
break;
- moxadelay(1);
+ msleep(10);
}
if (readw(baseAddr + Magic_no) != Magic_code)
return (-102);
@@ -2842,7 +2829,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
for (i = 0; i < 600; i++) {
if (readw(baseAddr + Magic_no) == Magic_code)
break;
- moxadelay(1);
+ msleep(10);
}
if (readw(baseAddr + Magic_no) != Magic_code)
return (-102);
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 7ac30612068b..c716ef0dd370 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -265,7 +265,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
vdata->refcnt = ATOMIC_INIT(1);
vma->vm_private_data = vdata;
- vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+ vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP);
if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_ops = &mspec_vm_ops;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 5953a45d7e96..2aee3fef0416 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -90,8 +90,6 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
- IXON|IXOFF))
#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED)
@@ -1729,16 +1727,12 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
struct mxser_struct *info = tty->driver_data;
unsigned long flags;
- if ((tty->termios->c_cflag != old_termios->c_cflag) ||
- (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+ mxser_change_speed(info, old_termios);
- mxser_change_speed(info, old_termios);
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- mxser_start(tty);
- }
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ mxser_start(tty);
}
/* Handle sw stopped */
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 6cde448cd5b2..6a563932ba19 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -72,8 +72,6 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
- IXON|IXOFF))
#define C168_ASIC_ID 1
#define C104_ASIC_ID 2
@@ -1560,7 +1558,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
return -EFAULT;
return 0;
case MOXA_ASPP_MON_EXT: {
- int status, p, shiftbit;
+ int p, shiftbit;
unsigned long opmode;
unsigned cflag, iflag;
@@ -1990,18 +1988,14 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
struct mxser_port *info = tty->driver_data;
unsigned long flags;
- if ((tty->termios->c_cflag != old_termios->c_cflag) ||
- (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
-
- spin_lock_irqsave(&info->slock, flags);
- mxser_change_speed(info, old_termios);
- spin_unlock_irqrestore(&info->slock, flags);
+ spin_lock_irqsave(&info->slock, flags);
+ mxser_change_speed(info, old_termios);
+ spin_unlock_irqrestore(&info->slock, flags);
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- mxser_start(tty);
- }
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ mxser_start(tty);
}
/* Handle sw stopped */
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 337a87f86a3b..e8332f305d72 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -400,7 +400,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
/* Send the next block of data to device */
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
-
+
+ /* rollback was possible and has been done */
+ if (actual == -ERESTARTSYS) {
+ n_hdlc->tbuf = tbuf;
+ break;
+ }
/* if transmit error, throw frame away by */
/* pretending it was accepted by driver */
if (actual < 0)
@@ -780,13 +785,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
poll_wait(filp, &tty->write_wait, wait);
/* set bits for operations that won't block */
- if(n_hdlc->rx_buf_list.head)
+ if (n_hdlc->rx_buf_list.head)
mask |= POLLIN | POLLRDNORM; /* readable */
if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= POLLHUP;
- if(tty_hung_up_p(filp))
+ if (tty_hung_up_p(filp))
mask |= POLLHUP;
- if(n_hdlc->tx_free_buf_list.head)
+ if (!tty_is_writelocked(tty) &&
+ n_hdlc->tx_free_buf_list.head)
mask |= POLLOUT | POLLWRNORM; /* writable */
}
return mask;
@@ -861,7 +867,7 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
spin_lock_irqsave(&list->spinlock,flags);
buf->link=NULL;
- if(list->tail)
+ if (list->tail)
list->tail->link = buf;
else
list->head = buf;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 14557a4822c0..6b918b80f73e 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1071,8 +1071,6 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
struct r3964_client_info *pClient;
struct r3964_message *pMsg;
struct r3964_client_message theMsg;
- DECLARE_WAITQUEUE(wait, current);
-
int count;
TRACE_L("read()");
@@ -1086,16 +1084,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
return -EAGAIN;
}
/* block until there is a message: */
- add_wait_queue(&pInfo->read_wait, &wait);
-repeat:
- __set_current_state(TASK_INTERRUPTIBLE);
- pMsg = remove_msg(pInfo, pClient);
- if (!pMsg && !signal_pending(current)) {
- schedule();
- goto repeat;
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&pInfo->read_wait, &wait);
+ wait_event_interruptible(pInfo->read_wait,
+ (pMsg = remove_msg(pInfo, pClient)));
}
/* If we still haven't got a message, we must have been signalled */
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 154f42203b05..038056911934 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -45,6 +45,8 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/bitops.h>
+#include <linux/audit.h>
+#include <linux/file.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -78,6 +80,13 @@ static inline void free_buf(unsigned char *buf)
free_page((unsigned long) buf);
}
+static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
+ unsigned char __user *ptr)
+{
+ tty_audit_add_data(tty, &x, 1);
+ return put_user(x, ptr);
+}
+
/**
* n_tty_set__room - receive space
* @tty: terminal
@@ -1153,6 +1162,7 @@ static int copy_from_read_buf(struct tty_struct *tty,
if (n) {
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
n -= retval;
+ tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
@@ -1279,7 +1289,7 @@ do_it_again:
break;
cs = tty->link->ctrl_status;
tty->link->ctrl_status = 0;
- if (put_user(cs, b++)) {
+ if (tty_put_user(tty, cs, b++)) {
retval = -EFAULT;
b--;
break;
@@ -1321,7 +1331,7 @@ do_it_again:
/* Deal with packet mode. */
if (tty->packet && b == buf) {
- if (put_user(TIOCPKT_DATA, b++)) {
+ if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
retval = -EFAULT;
b--;
break;
@@ -1352,15 +1362,17 @@ do_it_again:
spin_unlock_irqrestore(&tty->read_lock, flags);
if (!eol || (c != __DISABLED_CHAR)) {
- if (put_user(c, b++)) {
+ if (tty_put_user(tty, c, b++)) {
retval = -EFAULT;
b--;
break;
}
nr--;
}
- if (eol)
+ if (eol) {
+ tty_audit_push(tty);
break;
+ }
}
if (retval)
break;
@@ -1538,7 +1550,8 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol
else
tty->minimum_to_wake = 1;
}
- if (tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
+ if (!tty_is_writelocked(tty) &&
+ tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
tty->driver->write_room(tty) > 0)
mask |= POLLOUT | POLLWRNORM;
return mask;
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 204deaa0de80..98dec380af49 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -42,19 +42,12 @@
#define PC 1
#define ATARI 2
-#define COBALT 3
/* select machine configuration */
#if defined(CONFIG_ATARI)
# define MACH ATARI
#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */
-#define MACH PC
-# if defined(CONFIG_COBALT)
-# include <linux/cobalt-nvram.h>
-# define MACH COBALT
-# else
-# define MACH PC
-# endif
+# define MACH PC
#else
# error Cannot build nvram driver for this machine configuration.
#endif
@@ -76,18 +69,6 @@
#endif
-#if MACH == COBALT
-
-#define CHECK_DRIVER_INIT() 1
-
-#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE)
-
-#define mach_check_checksum cobalt_check_checksum
-#define mach_set_checksum cobalt_set_checksum
-#define mach_proc_infos cobalt_proc_infos
-
-#endif
-
#if MACH == ATARI
/* Special parameters for RTC in Atari machines */
@@ -604,177 +585,6 @@ pc_proc_infos(unsigned char *nvram, char *buffer, int *len,
#endif /* MACH == PC */
-#if MACH == COBALT
-
-/* the cobalt CMOS has a wider range of its checksum */
-static int cobalt_check_checksum(void)
-{
- int i;
- unsigned short sum = 0;
- unsigned short expect;
-
- for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
- if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
- continue;
-
- sum += __nvram_read_byte(i);
- }
- expect = __nvram_read_byte(COBT_CMOS_CHECKSUM) << 8 |
- __nvram_read_byte(COBT_CMOS_CHECKSUM+1);
- return ((sum & 0xffff) == expect);
-}
-
-static void cobalt_set_checksum(void)
-{
- int i;
- unsigned short sum = 0;
-
- for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
- if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
- continue;
-
- sum += __nvram_read_byte(i);
- }
-
- __nvram_write_byte(sum >> 8, COBT_CMOS_CHECKSUM);
- __nvram_write_byte(sum & 0xff, COBT_CMOS_CHECKSUM+1);
-}
-
-#ifdef CONFIG_PROC_FS
-
-static int cobalt_proc_infos(unsigned char *nvram, char *buffer, int *len,
- off_t *begin, off_t offset, int size)
-{
- int i;
- unsigned int checksum;
- unsigned int flags;
- char sernum[14];
- char *key = "cNoEbTaWlOtR!";
- unsigned char bto_csum;
-
- spin_lock_irq(&rtc_lock);
- checksum = __nvram_check_checksum();
- spin_unlock_irq(&rtc_lock);
-
- PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
-
- flags = nvram[COBT_CMOS_FLAG_BYTE_0] << 8
- | nvram[COBT_CMOS_FLAG_BYTE_1];
-
- PRINT_PROC("Console: %s\n",
- flags & COBT_CMOS_CONSOLE_FLAG ? "on": "off");
-
- PRINT_PROC("Firmware Debug Messages: %s\n",
- flags & COBT_CMOS_DEBUG_FLAG ? "on": "off");
-
- PRINT_PROC("Auto Prompt: %s\n",
- flags & COBT_CMOS_AUTO_PROMPT_FLAG ? "on": "off");
-
- PRINT_PROC("Shutdown Status: %s\n",
- flags & COBT_CMOS_CLEAN_BOOT_FLAG ? "clean": "dirty");
-
- PRINT_PROC("Hardware Probe: %s\n",
- flags & COBT_CMOS_HW_NOPROBE_FLAG ? "partial": "full");
-
- PRINT_PROC("System Fault: %sdetected\n",
- flags & COBT_CMOS_SYSFAULT_FLAG ? "": "not ");
-
- PRINT_PROC("Panic on OOPS: %s\n",
- flags & COBT_CMOS_OOPSPANIC_FLAG ? "yes": "no");
-
- PRINT_PROC("Delayed Cache Initialization: %s\n",
- flags & COBT_CMOS_DELAY_CACHE_FLAG ? "yes": "no");
-
- PRINT_PROC("Show Logo at Boot: %s\n",
- flags & COBT_CMOS_NOLOGO_FLAG ? "no": "yes");
-
- PRINT_PROC("Boot Method: ");
- switch (nvram[COBT_CMOS_BOOT_METHOD]) {
- case COBT_CMOS_BOOT_METHOD_DISK:
- PRINT_PROC("disk\n");
- break;
-
- case COBT_CMOS_BOOT_METHOD_ROM:
- PRINT_PROC("rom\n");
- break;
-
- case COBT_CMOS_BOOT_METHOD_NET:
- PRINT_PROC("net\n");
- break;
-
- default:
- PRINT_PROC("unknown\n");
- break;
- }
-
- PRINT_PROC("Primary Boot Device: %d:%d\n",
- nvram[COBT_CMOS_BOOT_DEV0_MAJ],
- nvram[COBT_CMOS_BOOT_DEV0_MIN] );
- PRINT_PROC("Secondary Boot Device: %d:%d\n",
- nvram[COBT_CMOS_BOOT_DEV1_MAJ],
- nvram[COBT_CMOS_BOOT_DEV1_MIN] );
- PRINT_PROC("Tertiary Boot Device: %d:%d\n",
- nvram[COBT_CMOS_BOOT_DEV2_MAJ],
- nvram[COBT_CMOS_BOOT_DEV2_MIN] );
-
- PRINT_PROC("Uptime: %d\n",
- nvram[COBT_CMOS_UPTIME_0] << 24 |
- nvram[COBT_CMOS_UPTIME_1] << 16 |
- nvram[COBT_CMOS_UPTIME_2] << 8 |
- nvram[COBT_CMOS_UPTIME_3]);
-
- PRINT_PROC("Boot Count: %d\n",
- nvram[COBT_CMOS_BOOTCOUNT_0] << 24 |
- nvram[COBT_CMOS_BOOTCOUNT_1] << 16 |
- nvram[COBT_CMOS_BOOTCOUNT_2] << 8 |
- nvram[COBT_CMOS_BOOTCOUNT_3]);
-
- /* 13 bytes of serial num */
- for (i=0 ; i<13 ; i++) {
- sernum[i] = nvram[COBT_CMOS_SYS_SERNUM_0 + i];
- }
- sernum[13] = '\0';
-
- checksum = 0;
- for (i=0 ; i<13 ; i++) {
- checksum += sernum[i] ^ key[i];
- }
- checksum = ((checksum & 0x7f) ^ (0xd6)) & 0xff;
-
- PRINT_PROC("Serial Number: %s", sernum);
- if (checksum != nvram[COBT_CMOS_SYS_SERNUM_CSUM]) {
- PRINT_PROC(" (invalid checksum)");
- }
- PRINT_PROC("\n");
-
- PRINT_PROC("Rom Revison: %d.%d.%d\n", nvram[COBT_CMOS_ROM_REV_MAJ],
- nvram[COBT_CMOS_ROM_REV_MIN], nvram[COBT_CMOS_ROM_REV_REV]);
-
- PRINT_PROC("BTO Server: %d.%d.%d.%d", nvram[COBT_CMOS_BTO_IP_0],
- nvram[COBT_CMOS_BTO_IP_1], nvram[COBT_CMOS_BTO_IP_2],
- nvram[COBT_CMOS_BTO_IP_3]);
- bto_csum = nvram[COBT_CMOS_BTO_IP_0] + nvram[COBT_CMOS_BTO_IP_1]
- + nvram[COBT_CMOS_BTO_IP_2] + nvram[COBT_CMOS_BTO_IP_3];
- if (bto_csum != nvram[COBT_CMOS_BTO_IP_CSUM]) {
- PRINT_PROC(" (invalid checksum)");
- }
- PRINT_PROC("\n");
-
- if (flags & COBT_CMOS_VERSION_FLAG
- && nvram[COBT_CMOS_VERSION] >= COBT_CMOS_VER_BTOCODE) {
- PRINT_PROC("BTO Code: 0x%x\n",
- nvram[COBT_CMOS_BTO_CODE_0] << 24 |
- nvram[COBT_CMOS_BTO_CODE_1] << 16 |
- nvram[COBT_CMOS_BTO_CODE_2] << 8 |
- nvram[COBT_CMOS_BTO_CODE_3]);
- }
-
- return 1;
-}
-#endif /* CONFIG_PROC_FS */
-
-#endif /* MACH == COBALT */
-
#if MACH == ATARI
static int
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 3494e3fc44bf..b37e626f4faa 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -213,14 +213,6 @@ static inline void rc_release_io_range(struct riscom_board * const bp)
release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
}
-/* Must be called with enabled interrupts */
-static inline void rc_long_delay(unsigned long delay)
-{
- unsigned long i;
-
- for (i = jiffies + delay; time_after(i,jiffies); ) ;
-}
-
/* Reset and setup CD180 chip */
static void __init rc_init_CD180(struct riscom_board const * bp)
{
@@ -231,7 +223,7 @@ static void __init rc_init_CD180(struct riscom_board const * bp)
rc_wait_CCR(bp); /* Wait for CCR ready */
rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */
sti();
- rc_long_delay(HZ/20); /* Delay 0.05 sec */
+ msleep(50); /* Delay 0.05 sec */
cli();
rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */
rc_out(bp, CD180_GICR, 0); /* Clear all bits */
@@ -280,7 +272,7 @@ static int __init rc_probe(struct riscom_board *bp)
rc_wait_CCR(bp);
rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */
rc_out(bp, CD180_IER, IER_TXRDY); /* Enable tx empty intr */
- rc_long_delay(HZ/20);
+ msleep(50);
irqs = probe_irq_off(irqs);
val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */
val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index a3fd7e7ba5a9..0270080ff0c0 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1702,7 +1702,8 @@ static int rp_write(struct tty_struct *tty,
if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
return 0;
- mutex_lock_interruptible(&info->write_mtx);
+ if (mutex_lock_interruptible(&info->write_mtx))
+ return -ERESTARTSYS;
#ifdef ROCKET_DEBUG_WRITE
printk(KERN_INFO "rp_write %d chars...", count);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 20380a2c4dee..22cf7aa56cc4 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1159,7 +1159,8 @@ static void rtc_dropped_irq(unsigned long data)
spin_unlock_irq(&rtc_lock);
- printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
+ if (printk_ratelimit())
+ printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
/* Now we have new data */
wake_up_interruptible(&rtc_wait);
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index a69f094d1ed3..d63f5ccc29e6 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -20,6 +20,7 @@
#include <asm/uaccess.h>
+#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/consolemap.h>
#include <linux/selection.h>
@@ -34,6 +35,7 @@ extern void poke_blanked_console(void);
/* Variables for selection control. */
/* Use a dynamic buffer, instead of static (Dec 1994) */
struct vc_data *sel_cons; /* must not be deallocated */
+static int use_unicode;
static volatile int sel_start = -1; /* cleared by clear_selection */
static int sel_end;
static int sel_buffer_lth;
@@ -54,10 +56,11 @@ static inline void highlight_pointer(const int where)
complement_pos(sel_cons, where);
}
-static unsigned char
+static u16
sel_pos(int n)
{
- return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
+ return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
+ use_unicode);
}
/* remove the current selection highlight, if any,
@@ -86,8 +89,8 @@ static u32 inwordLut[8]={
0xFF7FFFFF /* latin-1 accented letters, not division sign */
};
-static inline int inword(const unsigned char c) {
- return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+static inline int inword(const u16 c) {
+ return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
}
/* set inwordLut contents. Invoked by ioctl(). */
@@ -108,13 +111,36 @@ static inline unsigned short limit(const unsigned short v, const unsigned short
return (v > u) ? u : v;
}
+/* stores the char in UTF8 and returns the number of bytes used (1-3) */
+static int store_utf8(u16 c, char *p)
+{
+ if (c < 0x80) {
+ /* 0******* */
+ p[0] = c;
+ return 1;
+ } else if (c < 0x800) {
+ /* 110***** 10****** */
+ p[0] = 0xc0 | (c >> 6);
+ p[1] = 0x80 | (c & 0x3f);
+ return 2;
+ } else {
+ /* 1110**** 10****** 10****** */
+ p[0] = 0xe0 | (c >> 12);
+ p[1] = 0x80 | ((c >> 6) & 0x3f);
+ p[2] = 0x80 | (c & 0x3f);
+ return 3;
+ }
+}
+
/* set the current selection. Invoked by ioctl() or by kernel code. */
int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
{
struct vc_data *vc = vc_cons[fg_console].d;
int sel_mode, new_sel_start, new_sel_end, spc;
char *bp, *obp;
- int i, ps, pe;
+ int i, ps, pe, multiplier;
+ u16 c;
+ struct kbd_struct *kbd = kbd_table + fg_console;
poke_blanked_console();
@@ -158,6 +184,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
clear_selection();
sel_cons = vc_cons[fg_console].d;
}
+ use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
switch (sel_mode)
{
@@ -240,7 +267,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
sel_end = new_sel_end;
/* Allocate a new buffer before freeing the old one ... */
- bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
+ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */
+ bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
@@ -251,8 +279,12 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
obp = bp;
for (i = sel_start; i <= sel_end; i += 2) {
- *bp = sel_pos(i);
- if (!isspace(*bp++))
+ c = sel_pos(i);
+ if (use_unicode)
+ bp += store_utf8(c, bp);
+ else
+ *bp++ = c;
+ if (!isspace(c))
obp = bp;
if (! ((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 3ef593a9015f..73037a4d3c50 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -885,53 +885,6 @@ found:
return IRQ_HANDLED;
}
-/* External camera command (exported to the motion eye v4l driver) */
-int sonypi_camera_command(int command, u8 value)
-{
- if (!camera)
- return -EIO;
-
- mutex_lock(&sonypi_device.lock);
-
- switch (command) {
- case SONYPI_COMMAND_SETCAMERA:
- if (value)
- sonypi_camera_on();
- else
- sonypi_camera_off();
- break;
- case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
- sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
- break;
- case SONYPI_COMMAND_SETCAMERACONTRAST:
- sonypi_set(SONYPI_CAMERA_CONTRAST, value);
- break;
- case SONYPI_COMMAND_SETCAMERAHUE:
- sonypi_set(SONYPI_CAMERA_HUE, value);
- break;
- case SONYPI_COMMAND_SETCAMERACOLOR:
- sonypi_set(SONYPI_CAMERA_COLOR, value);
- break;
- case SONYPI_COMMAND_SETCAMERASHARPNESS:
- sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
- break;
- case SONYPI_COMMAND_SETCAMERAPICTURE:
- sonypi_set(SONYPI_CAMERA_PICTURE, value);
- break;
- case SONYPI_COMMAND_SETCAMERAAGC:
- sonypi_set(SONYPI_CAMERA_AGC, value);
- break;
- default:
- printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n",
- command);
- break;
- }
- mutex_unlock(&sonypi_device.lock);
- return 0;
-}
-
-EXPORT_SYMBOL(sonypi_camera_command);
-
static int sonypi_misc_fasync(int fd, struct file *filp, int on)
{
int retval;
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index baf7234b6e66..455855631aef 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -345,18 +345,6 @@ static inline void sx_release_io_range(struct specialix_board * bp)
}
-/* Must be called with enabled interrupts */
-/* Ugly. Very ugly. Don't use this for anything else than initialization
- code */
-static inline void sx_long_delay(unsigned long delay)
-{
- unsigned long i;
-
- for (i = jiffies + delay; time_after(i, jiffies); ) ;
-}
-
-
-
/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
static int sx_set_irq ( struct specialix_board *bp)
{
@@ -397,7 +385,7 @@ static int sx_init_CD186x(struct specialix_board * bp)
spin_lock_irqsave(&bp->lock, flags);
sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */
spin_unlock_irqrestore(&bp->lock, flags);
- sx_long_delay(HZ/20); /* Delay 0.05 sec */
+ msleep(50); /* Delay 0.05 sec */
spin_lock_irqsave(&bp->lock, flags);
sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */
sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */
@@ -533,7 +521,7 @@ static int sx_probe(struct specialix_board *bp)
sx_wait_CCR(bp);
sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
- sx_long_delay(HZ/20);
+ msleep(50);
irqs = probe_irq_off(irqs);
dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 8c73ccb8830f..93d0bb8b4c0f 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1788,7 +1788,6 @@ static void stl_offintr(struct work_struct *work)
if (tty == NULL)
return;
- lock_kernel();
if (test_bit(ASYI_TXLOW, &portp->istate))
tty_wakeup(tty);
@@ -1802,7 +1801,6 @@ static void stl_offintr(struct work_struct *work)
if (portp->flags & ASYNC_CHECK_CD)
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
}
- unlock_kernel();
}
/*****************************************************************************/
@@ -2357,9 +2355,6 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev,
if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
goto err;
- dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
- pdev->vendor, pdev->device, pdev->class);
-
retval = pci_enable_device(pdev);
if (retval)
goto err;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index f02a0795983f..f53e51ddb9d7 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -160,8 +160,6 @@ typedef struct _DMABUFFERENTRY
#define IO_PIN_SHUTDOWN_LIMIT 100
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
struct _input_signal_events {
int ri_up;
int ri_down;
@@ -3064,12 +3062,6 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio
printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
tty->driver->name );
- /* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
mgsl_change_params(info);
/* Handle transition to B0 status */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 02b49bc00028..428b514201f4 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -144,8 +144,6 @@ MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable")
/*
* tty support and callbacks
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
static struct tty_driver *serial_driver;
static int open(struct tty_struct *tty, struct file * filp);
@@ -823,12 +821,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
DBGINFO(("%s set_termios\n", tty->driver->name));
- /* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_params(info);
/* Handle transition to B0 status */
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ef93d055bdd7..a65407b32079 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -135,8 +135,6 @@ typedef struct _SCADESC_EX
#define IO_PIN_SHUTDOWN_LIMIT 100
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
struct _input_signal_events {
int ri_up;
int ri_down;
@@ -927,12 +925,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
tty->driver->name );
- /* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_params(info);
/* Handle transition to B0 status */
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index dc4e1ff7f56f..8f3f7620f95a 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -2,11 +2,9 @@
# TPM device configuration
#
-menu "TPM devices"
- depends on HAS_IOMEM
-
-config TCG_TPM
+menuconfig TCG_TPM
tristate "TPM Hardware Support"
+ depends on HAS_IOMEM
depends on EXPERIMENTAL
---help---
If you have a TPM security chip in your system, which
@@ -21,9 +19,11 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
+if TCG_TPM
+
config TCG_TIS
tristate "TPM Interface Specification 1.2 Interface"
- depends on TCG_TPM && PNPACPI
+ depends on PNPACPI
---help---
If you have a TPM security chip that is compliant with the
TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -32,7 +32,7 @@ config TCG_TIS
config TCG_NSC
tristate "National Semiconductor TPM Interface"
- depends on TCG_TPM && PNPACPI
+ depends on PNPACPI
---help---
If you have a TPM security chip from National Semiconductor
say Yes and it will be accessible from within Linux. To
@@ -41,7 +41,6 @@ config TCG_NSC
config TCG_ATMEL
tristate "Atmel TPM Interface"
- depends on TCG_TPM
---help---
If you have a TPM security chip from Atmel say Yes and it
will be accessible from within Linux. To compile this driver
@@ -49,7 +48,7 @@ config TCG_ATMEL
config TCG_INFINEON
tristate "Infineon Technologies TPM Interface"
- depends on TCG_TPM && PNPACPI
+ depends on PNPACPI
---help---
If you have a TPM security chip from Infineon Technologies
(either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
@@ -59,5 +58,4 @@ config TCG_INFINEON
Further information on this driver and the supported hardware
can be found at http://www.prosec.rub.de/tpm
-endmenu
-
+endif # TCG_TPM
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
new file mode 100644
index 000000000000..d222012c1b0c
--- /dev/null
+++ b/drivers/char/tty_audit.c
@@ -0,0 +1,345 @@
+/*
+ * Creating audit events from TTY input.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved. This copyrighted
+ * material is made available to anyone wishing to use, modify, copy, or
+ * redistribute it subject to the terms and conditions of the GNU General
+ * Public License v.2.
+ *
+ * Authors: Miloslav Trmac <mitr@redhat.com>
+ */
+
+#include <linux/audit.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+
+struct tty_audit_buf {
+ atomic_t count;
+ struct mutex mutex; /* Protects all data below */
+ int major, minor; /* The TTY which the data is from */
+ unsigned icanon:1;
+ size_t valid;
+ unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */
+};
+
+static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
+ int icanon)
+{
+ struct tty_audit_buf *buf;
+
+ buf = kmalloc(sizeof (*buf), GFP_KERNEL);
+ if (!buf)
+ goto err;
+ if (PAGE_SIZE != N_TTY_BUF_SIZE)
+ buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ else
+ buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!buf->data)
+ goto err_buf;
+ atomic_set(&buf->count, 1);
+ mutex_init(&buf->mutex);
+ buf->major = major;
+ buf->minor = minor;
+ buf->icanon = icanon;
+ buf->valid = 0;
+ return buf;
+
+err_buf:
+ kfree(buf);
+err:
+ return NULL;
+}
+
+static void tty_audit_buf_free(struct tty_audit_buf *buf)
+{
+ WARN_ON(buf->valid != 0);
+ if (PAGE_SIZE != N_TTY_BUF_SIZE)
+ kfree(buf->data);
+ else
+ free_page((unsigned long)buf->data);
+ kfree(buf);
+}
+
+static void tty_audit_buf_put(struct tty_audit_buf *buf)
+{
+ if (atomic_dec_and_test(&buf->count))
+ tty_audit_buf_free(buf);
+}
+
+/**
+ * tty_audit_buf_push - Push buffered data out
+ *
+ * Generate an audit message from the contents of @buf, which is owned by
+ * @tsk with @loginuid. @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+ struct tty_audit_buf *buf)
+{
+ struct audit_buffer *ab;
+
+ if (buf->valid == 0)
+ return;
+ if (audit_enabled == 0)
+ return;
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+ if (ab) {
+ char name[sizeof(tsk->comm)];
+
+ audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
+ "minor=%d comm=", tsk->pid, tsk->uid,
+ loginuid, buf->major, buf->minor);
+ get_task_comm(name, tsk);
+ audit_log_untrustedstring(ab, name);
+ audit_log_format(ab, " data=");
+ audit_log_n_untrustedstring(ab, buf->valid, buf->data);
+ audit_log_end(ab);
+ }
+ buf->valid = 0;
+}
+
+/**
+ * tty_audit_buf_push_current - Push buffered data out
+ *
+ * Generate an audit message from the contents of @buf, which is owned by
+ * the current task. @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
+{
+ tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
+ buf);
+}
+
+/**
+ * tty_audit_exit - Handle a task exit
+ *
+ * Make sure all buffered data is written out and deallocate the buffer.
+ * Only needs to be called if current->signal->tty_audit_buf != %NULL.
+ */
+void tty_audit_exit(void)
+{
+ struct tty_audit_buf *buf;
+
+ spin_lock_irq(&current->sighand->siglock);
+ buf = current->signal->tty_audit_buf;
+ current->signal->tty_audit_buf = NULL;
+ spin_unlock_irq(&current->sighand->siglock);
+ if (!buf)
+ return;
+
+ mutex_lock(&buf->mutex);
+ tty_audit_buf_push_current(buf);
+ mutex_unlock(&buf->mutex);
+
+ tty_audit_buf_put(buf);
+}
+
+/**
+ * tty_audit_fork - Copy TTY audit state for a new task
+ *
+ * Set up TTY audit state in @sig from current. @sig needs no locking.
+ */
+void tty_audit_fork(struct signal_struct *sig)
+{
+ spin_lock_irq(&current->sighand->siglock);
+ sig->audit_tty = current->signal->audit_tty;
+ spin_unlock_irq(&current->sighand->siglock);
+ sig->tty_audit_buf = NULL;
+}
+
+/**
+ * tty_audit_push_task - Flush task's pending audit data
+ */
+void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+ struct tty_audit_buf *buf;
+
+ spin_lock_irq(&tsk->sighand->siglock);
+ buf = tsk->signal->tty_audit_buf;
+ if (buf)
+ atomic_inc(&buf->count);
+ spin_unlock_irq(&tsk->sighand->siglock);
+ if (!buf)
+ return;
+
+ mutex_lock(&buf->mutex);
+ tty_audit_buf_push(tsk, loginuid, buf);
+ mutex_unlock(&buf->mutex);
+
+ tty_audit_buf_put(buf);
+}
+
+/**
+ * tty_audit_buf_get - Get an audit buffer.
+ *
+ * Get an audit buffer for @tty, allocate it if necessary. Return %NULL
+ * if TTY auditing is disabled or out of memory. Otherwise, return a new
+ * reference to the buffer.
+ */
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+{
+ struct tty_audit_buf *buf, *buf2;
+
+ buf = NULL;
+ buf2 = NULL;
+ spin_lock_irq(&current->sighand->siglock);
+ if (likely(!current->signal->audit_tty))
+ goto out;
+ buf = current->signal->tty_audit_buf;
+ if (buf) {
+ atomic_inc(&buf->count);
+ goto out;
+ }
+ spin_unlock_irq(&current->sighand->siglock);
+
+ buf2 = tty_audit_buf_alloc(tty->driver->major,
+ tty->driver->minor_start + tty->index,
+ tty->icanon);
+ if (buf2 == NULL) {
+ audit_log_lost("out of memory in TTY auditing");
+ return NULL;
+ }
+
+ spin_lock_irq(&current->sighand->siglock);
+ if (!current->signal->audit_tty)
+ goto out;
+ buf = current->signal->tty_audit_buf;
+ if (!buf) {
+ current->signal->tty_audit_buf = buf2;
+ buf = buf2;
+ buf2 = NULL;
+ }
+ atomic_inc(&buf->count);
+ /* Fall through */
+ out:
+ spin_unlock_irq(&current->sighand->siglock);
+ if (buf2)
+ tty_audit_buf_free(buf2);
+ return buf;
+}
+
+/**
+ * tty_audit_add_data - Add data for TTY auditing.
+ *
+ * Audit @data of @size from @tty, if necessary.
+ */
+void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+ size_t size)
+{
+ struct tty_audit_buf *buf;
+ int major, minor;
+
+ if (unlikely(size == 0))
+ return;
+
+ buf = tty_audit_buf_get(tty);
+ if (!buf)
+ return;
+
+ mutex_lock(&buf->mutex);
+ major = tty->driver->major;
+ minor = tty->driver->minor_start + tty->index;
+ if (buf->major != major || buf->minor != minor
+ || buf->icanon != tty->icanon) {
+ tty_audit_buf_push_current(buf);
+ buf->major = major;
+ buf->minor = minor;
+ buf->icanon = tty->icanon;
+ }
+ do {
+ size_t run;
+
+ run = N_TTY_BUF_SIZE - buf->valid;
+ if (run > size)
+ run = size;
+ memcpy(buf->data + buf->valid, data, run);
+ buf->valid += run;
+ data += run;
+ size -= run;
+ if (buf->valid == N_TTY_BUF_SIZE)
+ tty_audit_buf_push_current(buf);
+ } while (size != 0);
+ mutex_unlock(&buf->mutex);
+ tty_audit_buf_put(buf);
+}
+
+/**
+ * tty_audit_push - Push buffered data out
+ *
+ * Make sure no audit data is pending for @tty on the current process.
+ */
+void tty_audit_push(struct tty_struct *tty)
+{
+ struct tty_audit_buf *buf;
+
+ spin_lock_irq(&current->sighand->siglock);
+ if (likely(!current->signal->audit_tty)) {
+ spin_unlock_irq(&current->sighand->siglock);
+ return;
+ }
+ buf = current->signal->tty_audit_buf;
+ if (buf)
+ atomic_inc(&buf->count);
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (buf) {
+ int major, minor;
+
+ major = tty->driver->major;
+ minor = tty->driver->minor_start + tty->index;
+ mutex_lock(&buf->mutex);
+ if (buf->major == major && buf->minor == minor)
+ tty_audit_buf_push_current(buf);
+ mutex_unlock(&buf->mutex);
+ tty_audit_buf_put(buf);
+ }
+}
+
+/**
+ * tty_audit_opening - A TTY is being opened.
+ *
+ * As a special hack, tasks that close all their TTYs and open new ones
+ * are assumed to be system daemons (e.g. getty) and auditing is
+ * automatically disabled for them.
+ */
+void tty_audit_opening(void)
+{
+ int disable;
+
+ disable = 1;
+ spin_lock_irq(&current->sighand->siglock);
+ if (current->signal->audit_tty == 0)
+ disable = 0;
+ spin_unlock_irq(&current->sighand->siglock);
+ if (!disable)
+ return;
+
+ task_lock(current);
+ if (current->files) {
+ struct fdtable *fdt;
+ unsigned i;
+
+ /*
+ * We don't take a ref to the file, so we must hold ->file_lock
+ * instead.
+ */
+ spin_lock(&current->files->file_lock);
+ fdt = files_fdtable(current->files);
+ for (i = 0; i < fdt->max_fds; i++) {
+ struct file *filp;
+
+ filp = fcheck_files(current->files, i);
+ if (filp && is_tty(filp)) {
+ disable = 0;
+ break;
+ }
+ }
+ spin_unlock(&current->files->file_lock);
+ }
+ task_unlock(current);
+ if (!disable)
+ return;
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->signal->audit_tty = 0;
+ spin_unlock_irq(&current->sighand->siglock);
+}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a96f26a63fa2..de37ebc3a4cf 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1503,6 +1503,15 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
+/**
+ * is_tty - checker whether file is a TTY
+ */
+int is_tty(struct file *filp)
+{
+ return filp->f_op->read == tty_read
+ || filp->f_op->read == hung_up_tty_read;
+}
+
static void session_clear_tty(struct pid *session)
{
struct task_struct *p;
@@ -1726,6 +1735,23 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
return i;
}
+void tty_write_unlock(struct tty_struct *tty)
+{
+ mutex_unlock(&tty->atomic_write_lock);
+ wake_up_interruptible(&tty->write_wait);
+}
+
+int tty_write_lock(struct tty_struct *tty, int ndelay)
+{
+ if (!mutex_trylock(&tty->atomic_write_lock)) {
+ if (ndelay)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ return -ERESTARTSYS;
+ }
+ return 0;
+}
+
/*
* Split writes up in sane blocksizes to avoid
* denial-of-service type attacks
@@ -1737,13 +1763,12 @@ static inline ssize_t do_tty_write(
const char __user *buf,
size_t count)
{
- ssize_t ret = 0, written = 0;
+ ssize_t ret, written = 0;
unsigned int chunk;
- /* FIXME: O_NDELAY ... */
- if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
- return -ERESTARTSYS;
- }
+ ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
+ if (ret < 0)
+ return ret;
/*
* We chunk up writes into a temporary buffer. This
@@ -1776,8 +1801,8 @@ static inline ssize_t do_tty_write(
buf = kmalloc(chunk, GFP_KERNEL);
if (!buf) {
- mutex_unlock(&tty->atomic_write_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
kfree(tty->write_buf);
tty->write_cnt = chunk;
@@ -1812,7 +1837,8 @@ static inline ssize_t do_tty_write(
inode->i_mtime = current_fs_time(inode->i_sb);
ret = written;
}
- mutex_unlock(&tty->atomic_write_lock);
+out:
+ tty_write_unlock(tty);
return ret;
}
@@ -2016,11 +2042,9 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*ltp_loc) {
- ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
- GFP_KERNEL);
+ ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!ltp)
goto free_mem_out;
- memset(ltp, 0, sizeof(struct ktermios));
}
if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -2049,11 +2073,9 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*o_ltp_loc) {
- o_ltp = (struct ktermios *)
- kmalloc(sizeof(struct ktermios), GFP_KERNEL);
+ o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_ltp)
goto free_mem_out;
- memset(o_ltp, 0, sizeof(struct ktermios));
}
/*
@@ -2660,6 +2682,7 @@ got_driver:
__proc_set_tty(current, tty);
spin_unlock_irq(&current->sighand->siglock);
mutex_unlock(&tty_mutex);
+ tty_audit_opening();
return 0;
}
@@ -2722,8 +2745,10 @@ static int ptmx_open(struct inode * inode, struct file * filp)
check_tty_count(tty, "tty_open");
retval = ptm_driver->open(tty, filp);
- if (!retval)
+ if (!retval) {
+ tty_audit_opening();
return 0;
+ }
out1:
release_dev(filp);
return retval;
@@ -3163,14 +3188,13 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
static int send_break(struct tty_struct *tty, unsigned int duration)
{
- if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ if (tty_write_lock(tty, 0) < 0)
return -EINTR;
tty->driver->break_ctl(tty, -1);
- if (!signal_pending(current)) {
+ if (!signal_pending(current))
msleep_interruptible(duration);
- }
tty->driver->break_ctl(tty, 0);
- mutex_unlock(&tty->atomic_write_lock);
+ tty_write_unlock(tty);
if (signal_pending(current))
return -EINTR;
return 0;
@@ -3739,9 +3763,8 @@ struct tty_driver *alloc_tty_driver(int lines)
{
struct tty_driver *driver;
- driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
+ driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
if (driver) {
- memset(driver, 0, sizeof(struct tty_driver));
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines;
/* later we'll move allocation of tables here */
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index fd471cb3338f..3423e9ee6481 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -52,8 +52,6 @@
void tty_wait_until_sent(struct tty_struct * tty, long timeout)
{
- DECLARE_WAITQUEUE(wait, current);
-
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
char buf[64];
@@ -61,26 +59,13 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout)
#endif
if (!tty->driver->chars_in_buffer)
return;
- add_wait_queue(&tty->write_wait, &wait);
if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
- do {
-#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
- printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
- tty->driver->chars_in_buffer(tty));
-#endif
- set_current_state(TASK_INTERRUPTIBLE);
- if (signal_pending(current))
- goto stop_waiting;
- if (!tty->driver->chars_in_buffer(tty))
- break;
- timeout = schedule_timeout(timeout);
- } while (timeout);
+ if (wait_event_interruptible_timeout(tty->write_wait,
+ !tty->driver->chars_in_buffer(tty), timeout))
+ return;
if (tty->driver->wait_until_sent)
tty->driver->wait_until_sent(tty, timeout);
-stop_waiting:
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
}
EXPORT_SYMBOL(tty_wait_until_sent);
@@ -276,13 +261,12 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed
termios->c_cflag |= (baud_bits[i] << IBSHIFT);
ifound = i;
}
- }
- while(++i < n_baud_table);
+ } while (++i < n_baud_table);
if (ofound == -1)
termios->c_cflag |= BOTHER;
/* Set exact input bits only if the input and output differ or the
user already did */
- if (ifound == -1 && (ibaud != obaud || ibinput))
+ if (ifound == -1 && (ibaud != obaud || ibinput))
termios->c_cflag |= (BOTHER << IBSHIFT);
}
@@ -575,7 +559,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
return -EFAULT;
mutex_lock(&tty->termios_mutex);
- termios = *tty->termios;
+ termios = *tty->termios;
termios.c_cc[VERASE] = tmp.sg_erase;
termios.c_cc[VKILL] = tmp.sg_kill;
set_sgflags(&termios, tmp.sg_flags);
@@ -667,7 +651,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
return 0;
}
- if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ if (tty_write_lock(tty, 0) < 0)
return -ERESTARTSYS;
if (was_stopped)
@@ -675,7 +659,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
tty->driver->write(tty, &ch, 1);
if (was_stopped)
stop_tty(tty);
- mutex_unlock(&tty->atomic_write_lock);
+ tty_write_unlock(tty);
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 13faf8d17482..db57277117bb 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -873,12 +873,12 @@ free_op:
}
const struct file_operations viotap_fops = {
- owner: THIS_MODULE,
- read: viotap_read,
- write: viotap_write,
- ioctl: viotap_ioctl,
- open: viotap_open,
- release: viotap_release,
+ .owner = THIS_MODULE,
+ .read = viotap_read,
+ .write = viotap_write,
+ .ioctl = viotap_ioctl,
+ .open = viotap_open,
+ .release = viotap_release,
};
/* Handle interrupt events for tape */
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6650ae1c088f..edb7002a3216 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -729,10 +729,9 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
/* although the numbers above are not valid since long ago, the
point is still up-to-date and the comment still has its value
even if only as a historical artifact. --mj, July 1998 */
- vc = kmalloc(sizeof(struct vc_data), GFP_KERNEL);
+ vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
if (!vc)
return -ENOMEM;
- memset(vc, 0, sizeof(*vc));
vc_cons[currcons].d = vc;
INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
visual_init(vc, currcons, 1);
@@ -1991,8 +1990,7 @@ static int is_double_width(uint32_t ucs)
{ 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
{ 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
};
- return bisearch(ucs, double_width,
- sizeof(double_width) / sizeof(*double_width) - 1);
+ return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
}
/* acquires console_sem */
@@ -2989,8 +2987,24 @@ static int con_is_graphics(const struct consw *csw, int first, int last)
return retval;
}
-static int unbind_con_driver(const struct consw *csw, int first, int last,
- int deflt)
+/**
+ * unbind_con_driver - unbind a console driver
+ * @csw: pointer to console driver to unregister
+ * @first: first in range of consoles that @csw should be unbound from
+ * @last: last in range of consoles that @csw should be unbound from
+ * @deflt: should next bound console driver be default after @csw is unbound?
+ *
+ * To unbind a driver from all possible consoles, pass 0 as @first and
+ * %MAX_NR_CONSOLES as @last.
+ *
+ * @deflt controls whether the console that ends up replacing @csw should be
+ * the default console.
+ *
+ * RETURNS:
+ * -ENODEV if @csw isn't a registered console driver or can't be unregistered
+ * or 0 on success.
+ */
+int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
{
struct module *owner = csw->owner;
const struct consw *defcsw = NULL;
@@ -3075,6 +3089,7 @@ err:
return retval;
}
+EXPORT_SYMBOL(unbind_con_driver);
static int vt_bind(struct con_driver *con)
{
@@ -3491,9 +3506,6 @@ void do_blank_screen(int entering_gfx)
}
return;
}
- if (blank_state != blank_normal_wait)
- return;
- blank_state = blank_off;
/* entering graphics mode? */
if (entering_gfx) {
@@ -3501,10 +3513,15 @@ void do_blank_screen(int entering_gfx)
save_screen(vc);
vc->vc_sw->con_blank(vc, -1, 1);
console_blanked = fg_console + 1;
+ blank_state = blank_off;
set_origin(vc);
return;
}
+ if (blank_state != blank_normal_wait)
+ return;
+ blank_state = blank_off;
+
/* don't blank graphics */
if (vc->vc_mode != KD_TEXT) {
console_blanked = fg_console + 1;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 53f5538c0c05..2f48ba329961 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -187,6 +187,15 @@ config PNX4008_WATCHDOG
Say N if you are unsure.
+# AVR32 Architecture
+
+config AT32AP700X_WDT
+ tristate "AT32AP700x watchdog"
+ depends on WATCHDOG && CPU_AT32AP7000
+ help
+ Watchdog timer embedded into AT32AP700x devices. This will reboot
+ your system when the timeout is reached.
+
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index d90f649038c2..3907ec04a4e5 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -36,6 +36,9 @@ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
+# AVR32 Architecture
+obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
+
# X86 (i386 + ia64 + x86_64) Architecture
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
diff --git a/drivers/char/watchdog/at32ap700x_wdt.c b/drivers/char/watchdog/at32ap700x_wdt.c
new file mode 100644
index 000000000000..54a516169d07
--- /dev/null
+++ b/drivers/char/watchdog/at32ap700x_wdt.c
@@ -0,0 +1,386 @@
+/*
+ * Watchdog driver for Atmel AT32AP700X devices
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#define TIMEOUT_MIN 1
+#define TIMEOUT_MAX 2
+#define TIMEOUT_DEFAULT TIMEOUT_MAX
+
+/* module parameters */
+static int timeout = TIMEOUT_DEFAULT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+ "Timeout value. Limited to be 1 or 2 seconds. (default="
+ __MODULE_STRING(TIMEOUT_DEFAULT) ")");
+
+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) ")");
+
+/* Watchdog registers and write/read macro */
+#define WDT_CTRL 0x00
+#define WDT_CTRL_EN 0
+#define WDT_CTRL_PSEL 8
+#define WDT_CTRL_KEY 24
+
+#define WDT_CLR 0x04
+
+#define WDT_BIT(name) (1 << WDT_##name)
+#define WDT_BF(name, value) ((value) << WDT_##name)
+
+#define wdt_readl(dev, reg) \
+ __raw_readl((dev)->regs + WDT_##reg)
+#define wdt_writel(dev, reg, value) \
+ __raw_writel((value), (dev)->regs + WDT_##reg)
+
+struct wdt_at32ap700x {
+ void __iomem *regs;
+ spinlock_t io_lock;
+ int timeout;
+ unsigned long users;
+ struct miscdevice miscdev;
+};
+
+static struct wdt_at32ap700x *wdt;
+static char expect_release;
+
+/*
+ * Disable the watchdog.
+ */
+static inline void at32_wdt_stop(void)
+{
+ unsigned long psel;
+
+ spin_lock(&wdt->io_lock);
+ psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f);
+ wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55));
+ wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa));
+ spin_unlock(&wdt->io_lock);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static inline void at32_wdt_start(void)
+{
+ /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */
+ unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe;
+
+ spin_lock(&wdt->io_lock);
+ wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
+ | WDT_BF(CTRL_PSEL, psel)
+ | WDT_BF(CTRL_KEY, 0x55));
+ wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
+ | WDT_BF(CTRL_PSEL, psel)
+ | WDT_BF(CTRL_KEY, 0xaa));
+ spin_unlock(&wdt->io_lock);
+}
+
+/*
+ * Pat the watchdog timer.
+ */
+static inline void at32_wdt_pat(void)
+{
+ spin_lock(&wdt->io_lock);
+ wdt_writel(wdt, CLR, 0x42);
+ spin_unlock(&wdt->io_lock);
+}
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at32_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(1, &wdt->users))
+ return -EBUSY;
+
+ at32_wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ */
+static int at32_wdt_close(struct inode *inode, struct file *file)
+{
+ if (expect_release == 42) {
+ at32_wdt_stop();
+ } else {
+ dev_dbg(wdt->miscdev.parent,
+ "Unexpected close, not stopping watchdog!\n");
+ at32_wdt_pat();
+ }
+ clear_bit(1, &wdt->users);
+ expect_release = 0;
+ return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at32_wdt_settimeout(int time)
+{
+ /*
+ * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is
+ * 2 ^ 16 allowing up to 2 seconds timeout.
+ */
+ if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX))
+ return -EINVAL;
+
+ /*
+ * Set new watchdog time. It will be used when at32_wdt_start() is
+ * called.
+ */
+ wdt->timeout = time;
+ return 0;
+}
+
+static struct watchdog_info at32_wdt_info = {
+ .identity = "at32ap700x watchdog",
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at32_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENOTTY;
+ int time;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+
+ switch (cmd) {
+ case WDIOC_KEEPALIVE:
+ at32_wdt_pat();
+ ret = 0;
+ break;
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user(argp, &at32_wdt_info,
+ sizeof(at32_wdt_info)) ? -EFAULT : 0;
+ break;
+ case WDIOC_SETTIMEOUT:
+ ret = get_user(time, p);
+ if (ret)
+ break;
+ ret = at32_wdt_settimeout(time);
+ if (ret)
+ break;
+ /* Enable new time value */
+ at32_wdt_start();
+ /* fall through */
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(wdt->timeout, p);
+ break;
+ case WDIOC_GETSTATUS: /* fall through */
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(0, p);
+ break;
+ case WDIOC_SETOPTIONS:
+ ret = get_user(time, p);
+ if (ret)
+ break;
+ if (time & WDIOS_DISABLECARD)
+ at32_wdt_stop();
+ if (time & WDIOS_ENABLECARD)
+ at32_wdt_start();
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static ssize_t at32_wdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /*
+ * note: just in case someone wrote the magic
+ * character five months ago...
+ */
+ expect_release = 0;
+
+ /*
+ * scan to see whether or not we got the magic
+ * character
+ */
+ for (i = 0; i != len; i++) {
+ char c;
+ if (get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_release = 42;
+ }
+ }
+ /* someone wrote to us, we should pat the watchdog */
+ at32_wdt_pat();
+ }
+ return len;
+}
+
+static const struct file_operations at32_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = at32_wdt_ioctl,
+ .open = at32_wdt_open,
+ .release = at32_wdt_close,
+ .write = at32_wdt_write,
+};
+
+static int __init at32_wdt_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+ int ret;
+
+ if (wdt) {
+ dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n");
+ return -EBUSY;
+ }
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_dbg(&pdev->dev, "missing mmio resource\n");
+ return -ENXIO;
+ }
+
+ wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL);
+ if (!wdt) {
+ dev_dbg(&pdev->dev, "no memory for wdt structure\n");
+ return -ENOMEM;
+ }
+
+ wdt->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!wdt->regs) {
+ ret = -ENOMEM;
+ dev_dbg(&pdev->dev, "could not map I/O memory\n");
+ goto err_free;
+ }
+ spin_lock_init(&wdt->io_lock);
+ wdt->users = 0;
+ wdt->miscdev.minor = WATCHDOG_MINOR;
+ wdt->miscdev.name = "watchdog";
+ wdt->miscdev.fops = &at32_wdt_fops;
+
+ if (at32_wdt_settimeout(timeout)) {
+ at32_wdt_settimeout(TIMEOUT_DEFAULT);
+ dev_dbg(&pdev->dev,
+ "default timeout invalid, set to %d sec.\n",
+ TIMEOUT_DEFAULT);
+ }
+
+ ret = misc_register(&wdt->miscdev);
+ if (ret) {
+ dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
+ goto err_iounmap;
+ }
+
+ platform_set_drvdata(pdev, wdt);
+ wdt->miscdev.parent = &pdev->dev;
+ dev_info(&pdev->dev,
+ "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
+ wdt->regs, wdt->timeout, nowayout);
+
+ return 0;
+
+err_iounmap:
+ iounmap(wdt->regs);
+err_free:
+ kfree(wdt);
+ wdt = NULL;
+ return ret;
+}
+
+static int __exit at32_wdt_remove(struct platform_device *pdev)
+{
+ if (wdt && platform_get_drvdata(pdev) == wdt) {
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ at32_wdt_stop();
+
+ misc_deregister(&wdt->miscdev);
+ iounmap(wdt->regs);
+ kfree(wdt);
+ wdt = NULL;
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+static void at32_wdt_shutdown(struct platform_device *pdev)
+{
+ at32_wdt_stop();
+}
+
+#ifdef CONFIG_PM
+static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ at32_wdt_stop();
+ return 0;
+}
+
+static int at32_wdt_resume(struct platform_device *pdev)
+{
+ if (wdt->users)
+ at32_wdt_start();
+ return 0;
+}
+#else
+#define at32_wdt_suspend NULL
+#define at32_wdt_resume NULL
+#endif
+
+static struct platform_driver at32_wdt_driver = {
+ .remove = __exit_p(at32_wdt_remove),
+ .suspend = at32_wdt_suspend,
+ .resume = at32_wdt_resume,
+ .driver = {
+ .name = "at32_wdt",
+ .owner = THIS_MODULE,
+ },
+ .shutdown = at32_wdt_shutdown,
+};
+
+static int __init at32_wdt_init(void)
+{
+ return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe);
+}
+module_init(at32_wdt_init);
+
+static void __exit at32_wdt_exit(void)
+{
+ platform_driver_unregister(&at32_wdt_driver);
+}
+module_exit(at32_wdt_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
index 01cf123b1616..0e4787a0bb87 100644
--- a/drivers/char/watchdog/ep93xx_wdt.c
+++ b/drivers/char/watchdog/ep93xx_wdt.c
@@ -107,10 +107,6 @@ static ssize_t
ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
loff_t *ppos)
{
- /* Can't seek (pwrite) on this device */
- if (*ppos != file->f_pos)
- return -ESPIPE;
-
if (len) {
if (!nowayout) {
size_t i;
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index f35e2848aa3e..db2ccb864412 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -29,11 +29,18 @@
* - support for one more type board
*
* Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
- * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
+ * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com>
+ * - make mixcomwd_opened unsigned,
+ * removed lock_kernel/unlock_kernel from mixcomwd_release,
+ * modified ioctl a bit to conform to API
*
*/
-#define VERSION "0.5"
+#define VERSION "0.6"
+#define WATCHDOG_NAME "mixcomwd"
+#define PFX WATCHDOG_NAME ": "
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -49,12 +56,46 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
-
-#define MIXCOM_WATCHDOG_OFFSET 0xc10
+/*
+ * We have two types of cards that can be probed:
+ * 1) The Mixcom cards: these cards can be found at addresses
+ * 0x180, 0x280, 0x380 with an additional offset of 0xc10.
+ * (Or 0xd90, 0xe90, 0xf90).
+ * 2) The FlashCOM cards: these cards can be set up at
+ * 0x300 -> 0x378, in 0x8 jumps with an offset of 0x04.
+ * (Or 0x304 -> 0x37c in 0x8 jumps).
+ * Each card has it's own ID.
+ */
#define MIXCOM_ID 0x11
-#define FLASHCOM_WATCHDOG_OFFSET 0x4
#define FLASHCOM_ID 0x18
+static struct {
+ int ioport;
+ int id;
+} mixcomwd_io_info[] __devinitdata = {
+ /* The Mixcom cards */
+ {0x0d90, MIXCOM_ID},
+ {0x0e90, MIXCOM_ID},
+ {0x0f90, MIXCOM_ID},
+ /* The FlashCOM cards */
+ {0x0304, FLASHCOM_ID},
+ {0x030c, FLASHCOM_ID},
+ {0x0314, FLASHCOM_ID},
+ {0x031c, FLASHCOM_ID},
+ {0x0324, FLASHCOM_ID},
+ {0x032c, FLASHCOM_ID},
+ {0x0334, FLASHCOM_ID},
+ {0x033c, FLASHCOM_ID},
+ {0x0344, FLASHCOM_ID},
+ {0x034c, FLASHCOM_ID},
+ {0x0354, FLASHCOM_ID},
+ {0x035c, FLASHCOM_ID},
+ {0x0364, FLASHCOM_ID},
+ {0x036c, FLASHCOM_ID},
+ {0x0374, FLASHCOM_ID},
+ {0x037c, FLASHCOM_ID},
+ /* The end of the list */
+ {0x0000, 0},
+};
static void mixcomwd_timerfun(unsigned long d);
@@ -113,13 +154,13 @@ static int mixcomwd_release(struct inode *inode, struct file *file)
{
if (expect_close == 42) {
if(mixcomwd_timer_alive) {
- printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+ printk(KERN_ERR PFX "release called while internal timer alive");
return -EBUSY;
}
mixcomwd_timer_alive=1;
mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
} else {
- printk(KERN_CRIT "mixcomwd: WDT device closed unexpectedly. WDT will not stop!\n");
+ printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n");
}
clear_bit(0,&mixcomwd_opened);
@@ -188,8 +229,7 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
return 0;
}
-static const struct file_operations mixcomwd_fops=
-{
+static const struct file_operations mixcomwd_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = mixcomwd_write,
@@ -198,46 +238,30 @@ static const struct file_operations mixcomwd_fops=
.release = mixcomwd_release,
};
-static struct miscdevice mixcomwd_miscdev=
-{
+static struct miscdevice mixcomwd_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &mixcomwd_fops,
};
-static int __init mixcomwd_checkcard(int port)
+static int __init checkcard(int port, int card_id)
{
int id;
- port += MIXCOM_WATCHDOG_OFFSET;
- if (!request_region(port, 1, "MixCOM watchdog")) {
- return 0;
- }
-
- id=inb_p(port) & 0x3f;
- if(id!=MIXCOM_ID) {
- release_region(port, 1);
- return 0;
- }
- return port;
-}
-
-static int __init flashcom_checkcard(int port)
-{
- int id;
-
- port += FLASHCOM_WATCHDOG_OFFSET;
if (!request_region(port, 1, "MixCOM watchdog")) {
return 0;
}
id=inb_p(port);
- if(id!=FLASHCOM_ID) {
+ if (card_id==MIXCOM_ID)
+ id &= 0x3f;
+
+ if (id!=card_id) {
release_region(port, 1);
return 0;
}
- return port;
- }
+ return 1;
+}
static int __init mixcomwd_init(void)
{
@@ -245,50 +269,50 @@ static int __init mixcomwd_init(void)
int ret;
int found=0;
- for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) {
- watchdog_port = mixcomwd_checkcard(mixcomwd_ioports[i]);
- if (watchdog_port) {
- found = 1;
- }
- }
-
- /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */
- for (i = 0x300; !found && i < 0x380; i+=0x8) {
- watchdog_port = flashcom_checkcard(i);
- if (watchdog_port) {
+ for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) {
+ if (checkcard(mixcomwd_io_info[i].ioport,
+ mixcomwd_io_info[i].id)) {
found = 1;
+ watchdog_port = mixcomwd_io_info[i].ioport;
}
}
if (!found) {
- printk("mixcomwd: No card detected, or port not available.\n");
+ printk(KERN_ERR PFX "No card detected, or port not available.\n");
return -ENODEV;
}
ret = misc_register(&mixcomwd_miscdev);
if (ret)
{
- release_region(watchdog_port, 1);
- return ret;
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto error_misc_register_watchdog;
}
- printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port);
+ printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
+ VERSION, watchdog_port);
return 0;
+
+error_misc_register_watchdog:
+ release_region(watchdog_port, 1);
+ watchdog_port = 0x0000;
+ return ret;
}
static void __exit mixcomwd_exit(void)
{
if (!nowayout) {
if(mixcomwd_timer_alive) {
- printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
+ printk(KERN_WARNING PFX "I quit now, hardware will"
" probably reboot!\n");
del_timer_sync(&mixcomwd_timer);
mixcomwd_timer_alive=0;
}
}
- release_region(watchdog_port,1);
misc_deregister(&mixcomwd_miscdev);
+ release_region(watchdog_port,1);
}
module_init(mixcomwd_init);
@@ -296,5 +320,6 @@ module_exit(mixcomwd_exit);
MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
MODULE_DESCRIPTION("MixCom Watchdog driver");
+MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c
index 5991add702b0..22f8873dd092 100644
--- a/drivers/char/watchdog/pnx4008_wdt.c
+++ b/drivers/char/watchdog/pnx4008_wdt.c
@@ -148,10 +148,6 @@ static ssize_t
pnx4008_wdt_write(struct file *file, const char *data, size_t len,
loff_t * ppos)
{
- /* Can't seek (pwrite) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
if (len) {
if (!nowayout) {
size_t i;
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 20fa29ca7404..50430bced2f2 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -92,6 +92,7 @@ typedef enum close_state {
static DECLARE_MUTEX(open_lock);
+static struct device *wdt_dev; /* platform device attached to */
static struct resource *wdt_mem;
static struct resource *wdt_irq;
static struct clk *wdt_clock;
@@ -180,7 +181,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
}
if ((count / divisor) >= 0x10000) {
- printk(KERN_ERR PFX "timeout %d too big\n", timeout);
+ dev_err(wdt_dev, "timeout %d too big\n", timeout);
return -EINVAL;
}
}
@@ -233,7 +234,7 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file)
if (allow_close == CLOSE_STATE_ALLOW) {
s3c2410wdt_stop();
} else {
- printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
s3c2410wdt_keepalive();
}
@@ -338,7 +339,7 @@ static struct miscdevice s3c2410wdt_miscdev = {
static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
{
- printk(KERN_INFO PFX "Watchdog timer expired!\n");
+ dev_info(wdt_dev, "watchdog timer expired (irq)\n");
s3c2410wdt_keepalive();
return IRQ_HANDLED;
@@ -348,31 +349,36 @@ static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
static int s3c2410wdt_probe(struct platform_device *pdev)
{
struct resource *res;
+ struct device *dev;
+ unsigned int wtcon;
int started = 0;
int ret;
int size;
DBG("%s: probe=%p\n", __FUNCTION__, pdev);
+ dev = &pdev->dev;
+ wdt_dev = &pdev->dev;
+
/* get the memory region for the watchdog timer */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
- printk(KERN_INFO PFX "failed to get memory region resouce\n");
+ dev_err(dev, "no memory resource specified\n");
return -ENOENT;
}
size = (res->end-res->start)+1;
wdt_mem = request_mem_region(res->start, size, pdev->name);
if (wdt_mem == NULL) {
- printk(KERN_INFO PFX "failed to get memory region\n");
+ dev_err(dev, "failed to get memory region\n");
ret = -ENOENT;
goto err_req;
}
wdt_base = ioremap(res->start, size);
if (wdt_base == 0) {
- printk(KERN_INFO PFX "failed to ioremap() region\n");
+ dev_err(dev, "failed to ioremap() region\n");
ret = -EINVAL;
goto err_req;
}
@@ -381,20 +387,20 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (wdt_irq == NULL) {
- printk(KERN_INFO PFX "failed to get irq resource\n");
+ dev_err(dev, "no irq resource specified\n");
ret = -ENOENT;
goto err_map;
}
ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
if (ret != 0) {
- printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
+ dev_err(dev, "failed to install irq (%d)\n", ret);
goto err_map;
}
wdt_clock = clk_get(&pdev->dev, "watchdog");
if (IS_ERR(wdt_clock)) {
- printk(KERN_INFO PFX "failed to find watchdog clock source\n");
+ dev_err(dev, "failed to find watchdog clock source\n");
ret = PTR_ERR(wdt_clock);
goto err_irq;
}
@@ -408,22 +414,22 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
started = s3c2410wdt_set_heartbeat(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
if (started == 0) {
- printk(KERN_INFO PFX "tmr_margin value out of range, default %d used\n",
+ dev_info(dev,"tmr_margin value out of range, default %d used\n",
CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
} else {
- printk(KERN_INFO PFX "default timer value is out of range, cannot start\n");
+ dev_info(dev, "default timer value is out of range, cannot start\n");
}
}
ret = misc_register(&s3c2410wdt_miscdev);
if (ret) {
- printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n",
+ dev_err(dev, "cannot register miscdev on minor=%d (%d)\n",
WATCHDOG_MINOR, ret);
goto err_clk;
}
if (tmr_atboot && started == 0) {
- printk(KERN_INFO PFX "Starting Watchdog Timer\n");
+ dev_info(dev, "starting watchdog timer\n");
s3c2410wdt_start();
} else if (!tmr_atboot) {
/* if we're not enabling the watchdog, then ensure it is
@@ -433,6 +439,15 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
s3c2410wdt_stop();
}
+ /* print out a statement of readiness */
+
+ wtcon = readl(wdt_base + S3C2410_WTCON);
+
+ dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",
+ (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in",
+ (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
+ (wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
+
return 0;
err_clk:
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
index e0bdc0db9640..100bfd422066 100644
--- a/drivers/connector/Kconfig
+++ b/drivers/connector/Kconfig
@@ -1,6 +1,5 @@
-menu "Connector - unified userspace <-> kernelspace linker"
-config CONNECTOR
+menuconfig CONNECTOR
tristate "Connector - unified userspace <-> kernelspace linker"
depends on NET
---help---
@@ -10,6 +9,8 @@ config CONNECTOR
Connector support can also be built as a module. If so, the module
will be called cn.ko.
+if CONNECTOR
+
config PROC_EVENTS
boolean "Report process events to userspace"
depends on CONNECTOR=y
@@ -18,4 +19,4 @@ config PROC_EVENTS
Provide a connector that reports process events to userspace. Send
events such as fork, exec, id change (uid, gid, suid, etc), and exit.
-endmenu
+endif # CONNECTOR
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index bb90cbd7ca51..84ebfcc1ffb4 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -1,4 +1,9 @@
-menu "Hardware crypto devices"
+
+menuconfig CRYPTO_HW
+ bool "Hardware crypto devices"
+ default y
+
+if CRYPTO_HW
config CRYPTO_DEV_PADLOCK
tristate "Support for VIA PadLock ACE"
@@ -78,4 +83,4 @@ config ZCRYPT_MONOLITHIC
that contains all parts of the crypto device driver (ap bus,
request router and all the card drivers).
-endmenu
+endif # CRYPTO_HW
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b31756d59978..8f670dae53bb 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -3,7 +3,7 @@
#
menu "DMA Engine support"
- depends on !S390
+ depends on HAS_DMA
config DMA_ENGINE
bool "Support for DMA engines"
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 807c402df049..debf1d8e8b41 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -6,11 +6,9 @@
# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
#
-menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)'
+menuconfig EDAC
+ tristate "EDAC - error detection and reporting (EXPERIMENTAL)"
depends on HAS_IOMEM
-
-config EDAC
- tristate "EDAC core system error reporting (EXPERIMENTAL)"
depends on X86 && EXPERIMENTAL
help
EDAC is designed to report errors in the core system.
@@ -30,13 +28,12 @@ config EDAC
There is also a mailing list for the EDAC project, which can
be found via the sourceforge page.
+if EDAC
comment "Reporting subsystems"
- depends on EDAC
config EDAC_DEBUG
bool "Debugging"
- depends on EDAC
help
This turns on debugging information for the entire EDAC
sub-system. You can insert module with "debug_level=x", current
@@ -45,7 +42,6 @@ config EDAC_DEBUG
config EDAC_MM_EDAC
tristate "Main Memory EDAC (Error Detection And Correction) reporting"
- depends on EDAC
default y
help
Some systems are able to detect and correct errors in main
@@ -100,15 +96,13 @@ config EDAC_R82600
choice
prompt "Error detecting method"
- depends on EDAC
default EDAC_POLL
config EDAC_POLL
bool "Poll for errors"
- depends on EDAC
help
Poll the chipset periodically to detect errors.
endchoice
-endmenu
+endif # EDAC
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 7b622300d0e5..804875de5801 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1906,6 +1906,7 @@ static void do_edac_check(void)
static int edac_kernel_thread(void *arg)
{
+ set_freezable();
while (!kthread_should_stop()) {
do_edac_check();
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 15232271d848..0fb730ee1da8 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -669,7 +669,7 @@ edd_get_pci_dev(struct edd_device *edev)
struct edd_info *info = edd_dev_get_info(edev);
if (edd_dev_is_type(edev, "PCI")) {
- return pci_find_slot(info->params.interface_path.pci.bus,
+ return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
PCI_DEVFN(info->params.interface_path.pci.slot,
info->params.interface_path.pci.
function));
@@ -682,9 +682,12 @@ edd_create_symlink_to_pcidev(struct edd_device *edev)
{
struct pci_dev *pci_dev = edd_get_pci_dev(edev);
+ int ret;
if (!pci_dev)
return 1;
- return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+ ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+ pci_dev_put(pci_dev);
+ return ret;
}
static inline void
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 2b4b76e8bd72..58e9f8e457f8 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,6 +15,7 @@
#include <linux/console.h>
#include <linux/efi.h>
#include <linux/serial.h>
+#include <linux/serial_8250.h>
#include <asm/vga.h>
#include "pcdp.h"
@@ -27,7 +28,7 @@ setup_serial_console(struct pcdp_uart *uart)
char parity;
mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
- p += sprintf(p, "console=uart,%s,0x%lx",
+ p += sprintf(p, "uart8250,%s,0x%lx",
mmio ? "mmio" : "io", uart->addr.address);
if (uart->baud) {
p += sprintf(p, ",%lu", uart->baud);
@@ -41,7 +42,8 @@ setup_serial_console(struct pcdp_uart *uart)
}
}
- return early_serial_console_init(options);
+ add_preferred_console("uart", 8250, &options[9]);
+ return setup_early_serial8250_console(options);
#else
return -ENODEV;
#endif
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 7eaae3834e15..275d392eca61 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -96,6 +96,10 @@ static int __devinit lm70_probe(struct spi_device *spi)
struct lm70 *p_lm70;
int status;
+ /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */
+ if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE))
+ return -EINVAL;
+
p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
if (!p_lm70)
return -ENOMEM;
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 03188d277af1..17cecf1ea797 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -630,7 +630,7 @@ static struct i2c_adapter pmcmsptwi_adapter = {
static struct platform_driver pmcmsptwi_driver = {
.probe = pmcmsptwi_probe,
.remove = __devexit_p(pmcmsptwi_remove),
- .driver {
+ .driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 3944e889cb21..2e1c24f671cf 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -153,4 +153,14 @@ config SENSORS_TSL2550
This driver can also be built as a module. If so, the module
will be called tsl2550.
+config MENELAUS
+ bool "TWL92330/Menelaus PM chip"
+ depends on I2C=y && ARCH_OMAP24XX
+ help
+ If you say yes here you get support for the Texas Instruments
+ TWL92330/Menelaus Power Management chip. This include voltage
+ regulators, Dual slot memory card tranceivers, real-time clock
+ and other features that are often used in portable devices like
+ cell phones and PDAs.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index d8cbeb3f4b63..ca924e105959 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
+obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
new file mode 100644
index 000000000000..48a7e2f0bdd3
--- /dev/null
+++ b/drivers/i2c/chips/menelaus.c
@@ -0,0 +1,1281 @@
+#define DEBUG
+/*
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Some parts based tps65010.c:
+ * Copyright (C) 2004 Texas Instruments and
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * Some parts based on tlv320aic24.c:
+ * Copyright (C) by Kai Svahn <kai.svahn@nokia.com>
+ *
+ * Changes for interrupt handling and clean-up by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Cleanup and generalized support for voltage setting by
+ * Juha Yrjola
+ * Added support for controlling VCORE and regulator sleep states,
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/menelaus.h>
+
+#define DRIVER_NAME "menelaus"
+
+#define pr_err(fmt, arg...) printk(KERN_ERR DRIVER_NAME ": ", ## arg);
+
+#define MENELAUS_I2C_ADDRESS 0x72
+
+#define MENELAUS_REV 0x01
+#define MENELAUS_VCORE_CTRL1 0x02
+#define MENELAUS_VCORE_CTRL2 0x03
+#define MENELAUS_VCORE_CTRL3 0x04
+#define MENELAUS_VCORE_CTRL4 0x05
+#define MENELAUS_VCORE_CTRL5 0x06
+#define MENELAUS_DCDC_CTRL1 0x07
+#define MENELAUS_DCDC_CTRL2 0x08
+#define MENELAUS_DCDC_CTRL3 0x09
+#define MENELAUS_LDO_CTRL1 0x0A
+#define MENELAUS_LDO_CTRL2 0x0B
+#define MENELAUS_LDO_CTRL3 0x0C
+#define MENELAUS_LDO_CTRL4 0x0D
+#define MENELAUS_LDO_CTRL5 0x0E
+#define MENELAUS_LDO_CTRL6 0x0F
+#define MENELAUS_LDO_CTRL7 0x10
+#define MENELAUS_LDO_CTRL8 0x11
+#define MENELAUS_SLEEP_CTRL1 0x12
+#define MENELAUS_SLEEP_CTRL2 0x13
+#define MENELAUS_DEVICE_OFF 0x14
+#define MENELAUS_OSC_CTRL 0x15
+#define MENELAUS_DETECT_CTRL 0x16
+#define MENELAUS_INT_MASK1 0x17
+#define MENELAUS_INT_MASK2 0x18
+#define MENELAUS_INT_STATUS1 0x19
+#define MENELAUS_INT_STATUS2 0x1A
+#define MENELAUS_INT_ACK1 0x1B
+#define MENELAUS_INT_ACK2 0x1C
+#define MENELAUS_GPIO_CTRL 0x1D
+#define MENELAUS_GPIO_IN 0x1E
+#define MENELAUS_GPIO_OUT 0x1F
+#define MENELAUS_BBSMS 0x20
+#define MENELAUS_RTC_CTRL 0x21
+#define MENELAUS_RTC_UPDATE 0x22
+#define MENELAUS_RTC_SEC 0x23
+#define MENELAUS_RTC_MIN 0x24
+#define MENELAUS_RTC_HR 0x25
+#define MENELAUS_RTC_DAY 0x26
+#define MENELAUS_RTC_MON 0x27
+#define MENELAUS_RTC_YR 0x28
+#define MENELAUS_RTC_WKDAY 0x29
+#define MENELAUS_RTC_AL_SEC 0x2A
+#define MENELAUS_RTC_AL_MIN 0x2B
+#define MENELAUS_RTC_AL_HR 0x2C
+#define MENELAUS_RTC_AL_DAY 0x2D
+#define MENELAUS_RTC_AL_MON 0x2E
+#define MENELAUS_RTC_AL_YR 0x2F
+#define MENELAUS_RTC_COMP_MSB 0x30
+#define MENELAUS_RTC_COMP_LSB 0x31
+#define MENELAUS_S1_PULL_EN 0x32
+#define MENELAUS_S1_PULL_DIR 0x33
+#define MENELAUS_S2_PULL_EN 0x34
+#define MENELAUS_S2_PULL_DIR 0x35
+#define MENELAUS_MCT_CTRL1 0x36
+#define MENELAUS_MCT_CTRL2 0x37
+#define MENELAUS_MCT_CTRL3 0x38
+#define MENELAUS_MCT_PIN_ST 0x39
+#define MENELAUS_DEBOUNCE1 0x3A
+
+#define IH_MENELAUS_IRQS 12
+#define MENELAUS_MMC_S1CD_IRQ 0 /* MMC slot 1 card change */
+#define MENELAUS_MMC_S2CD_IRQ 1 /* MMC slot 2 card change */
+#define MENELAUS_MMC_S1D1_IRQ 2 /* MMC DAT1 low in slot 1 */
+#define MENELAUS_MMC_S2D1_IRQ 3 /* MMC DAT1 low in slot 2 */
+#define MENELAUS_LOWBAT_IRQ 4 /* Low battery */
+#define MENELAUS_HOTDIE_IRQ 5 /* Hot die detect */
+#define MENELAUS_UVLO_IRQ 6 /* UVLO detect */
+#define MENELAUS_TSHUT_IRQ 7 /* Thermal shutdown */
+#define MENELAUS_RTCTMR_IRQ 8 /* RTC timer */
+#define MENELAUS_RTCALM_IRQ 9 /* RTC alarm */
+#define MENELAUS_RTCERR_IRQ 10 /* RTC error */
+#define MENELAUS_PSHBTN_IRQ 11 /* Push button */
+#define MENELAUS_RESERVED12_IRQ 12 /* Reserved */
+#define MENELAUS_RESERVED13_IRQ 13 /* Reserved */
+#define MENELAUS_RESERVED14_IRQ 14 /* Reserved */
+#define MENELAUS_RESERVED15_IRQ 15 /* Reserved */
+
+static void menelaus_work(struct work_struct *_menelaus);
+
+struct menelaus_chip {
+ struct mutex lock;
+ struct i2c_client *client;
+ struct work_struct work;
+#ifdef CONFIG_RTC_DRV_TWL92330
+ struct rtc_device *rtc;
+ u8 rtc_control;
+ unsigned uie:1;
+#endif
+ unsigned vcore_hw_mode:1;
+ u8 mask1, mask2;
+ void (*handlers[16])(struct menelaus_chip *);
+ void (*mmc_callback)(void *data, u8 mask);
+ void *mmc_callback_data;
+};
+
+static struct menelaus_chip *the_menelaus;
+
+static int menelaus_write_reg(int reg, u8 value)
+{
+ int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value);
+
+ if (val < 0) {
+ pr_err("write error");
+ return val;
+ }
+
+ return 0;
+}
+
+static int menelaus_read_reg(int reg)
+{
+ int val = i2c_smbus_read_byte_data(the_menelaus->client, reg);
+
+ if (val < 0)
+ pr_err("read error");
+
+ return val;
+}
+
+static int menelaus_enable_irq(int irq)
+{
+ if (irq > 7) {
+ irq -= 8;
+ the_menelaus->mask2 &= ~(1 << irq);
+ return menelaus_write_reg(MENELAUS_INT_MASK2,
+ the_menelaus->mask2);
+ } else {
+ the_menelaus->mask1 &= ~(1 << irq);
+ return menelaus_write_reg(MENELAUS_INT_MASK1,
+ the_menelaus->mask1);
+ }
+}
+
+static int menelaus_disable_irq(int irq)
+{
+ if (irq > 7) {
+ irq -= 8;
+ the_menelaus->mask2 |= (1 << irq);
+ return menelaus_write_reg(MENELAUS_INT_MASK2,
+ the_menelaus->mask2);
+ } else {
+ the_menelaus->mask1 |= (1 << irq);
+ return menelaus_write_reg(MENELAUS_INT_MASK1,
+ the_menelaus->mask1);
+ }
+}
+
+static int menelaus_ack_irq(int irq)
+{
+ if (irq > 7)
+ return menelaus_write_reg(MENELAUS_INT_ACK2, 1 << (irq - 8));
+ else
+ return menelaus_write_reg(MENELAUS_INT_ACK1, 1 << irq);
+}
+
+/* Adds a handler for an interrupt. Does not run in interrupt context */
+static int menelaus_add_irq_work(int irq,
+ void (*handler)(struct menelaus_chip *))
+{
+ int ret = 0;
+
+ mutex_lock(&the_menelaus->lock);
+ the_menelaus->handlers[irq] = handler;
+ ret = menelaus_enable_irq(irq);
+ mutex_unlock(&the_menelaus->lock);
+
+ return ret;
+}
+
+/* Removes handler for an interrupt */
+static int menelaus_remove_irq_work(int irq)
+{
+ int ret = 0;
+
+ mutex_lock(&the_menelaus->lock);
+ ret = menelaus_disable_irq(irq);
+ the_menelaus->handlers[irq] = NULL;
+ mutex_unlock(&the_menelaus->lock);
+
+ return ret;
+}
+
+/*
+ * Gets scheduled when a card detect interrupt happens. Note that in some cases
+ * this line is wired to card cover switch rather than the card detect switch
+ * in each slot. In this case the cards are not seen by menelaus.
+ * FIXME: Add handling for D1 too
+ */
+static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw)
+{
+ int reg;
+ unsigned char card_mask = 0;
+
+ reg = menelaus_read_reg(MENELAUS_MCT_PIN_ST);
+ if (reg < 0)
+ return;
+
+ if (!(reg & 0x1))
+ card_mask |= (1 << 0);
+
+ if (!(reg & 0x2))
+ card_mask |= (1 << 1);
+
+ if (menelaus_hw->mmc_callback)
+ menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data,
+ card_mask);
+}
+
+/*
+ * Toggles the MMC slots between open-drain and push-pull mode.
+ */
+int menelaus_set_mmc_opendrain(int slot, int enable)
+{
+ int ret, val;
+
+ if (slot != 1 && slot != 2)
+ return -EINVAL;
+ mutex_lock(&the_menelaus->lock);
+ ret = menelaus_read_reg(MENELAUS_MCT_CTRL1);
+ if (ret < 0) {
+ mutex_unlock(&the_menelaus->lock);
+ return ret;
+ }
+ val = ret;
+ if (slot == 1) {
+ if (enable)
+ val |= 1 << 2;
+ else
+ val &= ~(1 << 2);
+ } else {
+ if (enable)
+ val |= 1 << 3;
+ else
+ val &= ~(1 << 3);
+ }
+ ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val);
+ mutex_unlock(&the_menelaus->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(menelaus_set_mmc_opendrain);
+
+int menelaus_set_slot_sel(int enable)
+{
+ int ret;
+
+ mutex_lock(&the_menelaus->lock);
+ ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
+ if (ret < 0)
+ goto out;
+ ret |= 0x02;
+ if (enable)
+ ret |= 1 << 5;
+ else
+ ret &= ~(1 << 5);
+ ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
+out:
+ mutex_unlock(&the_menelaus->lock);
+ return ret;
+}
+EXPORT_SYMBOL(menelaus_set_slot_sel);
+
+int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en)
+{
+ int ret, val;
+
+ if (slot != 1 && slot != 2)
+ return -EINVAL;
+ if (power >= 3)
+ return -EINVAL;
+
+ mutex_lock(&the_menelaus->lock);
+
+ ret = menelaus_read_reg(MENELAUS_MCT_CTRL2);
+ if (ret < 0)
+ goto out;
+ val = ret;
+ if (slot == 1) {
+ if (cd_en)
+ val |= (1 << 4) | (1 << 6);
+ else
+ val &= ~((1 << 4) | (1 << 6));
+ } else {
+ if (cd_en)
+ val |= (1 << 5) | (1 << 7);
+ else
+ val &= ~((1 << 5) | (1 << 7));
+ }
+ ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val);
+ if (ret < 0)
+ goto out;
+
+ ret = menelaus_read_reg(MENELAUS_MCT_CTRL3);
+ if (ret < 0)
+ goto out;
+ val = ret;
+ if (slot == 1) {
+ if (enable)
+ val |= 1 << 0;
+ else
+ val &= ~(1 << 0);
+ } else {
+ int b;
+
+ if (enable)
+ ret |= 1 << 1;
+ else
+ ret &= ~(1 << 1);
+ b = menelaus_read_reg(MENELAUS_MCT_CTRL2);
+ b &= ~0x03;
+ b |= power;
+ ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b);
+ if (ret < 0)
+ goto out;
+ }
+ /* Disable autonomous shutdown */
+ val &= ~(0x03 << 2);
+ ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val);
+out:
+ mutex_unlock(&the_menelaus->lock);
+ return ret;
+}
+EXPORT_SYMBOL(menelaus_set_mmc_slot);
+
+int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
+ void *data)
+{
+ int ret = 0;
+
+ the_menelaus->mmc_callback_data = data;
+ the_menelaus->mmc_callback = callback;
+ ret = menelaus_add_irq_work(MENELAUS_MMC_S1CD_IRQ,
+ menelaus_mmc_cd_work);
+ if (ret < 0)
+ return ret;
+ ret = menelaus_add_irq_work(MENELAUS_MMC_S2CD_IRQ,
+ menelaus_mmc_cd_work);
+ if (ret < 0)
+ return ret;
+ ret = menelaus_add_irq_work(MENELAUS_MMC_S1D1_IRQ,
+ menelaus_mmc_cd_work);
+ if (ret < 0)
+ return ret;
+ ret = menelaus_add_irq_work(MENELAUS_MMC_S2D1_IRQ,
+ menelaus_mmc_cd_work);
+
+ return ret;
+}
+EXPORT_SYMBOL(menelaus_register_mmc_callback);
+
+void menelaus_unregister_mmc_callback(void)
+{
+ menelaus_remove_irq_work(MENELAUS_MMC_S1CD_IRQ);
+ menelaus_remove_irq_work(MENELAUS_MMC_S2CD_IRQ);
+ menelaus_remove_irq_work(MENELAUS_MMC_S1D1_IRQ);
+ menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
+
+ the_menelaus->mmc_callback = NULL;
+ the_menelaus->mmc_callback_data = 0;
+}
+EXPORT_SYMBOL(menelaus_unregister_mmc_callback);
+
+struct menelaus_vtg {
+ const char *name;
+ u8 vtg_reg;
+ u8 vtg_shift;
+ u8 vtg_bits;
+ u8 mode_reg;
+};
+
+struct menelaus_vtg_value {
+ u16 vtg;
+ u16 val;
+};
+
+static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV,
+ int vtg_val, int mode)
+{
+ int val, ret;
+ struct i2c_client *c = the_menelaus->client;
+
+ mutex_lock(&the_menelaus->lock);
+ if (vtg == 0)
+ goto set_voltage;
+
+ ret = menelaus_read_reg(vtg->vtg_reg);
+ if (ret < 0)
+ goto out;
+ val = ret & ~(((1 << vtg->vtg_bits) - 1) << vtg->vtg_shift);
+ val |= vtg_val << vtg->vtg_shift;
+
+ dev_dbg(&c->dev, "Setting voltage '%s'"
+ "to %d mV (reg 0x%02x, val 0x%02x)\n",
+ vtg->name, mV, vtg->vtg_reg, val);
+
+ ret = menelaus_write_reg(vtg->vtg_reg, val);
+ if (ret < 0)
+ goto out;
+set_voltage:
+ ret = menelaus_write_reg(vtg->mode_reg, mode);
+out:
+ mutex_unlock(&the_menelaus->lock);
+ if (ret == 0) {
+ /* Wait for voltage to stabilize */
+ msleep(1);
+ }
+ return ret;
+}
+
+static int menelaus_get_vtg_value(int vtg, const struct menelaus_vtg_value *tbl,
+ int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++, tbl++)
+ if (tbl->vtg == vtg)
+ return tbl->val;
+ return -EINVAL;
+}
+
+/*
+ * Vcore can be programmed in two ways:
+ * SW-controlled: Required voltage is programmed into VCORE_CTRL1
+ * HW-controlled: Required range (roof-floor) is programmed into VCORE_CTRL3
+ * and VCORE_CTRL4
+ *
+ * Call correct 'set' function accordingly
+ */
+
+static const struct menelaus_vtg_value vcore_values[] = {
+ { 1000, 0 },
+ { 1025, 1 },
+ { 1050, 2 },
+ { 1075, 3 },
+ { 1100, 4 },
+ { 1125, 5 },
+ { 1150, 6 },
+ { 1175, 7 },
+ { 1200, 8 },
+ { 1225, 9 },
+ { 1250, 10 },
+ { 1275, 11 },
+ { 1300, 12 },
+ { 1325, 13 },
+ { 1350, 14 },
+ { 1375, 15 },
+ { 1400, 16 },
+ { 1425, 17 },
+ { 1450, 18 },
+};
+
+int menelaus_set_vcore_sw(unsigned int mV)
+{
+ int val, ret;
+ struct i2c_client *c = the_menelaus->client;
+
+ val = menelaus_get_vtg_value(mV, vcore_values,
+ ARRAY_SIZE(vcore_values));
+ if (val < 0)
+ return -EINVAL;
+
+ dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val);
+
+ /* Set SW mode and the voltage in one go. */
+ mutex_lock(&the_menelaus->lock);
+ ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
+ if (ret == 0)
+ the_menelaus->vcore_hw_mode = 0;
+ mutex_unlock(&the_menelaus->lock);
+ msleep(1);
+
+ return ret;
+}
+
+int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV)
+{
+ int fval, rval, val, ret;
+ struct i2c_client *c = the_menelaus->client;
+
+ rval = menelaus_get_vtg_value(roof_mV, vcore_values,
+ ARRAY_SIZE(vcore_values));
+ if (rval < 0)
+ return -EINVAL;
+ fval = menelaus_get_vtg_value(floor_mV, vcore_values,
+ ARRAY_SIZE(vcore_values));
+ if (fval < 0)
+ return -EINVAL;
+
+ dev_dbg(&c->dev, "Setting VCORE FLOOR to %d mV and ROOF to %d mV\n",
+ floor_mV, roof_mV);
+
+ mutex_lock(&the_menelaus->lock);
+ ret = menelaus_write_reg(MENELAUS_VCORE_CTRL3, fval);
+ if (ret < 0)
+ goto out;
+ ret = menelaus_write_reg(MENELAUS_VCORE_CTRL4, rval);
+ if (ret < 0)
+ goto out;
+ if (!the_menelaus->vcore_hw_mode) {
+ val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
+ /* HW mode, turn OFF byte comparator */
+ val |= ((1 << 7) | (1 << 5));
+ ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
+ the_menelaus->vcore_hw_mode = 1;
+ }
+ msleep(1);
+out:
+ mutex_unlock(&the_menelaus->lock);
+ return ret;
+}
+
+static const struct menelaus_vtg vmem_vtg = {
+ .name = "VMEM",
+ .vtg_reg = MENELAUS_LDO_CTRL1,
+ .vtg_shift = 0,
+ .vtg_bits = 2,
+ .mode_reg = MENELAUS_LDO_CTRL3,
+};
+
+static const struct menelaus_vtg_value vmem_values[] = {
+ { 1500, 0 },
+ { 1800, 1 },
+ { 1900, 2 },
+ { 2500, 3 },
+};
+
+int menelaus_set_vmem(unsigned int mV)
+{
+ int val;
+
+ if (mV == 0)
+ return menelaus_set_voltage(&vmem_vtg, 0, 0, 0);
+
+ val = menelaus_get_vtg_value(mV, vmem_values, ARRAY_SIZE(vmem_values));
+ if (val < 0)
+ return -EINVAL;
+ return menelaus_set_voltage(&vmem_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vmem);
+
+static const struct menelaus_vtg vio_vtg = {
+ .name = "VIO",
+ .vtg_reg = MENELAUS_LDO_CTRL1,
+ .vtg_shift = 2,
+ .vtg_bits = 2,
+ .mode_reg = MENELAUS_LDO_CTRL4,
+};
+
+static const struct menelaus_vtg_value vio_values[] = {
+ { 1500, 0 },
+ { 1800, 1 },
+ { 2500, 2 },
+ { 2800, 3 },
+};
+
+int menelaus_set_vio(unsigned int mV)
+{
+ int val;
+
+ if (mV == 0)
+ return menelaus_set_voltage(&vio_vtg, 0, 0, 0);
+
+ val = menelaus_get_vtg_value(mV, vio_values, ARRAY_SIZE(vio_values));
+ if (val < 0)
+ return -EINVAL;
+ return menelaus_set_voltage(&vio_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vio);
+
+static const struct menelaus_vtg_value vdcdc_values[] = {
+ { 1500, 0 },
+ { 1800, 1 },
+ { 2000, 2 },
+ { 2200, 3 },
+ { 2400, 4 },
+ { 2800, 5 },
+ { 3000, 6 },
+ { 3300, 7 },
+};
+
+static const struct menelaus_vtg vdcdc2_vtg = {
+ .name = "VDCDC2",
+ .vtg_reg = MENELAUS_DCDC_CTRL1,
+ .vtg_shift = 0,
+ .vtg_bits = 3,
+ .mode_reg = MENELAUS_DCDC_CTRL2,
+};
+
+static const struct menelaus_vtg vdcdc3_vtg = {
+ .name = "VDCDC3",
+ .vtg_reg = MENELAUS_DCDC_CTRL1,
+ .vtg_shift = 3,
+ .vtg_bits = 3,
+ .mode_reg = MENELAUS_DCDC_CTRL3,
+};
+
+int menelaus_set_vdcdc(int dcdc, unsigned int mV)
+{
+ const struct menelaus_vtg *vtg;
+ int val;
+
+ if (dcdc != 2 && dcdc != 3)
+ return -EINVAL;
+ if (dcdc == 2)
+ vtg = &vdcdc2_vtg;
+ else
+ vtg = &vdcdc3_vtg;
+
+ if (mV == 0)
+ return menelaus_set_voltage(vtg, 0, 0, 0);
+
+ val = menelaus_get_vtg_value(mV, vdcdc_values,
+ ARRAY_SIZE(vdcdc_values));
+ if (val < 0)
+ return -EINVAL;
+ return menelaus_set_voltage(vtg, mV, val, 0x03);
+}
+
+static const struct menelaus_vtg_value vmmc_values[] = {
+ { 1850, 0 },
+ { 2800, 1 },
+ { 3000, 2 },
+ { 3100, 3 },
+};
+
+static const struct menelaus_vtg vmmc_vtg = {
+ .name = "VMMC",
+ .vtg_reg = MENELAUS_LDO_CTRL1,
+ .vtg_shift = 6,
+ .vtg_bits = 2,
+ .mode_reg = MENELAUS_LDO_CTRL7,
+};
+
+int menelaus_set_vmmc(unsigned int mV)
+{
+ int val;
+
+ if (mV == 0)
+ return menelaus_set_voltage(&vmmc_vtg, 0, 0, 0);
+
+ val = menelaus_get_vtg_value(mV, vmmc_values, ARRAY_SIZE(vmmc_values));
+ if (val < 0)
+ return -EINVAL;
+ return menelaus_set_voltage(&vmmc_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vmmc);
+
+
+static const struct menelaus_vtg_value vaux_values[] = {
+ { 1500, 0 },
+ { 1800, 1 },
+ { 2500, 2 },
+ { 2800, 3 },
+};
+
+static const struct menelaus_vtg vaux_vtg = {
+ .name = "VAUX",
+ .vtg_reg = MENELAUS_LDO_CTRL1,
+ .vtg_shift = 4,
+ .vtg_bits = 2,
+ .mode_reg = MENELAUS_LDO_CTRL6,
+};
+
+int menelaus_set_vaux(unsigned int mV)
+{
+ int val;
+
+ if (mV == 0)
+ return menelaus_set_voltage(&vaux_vtg, 0, 0, 0);
+
+ val = menelaus_get_vtg_value(mV, vaux_values, ARRAY_SIZE(vaux_values));
+ if (val < 0)
+ return -EINVAL;
+ return menelaus_set_voltage(&vaux_vtg, mV, val, 0x02);
+}
+EXPORT_SYMBOL(menelaus_set_vaux);
+
+int menelaus_get_slot_pin_states(void)
+{
+ return menelaus_read_reg(MENELAUS_MCT_PIN_ST);
+}
+EXPORT_SYMBOL(menelaus_get_slot_pin_states);
+
+int menelaus_set_regulator_sleep(int enable, u32 val)
+{
+ int t, ret;
+ struct i2c_client *c = the_menelaus->client;
+
+ mutex_lock(&the_menelaus->lock);
+ ret = menelaus_write_reg(MENELAUS_SLEEP_CTRL2, val);
+ if (ret < 0)
+ goto out;
+
+ dev_dbg(&c->dev, "regulator sleep configuration: %02x\n", val);
+
+ ret = menelaus_read_reg(MENELAUS_GPIO_CTRL);
+ if (ret < 0)
+ goto out;
+ t = ((1 << 6) | 0x04);
+ if (enable)
+ ret |= t;
+ else
+ ret &= ~t;
+ ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret);
+out:
+ mutex_unlock(&the_menelaus->lock);
+ return ret;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Handles Menelaus interrupts. Does not run in interrupt context */
+static void menelaus_work(struct work_struct *_menelaus)
+{
+ struct menelaus_chip *menelaus =
+ container_of(_menelaus, struct menelaus_chip, work);
+ void (*handler)(struct menelaus_chip *menelaus);
+
+ while (1) {
+ unsigned isr;
+
+ isr = (menelaus_read_reg(MENELAUS_INT_STATUS2)
+ & ~menelaus->mask2) << 8;
+ isr |= menelaus_read_reg(MENELAUS_INT_STATUS1)
+ & ~menelaus->mask1;
+ if (!isr)
+ break;
+
+ while (isr) {
+ int irq = fls(isr) - 1;
+ isr &= ~(1 << irq);
+
+ mutex_lock(&menelaus->lock);
+ menelaus_disable_irq(irq);
+ menelaus_ack_irq(irq);
+ handler = menelaus->handlers[irq];
+ if (handler)
+ handler(menelaus);
+ menelaus_enable_irq(irq);
+ mutex_unlock(&menelaus->lock);
+ }
+ }
+ enable_irq(menelaus->client->irq);
+}
+
+/*
+ * We cannot use I2C in interrupt context, so we just schedule work.
+ */
+static irqreturn_t menelaus_irq(int irq, void *_menelaus)
+{
+ struct menelaus_chip *menelaus = _menelaus;
+
+ disable_irq_nosync(irq);
+ (void)schedule_work(&menelaus->work);
+
+ return IRQ_HANDLED;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/*
+ * The RTC needs to be set once, then it runs on backup battery power.
+ * It supports alarms, including system wake alarms (from some modes);
+ * and 1/second IRQs if requested.
+ */
+#ifdef CONFIG_RTC_DRV_TWL92330
+
+#define RTC_CTRL_RTC_EN (1 << 0)
+#define RTC_CTRL_AL_EN (1 << 1)
+#define RTC_CTRL_MODE12 (1 << 2)
+#define RTC_CTRL_EVERY_MASK (3 << 3)
+#define RTC_CTRL_EVERY_SEC (0 << 3)
+#define RTC_CTRL_EVERY_MIN (1 << 3)
+#define RTC_CTRL_EVERY_HR (2 << 3)
+#define RTC_CTRL_EVERY_DAY (3 << 3)
+
+#define RTC_UPDATE_EVERY 0x08
+
+#define RTC_HR_PM (1 << 7)
+
+static void menelaus_to_time(char *regs, struct rtc_time *t)
+{
+ t->tm_sec = BCD2BIN(regs[0]);
+ t->tm_min = BCD2BIN(regs[1]);
+ if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
+ t->tm_hour = BCD2BIN(regs[2] & 0x1f) - 1;
+ if (regs[2] & RTC_HR_PM)
+ t->tm_hour += 12;
+ } else
+ t->tm_hour = BCD2BIN(regs[2] & 0x3f);
+ t->tm_mday = BCD2BIN(regs[3]);
+ t->tm_mon = BCD2BIN(regs[4]) - 1;
+ t->tm_year = BCD2BIN(regs[5]) + 100;
+}
+
+static int time_to_menelaus(struct rtc_time *t, int regnum)
+{
+ int hour, status;
+
+ status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_sec));
+ if (status < 0)
+ goto fail;
+
+ status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_min));
+ if (status < 0)
+ goto fail;
+
+ if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
+ hour = t->tm_hour + 1;
+ if (hour > 12)
+ hour = RTC_HR_PM | BIN2BCD(hour - 12);
+ else
+ hour = BIN2BCD(hour);
+ } else
+ hour = BIN2BCD(t->tm_hour);
+ status = menelaus_write_reg(regnum++, hour);
+ if (status < 0)
+ goto fail;
+
+ status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mday));
+ if (status < 0)
+ goto fail;
+
+ status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mon + 1));
+ if (status < 0)
+ goto fail;
+
+ status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_year - 100));
+ if (status < 0)
+ goto fail;
+
+ return 0;
+fail:
+ dev_err(&the_menelaus->client->dev, "rtc write reg %02x, err %d\n",
+ --regnum, status);
+ return status;
+}
+
+static int menelaus_read_time(struct device *dev, struct rtc_time *t)
+{
+ struct i2c_msg msg[2];
+ char regs[7];
+ int status;
+
+ /* block read date and time registers */
+ regs[0] = MENELAUS_RTC_SEC;
+
+ msg[0].addr = MENELAUS_I2C_ADDRESS;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = regs;
+
+ msg[1].addr = MENELAUS_I2C_ADDRESS;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = sizeof(regs);
+ msg[1].buf = regs;
+
+ status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
+ if (status != 2) {
+ dev_err(dev, "%s error %d\n", "read", status);
+ return -EIO;
+ }
+
+ menelaus_to_time(regs, t);
+ t->tm_wday = BCD2BIN(regs[6]);
+
+ return 0;
+}
+
+static int menelaus_set_time(struct device *dev, struct rtc_time *t)
+{
+ int status;
+
+ /* write date and time registers */
+ status = time_to_menelaus(t, MENELAUS_RTC_SEC);
+ if (status < 0)
+ return status;
+ status = menelaus_write_reg(MENELAUS_RTC_WKDAY, BIN2BCD(t->tm_wday));
+ if (status < 0) {
+ dev_err(&the_menelaus->client->dev, "rtc write reg %02x",
+ "err %d\n", MENELAUS_RTC_WKDAY, status);
+ return status;
+ }
+
+ /* now commit the write */
+ status = menelaus_write_reg(MENELAUS_RTC_UPDATE, RTC_UPDATE_EVERY);
+ if (status < 0)
+ dev_err(&the_menelaus->client->dev, "rtc commit time, err %d\n",
+ status);
+
+ return 0;
+}
+
+static int menelaus_read_alarm(struct device *dev, struct rtc_wkalrm *w)
+{
+ struct i2c_msg msg[2];
+ char regs[6];
+ int status;
+
+ /* block read alarm registers */
+ regs[0] = MENELAUS_RTC_AL_SEC;
+
+ msg[0].addr = MENELAUS_I2C_ADDRESS;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = regs;
+
+ msg[1].addr = MENELAUS_I2C_ADDRESS;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = sizeof(regs);
+ msg[1].buf = regs;
+
+ status = i2c_transfer(the_menelaus->client->adapter, msg, 2);
+ if (status != 2) {
+ dev_err(dev, "%s error %d\n", "alarm read", status);
+ return -EIO;
+ }
+
+ menelaus_to_time(regs, &w->time);
+
+ w->enabled = !!(the_menelaus->rtc_control & RTC_CTRL_AL_EN);
+
+ /* NOTE we *could* check if actually pending... */
+ w->pending = 0;
+
+ return 0;
+}
+
+static int menelaus_set_alarm(struct device *dev, struct rtc_wkalrm *w)
+{
+ int status;
+
+ if (the_menelaus->client->irq <= 0 && w->enabled)
+ return -ENODEV;
+
+ /* clear previous alarm enable */
+ if (the_menelaus->rtc_control & RTC_CTRL_AL_EN) {
+ the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+ status = menelaus_write_reg(MENELAUS_RTC_CTRL,
+ the_menelaus->rtc_control);
+ if (status < 0)
+ return status;
+ }
+
+ /* write alarm registers */
+ status = time_to_menelaus(&w->time, MENELAUS_RTC_AL_SEC);
+ if (status < 0)
+ return status;
+
+ /* enable alarm if requested */
+ if (w->enabled) {
+ the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
+ status = menelaus_write_reg(MENELAUS_RTC_CTRL,
+ the_menelaus->rtc_control);
+ }
+
+ return status;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static void menelaus_rtc_update_work(struct menelaus_chip *m)
+{
+ /* report 1/sec update */
+ local_irq_disable();
+ rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_UF);
+ local_irq_enable();
+}
+
+static int menelaus_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
+{
+ int status;
+
+ if (the_menelaus->client->irq <= 0)
+ return -ENOIOCTLCMD;
+
+ switch (cmd) {
+ /* alarm IRQ */
+ case RTC_AIE_ON:
+ if (the_menelaus->rtc_control & RTC_CTRL_AL_EN)
+ return 0;
+ the_menelaus->rtc_control |= RTC_CTRL_AL_EN;
+ break;
+ case RTC_AIE_OFF:
+ if (!(the_menelaus->rtc_control & RTC_CTRL_AL_EN))
+ return 0;
+ the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+ break;
+ /* 1/second "update" IRQ */
+ case RTC_UIE_ON:
+ if (the_menelaus->uie)
+ return 0;
+ status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
+ status = menelaus_add_irq_work(MENELAUS_RTCTMR_IRQ,
+ menelaus_rtc_update_work);
+ if (status == 0)
+ the_menelaus->uie = 1;
+ return status;
+ case RTC_UIE_OFF:
+ if (!the_menelaus->uie)
+ return 0;
+ status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ);
+ if (status == 0)
+ the_menelaus->uie = 0;
+ return status;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
+}
+
+#else
+#define menelaus_ioctl NULL
+#endif
+
+/* REVISIT no compensation register support ... */
+
+static const struct rtc_class_ops menelaus_rtc_ops = {
+ .ioctl = menelaus_ioctl,
+ .read_time = menelaus_read_time,
+ .set_time = menelaus_set_time,
+ .read_alarm = menelaus_read_alarm,
+ .set_alarm = menelaus_set_alarm,
+};
+
+static void menelaus_rtc_alarm_work(struct menelaus_chip *m)
+{
+ /* report alarm */
+ local_irq_disable();
+ rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_AF);
+ local_irq_enable();
+
+ /* then disable it; alarms are oneshot */
+ the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN;
+ menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control);
+}
+
+static inline void menelaus_rtc_init(struct menelaus_chip *m)
+{
+ int alarm = (m->client->irq > 0);
+
+ /* assume 32KDETEN pin is pulled high */
+ if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) {
+ dev_dbg(&m->client->dev, "no 32k oscillator\n");
+ return;
+ }
+
+ /* support RTC alarm; it can issue wakeups */
+ if (alarm) {
+ if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ,
+ menelaus_rtc_alarm_work) < 0) {
+ dev_err(&m->client->dev, "can't handle RTC alarm\n");
+ return;
+ }
+ device_init_wakeup(&m->client->dev, 1);
+ }
+
+ /* be sure RTC is enabled; allow 1/sec irqs; leave 12hr mode alone */
+ m->rtc_control = menelaus_read_reg(MENELAUS_RTC_CTRL);
+ if (!(m->rtc_control & RTC_CTRL_RTC_EN)
+ || (m->rtc_control & RTC_CTRL_AL_EN)
+ || (m->rtc_control & RTC_CTRL_EVERY_MASK)) {
+ if (!(m->rtc_control & RTC_CTRL_RTC_EN)) {
+ dev_warn(&m->client->dev, "rtc clock needs setting\n");
+ m->rtc_control |= RTC_CTRL_RTC_EN;
+ }
+ m->rtc_control &= ~RTC_CTRL_EVERY_MASK;
+ m->rtc_control &= ~RTC_CTRL_AL_EN;
+ menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
+ }
+
+ m->rtc = rtc_device_register(DRIVER_NAME,
+ &m->client->dev,
+ &menelaus_rtc_ops, THIS_MODULE);
+ if (IS_ERR(m->rtc)) {
+ if (alarm) {
+ menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
+ device_init_wakeup(&m->client->dev, 0);
+ }
+ dev_err(&m->client->dev, "can't register RTC: %d\n",
+ (int) PTR_ERR(m->rtc));
+ the_menelaus->rtc = NULL;
+ }
+}
+
+#else
+
+static inline void menelaus_rtc_init(struct menelaus_chip *m)
+{
+ /* nothing */
+}
+
+#endif
+
+/*-----------------------------------------------------------------------*/
+
+static struct i2c_driver menelaus_i2c_driver;
+
+static int menelaus_probe(struct i2c_client *client)
+{
+ struct menelaus_chip *menelaus;
+ int rev = 0, val;
+ int err = 0;
+ struct menelaus_platform_data *menelaus_pdata =
+ client->dev.platform_data;
+
+ if (the_menelaus) {
+ dev_dbg(&client->dev, "only one %s for now\n",
+ DRIVER_NAME);
+ return -ENODEV;
+ }
+
+ menelaus = kzalloc(sizeof *menelaus, GFP_KERNEL);
+ if (!menelaus)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, menelaus);
+
+ the_menelaus = menelaus;
+ menelaus->client = client;
+
+ /* If a true probe check the device */
+ rev = menelaus_read_reg(MENELAUS_REV);
+ if (rev < 0) {
+ pr_err("device not found");
+ err = -ENODEV;
+ goto fail1;
+ }
+
+ /* Ack and disable all Menelaus interrupts */
+ menelaus_write_reg(MENELAUS_INT_ACK1, 0xff);
+ menelaus_write_reg(MENELAUS_INT_ACK2, 0xff);
+ menelaus_write_reg(MENELAUS_INT_MASK1, 0xff);
+ menelaus_write_reg(MENELAUS_INT_MASK2, 0xff);
+ menelaus->mask1 = 0xff;
+ menelaus->mask2 = 0xff;
+
+ /* Set output buffer strengths */
+ menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73);
+
+ if (client->irq > 0) {
+ err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
+ DRIVER_NAME, menelaus);
+ if (err) {
+ dev_dbg(&client->dev, "can't get IRQ %d, err %d",
+ client->irq, err);
+ goto fail1;
+ }
+ }
+
+ mutex_init(&menelaus->lock);
+ INIT_WORK(&menelaus->work, menelaus_work);
+
+ pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f);
+
+ val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
+ if (val < 0)
+ goto fail2;
+ if (val & (1 << 7))
+ menelaus->vcore_hw_mode = 1;
+ else
+ menelaus->vcore_hw_mode = 0;
+
+ if (menelaus_pdata != NULL && menelaus_pdata->late_init != NULL) {
+ err = menelaus_pdata->late_init(&client->dev);
+ if (err < 0)
+ goto fail2;
+ }
+
+ menelaus_rtc_init(menelaus);
+
+ return 0;
+fail2:
+ free_irq(client->irq, menelaus);
+ flush_scheduled_work();
+fail1:
+ kfree(menelaus);
+ return err;
+}
+
+static int __exit menelaus_remove(struct i2c_client *client)
+{
+ struct menelaus_chip *menelaus = i2c_get_clientdata(client);
+
+ free_irq(client->irq, menelaus);
+ kfree(menelaus);
+ i2c_set_clientdata(client, NULL);
+ the_menelaus = NULL;
+ return 0;
+}
+
+static struct i2c_driver menelaus_i2c_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+ .probe = menelaus_probe,
+ .remove = __exit_p(menelaus_remove),
+};
+
+static int __init menelaus_init(void)
+{
+ int res;
+
+ res = i2c_add_driver(&menelaus_i2c_driver);
+ if (res < 0) {
+ pr_err("driver registration failed\n");
+ return res;
+ }
+
+ return 0;
+}
+
+static void __exit menelaus_exit(void)
+{
+ i2c_del_driver(&menelaus_i2c_driver);
+
+ /* FIXME: Shutdown menelaus parts that can be shut down */
+}
+
+MODULE_AUTHOR("Texas Instruments, Inc. (and others)");
+MODULE_DESCRIPTION("I2C interface for Menelaus.");
+MODULE_LICENSE("GPL");
+
+module_init(menelaus_init);
+module_exit(menelaus_exit);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index f429be88c4f9..a21f585b1caa 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1258,19 +1258,25 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
}
-static int
+static void
idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
{
- /*
- * just support eject for now, it would not be hard to make the
- * REQ_BLOCK_PC support fully-featured
- */
- if (rq->cmd[0] != IDEFLOPPY_START_STOP_CMD)
- return 1;
-
idefloppy_init_pc(pc);
+ pc->callback = &idefloppy_rw_callback;
memcpy(pc->c, rq->cmd, sizeof(pc->c));
- return 0;
+ pc->rq = rq;
+ pc->b_count = rq->data_len;
+ if (rq->data_len && rq_data_dir(rq) == WRITE)
+ set_bit(PC_WRITING, &pc->flags);
+ pc->buffer = rq->data;
+ if (rq->bio)
+ set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+
+ /*
+ * possibly problematic, doesn't look like ide-floppy correctly
+ * handled scattered requests if dma fails...
+ */
+ pc->request_transfer = pc->buffer_size = rq->data_len;
}
/*
@@ -1317,10 +1323,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
pc = (idefloppy_pc_t *) rq->buffer;
} else if (blk_pc_request(rq)) {
pc = idefloppy_next_pc_storage(drive);
- if (idefloppy_blockpc_cmd(floppy, pc, rq)) {
- idefloppy_do_end_request(drive, 0, 0);
- return ide_stopped;
- }
+ idefloppy_blockpc_cmd(floppy, pc, rq);
} else {
blk_dump_rq_flags(rq,
"ide-floppy: unsupported command in queue");
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index cc5801399467..5a4c5ea12f89 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1073,14 +1073,14 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->hwif->next = hwif;
spin_unlock_irq(&ide_lock);
} else {
- hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
+ hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
+ GFP_KERNEL | __GFP_ZERO,
hwif_to_node(hwif->drives[0].hwif));
if (!hwgroup)
goto out_up;
hwif->hwgroup = hwgroup;
- memset(hwgroup, 0, sizeof(ide_hwgroup_t));
hwgroup->hwif = hwif->next = hwif;
hwgroup->rq = NULL;
hwgroup->handler = NULL;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c948a5c17a5d..077fb674a96d 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1173,7 +1173,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
case CDROMEJECT:
case CDROMCLOSETRAY:
- return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);
+ return scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, p);
case HDIO_GET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN))
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 0fc8c6e559e4..ee45259573c8 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -30,6 +30,7 @@
#include <linux/moduleparam.h>
#include <linux/bitops.h>
#include <linux/kdev_t.h>
+#include <linux/freezer.h>
#include <linux/suspend.h>
#include <linux/kthread.h>
#include <linux/preempt.h>
@@ -1128,8 +1129,6 @@ static int hpsbpkt_thread(void *__hi)
struct list_head tmp;
int may_schedule;
- current->flags |= PF_NOFREEZE;
-
while (!kthread_should_stop()) {
INIT_LIST_HEAD(&tmp);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 51a12062ed36..2ffd53461db6 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1699,6 +1699,7 @@ static int nodemgr_host_thread(void *__hi)
unsigned int g, generation = 0;
int i, reset_cycles = 0;
+ set_freezable();
/* Setup our device-model entries */
nodemgr_create_host_dev_files(host);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index eef415b12b2e..11f1d99db40b 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1591,7 +1591,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int i;
int size;
int size0 = 0;
- u32 f0;
+ u32 f0 = 0;
int ind;
u8 op0 = 0;
@@ -1946,7 +1946,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int i;
int size;
int size0 = 0;
- u32 f0;
+ u32 f0 = 0;
int ind;
u8 op0 = 0;
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index bd686a2a517d..20896d5e5f0e 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -445,6 +445,7 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)
static int gameport_thread(void *nothing)
{
+ set_freezable();
do {
gameport_handle_event();
wait_event_interruptible(gameport_wait,
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index a8f3bc1dff22..372ca4931194 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -384,6 +384,7 @@ static struct serio *serio_get_pending_child(struct serio *parent)
static int serio_thread(void *nothing)
{
+ set_freezable();
do {
serio_handle_event();
wait_event_interruptible(serio_wait,
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index f0cbcdb008ed..36f944019158 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -292,6 +292,7 @@ static int ucb1400_ts_thread(void *_ucb)
sched_setscheduler(tsk, SCHED_FIFO, &param);
+ set_freezable();
while (!kthread_should_stop()) {
unsigned int x, y, p;
long timeout;
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 3e088c42b222..cf906c8cee4d 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -2,12 +2,10 @@
# ISDN device configuration
#
-menu "ISDN subsystem"
- depends on !S390
-
-config ISDN
+menuconfig ISDN
tristate "ISDN support"
depends on NET
+ depends on !S390
---help---
ISDN ("Integrated Services Digital Networks", called RNIS in France)
is a special type of fully digital telephone service; it's mostly
@@ -21,9 +19,9 @@ config ISDN
Select this option if you want your kernel to support ISDN.
+if ISDN
menu "Old ISDN4Linux"
- depends on NET && ISDN
config ISDN_I4L
tristate "Old ISDN4Linux (deprecated)"
@@ -50,20 +48,21 @@ endif
endmenu
comment "CAPI subsystem"
- depends on NET && ISDN
config ISDN_CAPI
tristate "CAPI2.0 support"
- depends on ISDN
help
This provides the CAPI (Common ISDN Application Programming
Interface, a standard making it easy for programs to access ISDN
hardware, see <http://www.capi.org/>. This is needed for AVM's set
of active ISDN controllers like B1, T1, M1.
+if ISDN_CAPI
+
source "drivers/isdn/capi/Kconfig"
source "drivers/isdn/hardware/Kconfig"
-endmenu
+endif # ISDN_CAPI
+endif # ISDN
diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig
index c92f9d764fce..e1afd60924fb 100644
--- a/drivers/isdn/capi/Kconfig
+++ b/drivers/isdn/capi/Kconfig
@@ -3,7 +3,6 @@
#
config ISDN_DRV_AVMB1_VERBOSE_REASON
bool "Verbose reason code reporting"
- depends on ISDN_CAPI
default y
help
If you say Y here, the CAPI drivers will give verbose reasons for
@@ -12,7 +11,6 @@ config ISDN_DRV_AVMB1_VERBOSE_REASON
config CAPI_TRACE
bool "CAPI trace support"
- depends on ISDN_CAPI
default y
help
If you say Y here, the kernelcapi driver can make verbose traces
@@ -23,7 +21,7 @@ config CAPI_TRACE
config ISDN_CAPI_MIDDLEWARE
bool "CAPI2.0 Middleware support (EXPERIMENTAL)"
- depends on ISDN_CAPI && EXPERIMENTAL
+ depends on EXPERIMENTAL
help
This option will enhance the capabilities of the /dev/capi20
interface. It will provide a means of moving a data connection,
@@ -33,7 +31,6 @@ config ISDN_CAPI_MIDDLEWARE
config ISDN_CAPI_CAPI20
tristate "CAPI2.0 /dev/capi support"
- depends on ISDN_CAPI
help
This option will provide the CAPI 2.0 interface to userspace
applications via /dev/capi20. Applications should use the
@@ -56,7 +53,7 @@ config ISDN_CAPI_CAPIFS
config ISDN_CAPI_CAPIDRV
tristate "CAPI2.0 capidrv interface support"
- depends on ISDN_CAPI && ISDN_I4L
+ depends on ISDN_I4L
help
This option provides the glue code to hook up CAPI driven cards to
the legacy isdn4linux link layer. If you have a card which is
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 81661b8bd3a8..f449daef3eed 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -549,7 +549,7 @@ static int handle_minor_send(struct capiminor *mp)
capimsg_setu8 (skb->data, 5, CAPI_REQ);
capimsg_setu16(skb->data, 6, mp->msgid++);
capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
- capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
+ capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
capimsg_setu16(skb->data, 16, len); /* Data length */
capimsg_setu16(skb->data, 18, datahandle);
capimsg_setu16(skb->data, 20, 0); /* Flags */
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 3ed34f7a1c4f..9f73bc2727c2 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -258,7 +258,7 @@ static void recv_handler(struct work_struct *work)
if ((!ap) || (ap->release_in_progress))
return;
- down(&ap->recv_sem);
+ mutex_lock(&ap->recv_mtx);
while ((skb = skb_dequeue(&ap->recv_queue))) {
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
ap->nrecvdatapkt++;
@@ -267,7 +267,7 @@ static void recv_handler(struct work_struct *work)
ap->recv_message(ap, skb);
}
- up(&ap->recv_sem);
+ mutex_unlock(&ap->recv_mtx);
}
void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb)
@@ -547,7 +547,7 @@ u16 capi20_register(struct capi20_appl *ap)
ap->nsentctlpkt = 0;
ap->nsentdatapkt = 0;
ap->callback = NULL;
- init_MUTEX(&ap->recv_sem);
+ mutex_init(&ap->recv_mtx);
skb_queue_head_init(&ap->recv_queue);
INIT_WORK(&ap->recv_work, recv_handler);
ap->release_in_progress = 0;
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 31f4fd8b8b0a..845a797b0030 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -243,36 +243,15 @@ create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
// ---------------------------------------------------------------------------
-
-static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos)
-{
- struct capi_driver *drv = NULL;
- struct list_head *l;
- loff_t i;
-
- i = 0;
- list_for_each(l, &capi_drivers) {
- drv = list_entry(l, struct capi_driver, list);
- if (i++ == pos)
- return drv;
- }
- return NULL;
-}
-
static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
{
- struct capi_driver *drv;
read_lock(&capi_drivers_list_lock);
- drv = capi_driver_get_idx(*pos);
- return drv;
+ return seq_list_start(&capi_drivers, *pos);
}
static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct capi_driver *drv = (struct capi_driver *)v;
- ++*pos;
- if (drv->list.next == &capi_drivers) return NULL;
- return list_entry(drv->list.next, struct capi_driver, list);
+ return seq_list_next(v, &capi_drivers, pos);
}
static void capi_driver_stop(struct seq_file *seq, void *v)
@@ -282,7 +261,8 @@ static void capi_driver_stop(struct seq_file *seq, void *v)
static int capi_driver_show(struct seq_file *seq, void *v)
{
- struct capi_driver *drv = (struct capi_driver *)v;
+ struct capi_driver *drv = list_entry(v, struct capi_driver, list);
+
seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
return 0;
}
diff --git a/drivers/isdn/hardware/Kconfig b/drivers/isdn/hardware/Kconfig
index 139f19797713..30d028d24955 100644
--- a/drivers/isdn/hardware/Kconfig
+++ b/drivers/isdn/hardware/Kconfig
@@ -2,7 +2,6 @@
# ISDN hardware drivers
#
comment "CAPI hardware drivers"
- depends on NET && ISDN && ISDN_CAPI
source "drivers/isdn/hardware/avm/Kconfig"
diff --git a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig
index 29a32a8830c0..5dbcbe3a54a6 100644
--- a/drivers/isdn/hardware/avm/Kconfig
+++ b/drivers/isdn/hardware/avm/Kconfig
@@ -2,23 +2,22 @@
# ISDN AVM drivers
#
-menu "Active AVM cards"
- depends on NET && ISDN && ISDN_CAPI!=n
-
-config CAPI_AVM
- bool "Support AVM cards"
+menuconfig CAPI_AVM
+ bool "Active AVM cards"
help
Enable support for AVM active ISDN cards.
+if CAPI_AVM
+
config ISDN_DRV_AVMB1_B1ISA
tristate "AVM B1 ISA support"
- depends on CAPI_AVM && ISDN_CAPI && ISA
+ depends on ISA
help
Enable support for the ISA version of the AVM B1 card.
config ISDN_DRV_AVMB1_B1PCI
tristate "AVM B1 PCI support"
- depends on CAPI_AVM && ISDN_CAPI && PCI
+ depends on PCI
help
Enable support for the PCI version of the AVM B1 card.
@@ -30,14 +29,13 @@ config ISDN_DRV_AVMB1_B1PCIV4
config ISDN_DRV_AVMB1_T1ISA
tristate "AVM T1/T1-B ISA support"
- depends on CAPI_AVM && ISDN_CAPI && ISA
+ depends on ISA
help
Enable support for the AVM T1 T1B card.
Note: This is a PRI card and handle 30 B-channels.
config ISDN_DRV_AVMB1_B1PCMCIA
tristate "AVM B1/M1/M2 PCMCIA support"
- depends on CAPI_AVM && ISDN_CAPI
help
Enable support for the PCMCIA version of the AVM B1 card.
@@ -50,17 +48,16 @@ config ISDN_DRV_AVMB1_AVM_CS
config ISDN_DRV_AVMB1_T1PCI
tristate "AVM T1/T1-B PCI support"
- depends on CAPI_AVM && ISDN_CAPI && PCI
+ depends on PCI
help
Enable support for the AVM T1 T1B card.
Note: This is a PRI card and handle 30 B-channels.
config ISDN_DRV_AVMB1_C4
tristate "AVM C4/C2 support"
- depends on CAPI_AVM && ISDN_CAPI && PCI
+ depends on PCI
help
Enable support for the AVM C4/C2 PCI cards.
These cards handle 4/2 BRI ISDN lines (8/4 channels).
-endmenu
-
+endif # CAPI_AVM
diff --git a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig
index 01d4afd9d843..6082b6a5ced3 100644
--- a/drivers/isdn/hardware/eicon/Kconfig
+++ b/drivers/isdn/hardware/eicon/Kconfig
@@ -2,52 +2,50 @@
# ISDN DIVAS Eicon driver
#
-menu "Active Eicon DIVA Server cards"
- depends on NET && ISDN && ISDN_CAPI!=n
-
-config CAPI_EICON
- bool "Support Eicon cards"
+menuconfig CAPI_EICON
+ bool "Active Eicon DIVA Server cards"
help
Enable support for Eicon Networks active ISDN cards.
+if CAPI_EICON
+
config ISDN_DIVAS
tristate "Support Eicon DIVA Server cards"
- depends on CAPI_EICON && PROC_FS && PCI
+ depends on PROC_FS && PCI
help
Say Y here if you have an Eicon Networks DIVA Server PCI ISDN card.
In order to use this card, additional firmware is necessary, which
has to be downloaded into the card using the divactrl utility.
+if ISDN_DIVAS
+
config ISDN_DIVAS_BRIPCI
bool "DIVA Server BRI/PCI support"
- depends on ISDN_DIVAS
help
Enable support for DIVA Server BRI-PCI.
config ISDN_DIVAS_PRIPCI
bool "DIVA Server PRI/PCI support"
- depends on ISDN_DIVAS
help
Enable support for DIVA Server PRI-PCI.
config ISDN_DIVAS_DIVACAPI
tristate "DIVA CAPI2.0 interface support"
- depends on ISDN_DIVAS && ISDN_CAPI
help
You need this to provide the CAPI interface
for DIVA Server cards.
config ISDN_DIVAS_USERIDI
tristate "DIVA User-IDI interface support"
- depends on ISDN_DIVAS
help
Enable support for user-mode IDI interface.
config ISDN_DIVAS_MAINT
tristate "DIVA Maint driver support"
- depends on ISDN_DIVAS && m
+ depends on m
help
Enable Divas Maintenance driver.
-endmenu
+endif # ISDN_DIVAS
+endif # CAPI_EICON
diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
index 4cbc68cf4dba..db87d5105422 100644
--- a/drivers/isdn/hardware/eicon/idifunc.c
+++ b/drivers/isdn/hardware/eicon/idifunc.c
@@ -106,6 +106,7 @@ static void um_new_card(DESCRIPTOR * d)
} else {
DBG_ERR(("could not create user mode idi card %d",
adapter_nr));
+ diva_os_free(0, card);
}
}
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index 871310d56a6e..3d1bdc8431ad 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -255,54 +255,38 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0);
}
-static struct pci_dev *dev_a4t __devinitdata = NULL;
+static int __devinit a4t_pci_probe(struct pci_dev *dev_a4t,
+ struct IsdnCardState *cs,
+ u_int *found,
+ u_int *pci_memaddr)
+{
+ u16 sub_sys;
+ u16 sub_vendor;
+
+ sub_vendor = dev_a4t->subsystem_vendor;
+ sub_sys = dev_a4t->subsystem_device;
+ if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
+ if (pci_enable_device(dev_a4t))
+ return (0); /* end loop & function */
+ *found = 1;
+ *pci_memaddr = pci_resource_start(dev_a4t, 0);
+ cs->irq = dev_a4t->irq;
+ return (1); /* end loop */
+ }
-int __devinit
-setup_bkm_a4t(struct IsdnCard *card)
+ return (-1); /* continue looping */
+}
+
+static int __devinit a4t_cs_init(struct IsdnCard *card,
+ struct IsdnCardState *cs,
+ u_int pci_memaddr)
{
- struct IsdnCardState *cs = card->cs;
- char tmp[64];
- u_int pci_memaddr = 0, found = 0;
I20_REGISTER_FILE *pI20_Regs;
-#ifdef CONFIG_PCI
-#endif
-
- strcpy(tmp, bkm_a4t_revision);
- printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
- if (cs->typ == ISDN_CTYPE_BKM_A4T) {
- cs->subtyp = BKM_A4T;
- } else
- return (0);
-#ifdef CONFIG_PCI
- while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
- PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
- u16 sub_sys;
- u16 sub_vendor;
-
- sub_vendor = dev_a4t->subsystem_vendor;
- sub_sys = dev_a4t->subsystem_device;
- if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
- if (pci_enable_device(dev_a4t))
- return(0);
- found = 1;
- pci_memaddr = pci_resource_start(dev_a4t, 0);
- cs->irq = dev_a4t->irq;
- break;
- }
- }
- if (!found) {
- printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
- return (0);
- }
if (!cs->irq) { /* IRQ range check ?? */
printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
return (0);
}
- if (!pci_memaddr) {
- printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
- return (0);
- }
cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
/* Check suspecious address */
pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
@@ -317,11 +301,7 @@ setup_bkm_a4t(struct IsdnCard *card)
cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
cs->hw.ax.isac_ale = GCS_1;
cs->hw.ax.jade_ale = GCS_3;
-#else
- printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
- printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
- return (0);
-#endif /* CONFIG_PCI */
+
printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
CardType[card->typ], cs->hw.ax.base, cs->irq);
@@ -339,5 +319,43 @@ setup_bkm_a4t(struct IsdnCard *card)
ISACVersion(cs, "Telekom A4T:");
/* Jade version */
JadeVersion(cs, "Telekom A4T:");
+
return (1);
}
+
+static struct pci_dev *dev_a4t __devinitdata = NULL;
+
+int __devinit
+setup_bkm_a4t(struct IsdnCard *card)
+{
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+ u_int pci_memaddr = 0, found = 0;
+ int ret;
+
+ strcpy(tmp, bkm_a4t_revision);
+ printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+ cs->subtyp = BKM_A4T;
+ } else
+ return (0);
+
+ while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
+ PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
+ ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr);
+ if (!ret)
+ return (0);
+ if (ret > 0)
+ break;
+ }
+ if (!found) {
+ printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+ return (0);
+ }
+ if (!pci_memaddr) {
+ printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
+ return (0);
+ }
+
+ return a4t_cs_init(card, cs, pci_memaddr);
+}
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 8d53a7fd2671..5f7907e57090 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -361,11 +361,11 @@ module_param_array(io1, int, NULL, 0);
int nrcards;
-extern char *l1_revision;
-extern char *l2_revision;
-extern char *l3_revision;
-extern char *lli_revision;
-extern char *tei_revision;
+extern const char *l1_revision;
+extern const char *l2_revision;
+extern const char *l3_revision;
+extern const char *lli_revision;
+extern const char *tei_revision;
char *HiSax_getrev(const char *revision)
{
@@ -847,95 +847,10 @@ static int init_card(struct IsdnCardState *cs)
return 3;
}
-static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+static int hisax_cs_setup_card(struct IsdnCard *card)
{
- int ret = 0;
- struct IsdnCard *card = cards + cardnr;
- struct IsdnCardState *cs;
+ int ret;
- cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
- if (!cs) {
- printk(KERN_WARNING
- "HiSax: No memory for IsdnCardState(card %d)\n",
- cardnr + 1);
- goto out;
- }
- card->cs = cs;
- spin_lock_init(&cs->statlock);
- spin_lock_init(&cs->lock);
- cs->chanlimit = 2; /* maximum B-channel number */
- cs->logecho = 0; /* No echo logging */
- cs->cardnr = cardnr;
- cs->debug = L1_DEB_WARN;
- cs->HW_Flags = 0;
- cs->busy_flag = busy_flag;
- cs->irq_flags = I4L_IRQ_FLAG;
-#if TEI_PER_CARD
- if (card->protocol == ISDN_PTYPE_NI1)
- test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#else
- test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
- cs->protocol = card->protocol;
-
- if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
- printk(KERN_WARNING
- "HiSax: Card Type %d out of range\n", card->typ);
- goto outf_cs;
- }
- if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
- goto outf_cs;
- }
- if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for status_buf(card %d)\n",
- cardnr + 1);
- goto outf_dlog;
- }
- cs->stlist = NULL;
- cs->status_read = cs->status_buf;
- cs->status_write = cs->status_buf;
- cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
- cs->typ = card->typ;
-#ifdef MODULE
- cs->iif.owner = lockowner;
-#endif
- strcpy(cs->iif.id, id);
- cs->iif.channels = 2;
- cs->iif.maxbufsize = MAX_DATA_SIZE;
- cs->iif.hl_hdrlen = MAX_HEADER_LEN;
- cs->iif.features =
- ISDN_FEATURE_L2_X75I |
- ISDN_FEATURE_L2_HDLC |
- ISDN_FEATURE_L2_HDLC_56K |
- ISDN_FEATURE_L2_TRANS |
- ISDN_FEATURE_L3_TRANS |
-#ifdef CONFIG_HISAX_1TR6
- ISDN_FEATURE_P_1TR6 |
-#endif
-#ifdef CONFIG_HISAX_EURO
- ISDN_FEATURE_P_EURO |
-#endif
-#ifdef CONFIG_HISAX_NI1
- ISDN_FEATURE_P_NI1 |
-#endif
- 0;
-
- cs->iif.command = HiSax_command;
- cs->iif.writecmd = NULL;
- cs->iif.writebuf_skb = HiSax_writebuf_skb;
- cs->iif.readstat = HiSax_readstatus;
- register_isdn(&cs->iif);
- cs->myid = cs->iif.channels;
- printk(KERN_INFO
- "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
- (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
- (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
- (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
- (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
- "NONE", cs->iif.id, cs->myid);
switch (card->typ) {
#if CARD_TELES0
case ISDN_CTYPE_16_0:
@@ -1094,13 +1009,115 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
printk(KERN_WARNING
"HiSax: Support for %s Card not selected\n",
CardType[card->typ]);
- ll_unload(cs);
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int hisax_cs_new(int cardnr, char *id, struct IsdnCard *card,
+ struct IsdnCardState **cs_out, int *busy_flag,
+ struct module *lockowner)
+{
+ struct IsdnCardState *cs;
+
+ *cs_out = NULL;
+
+ cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+ if (!cs) {
+ printk(KERN_WARNING
+ "HiSax: No memory for IsdnCardState(card %d)\n",
+ cardnr + 1);
+ goto out;
+ }
+ card->cs = cs;
+ spin_lock_init(&cs->statlock);
+ spin_lock_init(&cs->lock);
+ cs->chanlimit = 2; /* maximum B-channel number */
+ cs->logecho = 0; /* No echo logging */
+ cs->cardnr = cardnr;
+ cs->debug = L1_DEB_WARN;
+ cs->HW_Flags = 0;
+ cs->busy_flag = busy_flag;
+ cs->irq_flags = I4L_IRQ_FLAG;
+#if TEI_PER_CARD
+ if (card->protocol == ISDN_PTYPE_NI1)
+ test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#else
+ test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#endif
+ cs->protocol = card->protocol;
+
+ if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
+ printk(KERN_WARNING
+ "HiSax: Card Type %d out of range\n", card->typ);
goto outf_cs;
}
- if (!ret) {
- ll_unload(cs);
+ if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
goto outf_cs;
}
+ if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for status_buf(card %d)\n",
+ cardnr + 1);
+ goto outf_dlog;
+ }
+ cs->stlist = NULL;
+ cs->status_read = cs->status_buf;
+ cs->status_write = cs->status_buf;
+ cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+ cs->typ = card->typ;
+#ifdef MODULE
+ cs->iif.owner = lockowner;
+#endif
+ strcpy(cs->iif.id, id);
+ cs->iif.channels = 2;
+ cs->iif.maxbufsize = MAX_DATA_SIZE;
+ cs->iif.hl_hdrlen = MAX_HEADER_LEN;
+ cs->iif.features =
+ ISDN_FEATURE_L2_X75I |
+ ISDN_FEATURE_L2_HDLC |
+ ISDN_FEATURE_L2_HDLC_56K |
+ ISDN_FEATURE_L2_TRANS |
+ ISDN_FEATURE_L3_TRANS |
+#ifdef CONFIG_HISAX_1TR6
+ ISDN_FEATURE_P_1TR6 |
+#endif
+#ifdef CONFIG_HISAX_EURO
+ ISDN_FEATURE_P_EURO |
+#endif
+#ifdef CONFIG_HISAX_NI1
+ ISDN_FEATURE_P_NI1 |
+#endif
+ 0;
+
+ cs->iif.command = HiSax_command;
+ cs->iif.writecmd = NULL;
+ cs->iif.writebuf_skb = HiSax_writebuf_skb;
+ cs->iif.readstat = HiSax_readstatus;
+ register_isdn(&cs->iif);
+ cs->myid = cs->iif.channels;
+
+ *cs_out = cs;
+ return 1; /* success */
+
+outf_dlog:
+ kfree(cs->dlog);
+outf_cs:
+ kfree(cs);
+ card->cs = NULL;
+out:
+ return 0; /* error */
+}
+
+static int hisax_cs_setup(int cardnr, struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
+ int ret;
+
if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
ll_unload(cs);
@@ -1143,11 +1160,41 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
if (!test_bit(HW_ISAR, &cs->HW_Flags))
ll_run(cs, 0);
- ret = 1;
+ return 1;
+
+outf_cs:
+ kfree(cs);
+ card->cs = NULL;
+ return ret;
+}
+
+static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+{
+ int ret;
+ struct IsdnCard *card = cards + cardnr;
+ struct IsdnCardState *cs;
+
+ ret = hisax_cs_new(cardnr, id, card, &cs, busy_flag, lockowner);
+ if (!ret)
+ return 0;
+
+ printk(KERN_INFO
+ "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
+ (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
+ (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
+ (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
+ (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+ "NONE", cs->iif.id, cs->myid);
+
+ ret = hisax_cs_setup_card(card);
+ if (!ret) {
+ ll_unload(cs);
+ goto outf_cs;
+ }
+
+ ret = hisax_cs_setup(cardnr, card, cs);
goto out;
- outf_dlog:
- kfree(cs->dlog);
outf_cs:
kfree(cs);
card->cs = NULL;
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index b45de9d408d1..b73027ff50e8 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -300,98 +300,72 @@ enpci_interrupt(int intno, void *dev_id)
return IRQ_HANDLED;
}
-
-static struct pci_dev *dev_netjet __devinitdata = NULL;
-
-/* called by config.c */
-int __devinit
-setup_enternow_pci(struct IsdnCard *card)
+static int __devinit en_pci_probe(struct pci_dev *dev_netjet,
+ struct IsdnCardState *cs)
{
- int bytecnt;
- struct IsdnCardState *cs = card->cs;
- char tmp[64];
-
-#ifdef CONFIG_PCI
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
- strcpy(tmp, enternow_pci_rev);
- printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
- if (cs->typ != ISDN_CTYPE_ENTERNOW)
+ if (pci_enable_device(dev_netjet))
return(0);
- test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-
- for ( ;; )
- {
- if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
- PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
- if (pci_enable_device(dev_netjet))
- return(0);
- cs->irq = dev_netjet->irq;
- if (!cs->irq) {
- printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
- return(0);
- }
- cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
- if (!cs->hw.njet.base) {
- printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
- return(0);
- }
- /* checks Sub-Vendor ID because system crashes with Traverse-Card */
- if ((dev_netjet->subsystem_vendor != 0x55) ||
- (dev_netjet->subsystem_device != 0x02)) {
- printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
- printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
- return(0);
- }
- } else {
- printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
- return(0);
- }
-
- cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
- cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
-
- /* Reset an */
- cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff
- outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
- /* 20 ms Pause */
- mdelay(20);
+ cs->irq = dev_netjet->irq;
+ if (!cs->irq) {
+ printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
+ return(0);
+ }
+ cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+ if (!cs->hw.njet.base) {
+ printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
+ return(0);
+ }
+ /* checks Sub-Vendor ID because system crashes with Traverse-Card */
+ if ((dev_netjet->subsystem_vendor != 0x55) ||
+ (dev_netjet->subsystem_device != 0x02)) {
+ printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
+ printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
+ return(0);
+ }
- cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */
- outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
- mdelay(10);
+ return(1);
+}
- cs->hw.njet.auxd = 0x00; // war 0xc0
- cs->hw.njet.dmactrl = 0;
+static void __devinit en_cs_init(struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
+ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+ cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
- outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
- outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
- outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
+ /* Reset an */
+ cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff
+ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
+ /* 20 ms Pause */
+ mdelay(20);
- break;
- }
-#else
+ cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */
+ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
+ mdelay(10);
- printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n");
- printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n");
- return (0);
+ cs->hw.njet.auxd = 0x00; // war 0xc0
+ cs->hw.njet.dmactrl = 0;
-#endif /* CONFIG_PCI */
+ outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
+ outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
+ outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
+}
- bytecnt = 256;
+static int __devinit en_cs_init_rest(struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
+ const int bytecnt = 256;
printk(KERN_INFO
"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) {
printk(KERN_WARNING
- "HiSax: %s config port %lx-%lx already in use\n",
- CardType[card->typ],
- cs->hw.njet.base,
- cs->hw.njet.base + bytecnt);
+ "HiSax: enter:now config port %lx-%lx already in use\n",
+ cs->hw.njet.base,
+ cs->hw.njet.base + bytecnt);
return (0);
}
+
setup_Amd7930(cs);
cs->hw.njet.last_is0 = 0;
/* macro rByteAMD */
@@ -407,5 +381,44 @@ setup_enternow_pci(struct IsdnCard *card)
cs->irq_func = &enpci_interrupt;
cs->irq_flags |= IRQF_SHARED;
- return (1);
+ return (1);
+}
+
+static struct pci_dev *dev_netjet __devinitdata = NULL;
+
+/* called by config.c */
+int __devinit
+setup_enternow_pci(struct IsdnCard *card)
+{
+ int ret;
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+
+ strcpy(tmp, enternow_pci_rev);
+ printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_ENTERNOW)
+ return(0);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+ for ( ;; )
+ {
+ if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+ PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
+ ret = en_pci_probe(dev_netjet, cs);
+ if (!ret)
+ return(0);
+ } else {
+ printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
+ return(0);
+ }
+
+ en_cs_init(card, cs);
+ break;
+ }
+
+ return en_cs_init_rest(card, cs);
}
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 8a48a3ce0a55..077080aca799 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -6,7 +6,7 @@
* based on existing driver for CCD hfc ISA cards
* Copyright by Werner Cornelius <werner@isdn4linux.de>
* by Karsten Keil <keil@isdn4linux.de>
- *
+ *
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
@@ -67,8 +67,6 @@ static const PCI_ENTRY id_list[] =
};
-#ifdef CONFIG_PCI
-
/******************************************/
/* free hardware resources used by driver */
/******************************************/
@@ -237,7 +235,7 @@ static void hfcpci_clear_fifo_rx(struct IsdnCardState *cs, int fifo)
if (fifo_state)
cs->hw.hfcpci.fifo_en |= fifo_state;
Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
-}
+}
/***************************************/
/* clear the desired B-channel tx fifo */
@@ -263,7 +261,7 @@ static void hfcpci_clear_fifo_tx(struct IsdnCardState *cs, int fifo)
if (fifo_state)
cs->hw.hfcpci.fifo_en |= fifo_state;
Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
-}
+}
/*********************************************/
/* read a complete B-frame out of the buffer */
@@ -511,7 +509,6 @@ main_rec_hfcpci(struct BCState *bcs)
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
if (count && receive)
goto Begin;
- return;
}
/**************************/
@@ -582,7 +579,6 @@ hfcpci_fill_dfifo(struct IsdnCardState *cs)
dev_kfree_skb_any(cs->tx_skb);
cs->tx_skb = NULL;
- return;
}
/**************************/
@@ -729,7 +725,6 @@ hfcpci_fill_fifo(struct BCState *bcs)
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
- return;
}
/**********************************************/
@@ -924,7 +919,6 @@ receive_emsg(struct IsdnCardState *cs)
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
if (count && receive)
goto Begin;
- return;
} /* receive_emsg */
/*********************/
@@ -1350,13 +1344,13 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc)
cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
}
if (fifo2) {
- cs->hw.hfcpci.last_bfifo_cnt[1] = 0;
+ cs->hw.hfcpci.last_bfifo_cnt[1] = 0;
cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
cs->hw.hfcpci.ctmt &= ~2;
cs->hw.hfcpci.conn &= ~0x18;
} else {
- cs->hw.hfcpci.last_bfifo_cnt[0] = 0;
+ cs->hw.hfcpci.last_bfifo_cnt[0] = 0;
cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
cs->hw.hfcpci.ctmt &= ~1;
@@ -1642,8 +1636,6 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
/* this variable is used as card index when more than one cards are present */
static struct pci_dev *dev_hfcpci __devinitdata = NULL;
-#endif /* CONFIG_PCI */
-
int __devinit
setup_hfcpci(struct IsdnCard *card)
{
@@ -1656,96 +1648,99 @@ setup_hfcpci(struct IsdnCard *card)
#ifdef __BIG_ENDIAN
#error "not running on big endian machines now"
#endif
+
strcpy(tmp, hfcpci_revision);
printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#ifdef CONFIG_PCI
+
cs->hw.hfcpci.int_s1 = 0;
cs->dc.hfcpci.ph_state = 0;
cs->hw.hfcpci.fifo = 255;
- if (cs->typ == ISDN_CTYPE_HFC_PCI) {
- i = 0;
- while (id_list[i].vendor_id) {
- tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
- id_list[i].device_id,
- dev_hfcpci);
- i++;
- if (tmp_hfcpci) {
- if (pci_enable_device(tmp_hfcpci))
- continue;
- pci_set_master(tmp_hfcpci);
- if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
- continue;
- else
- break;
- }
- }
-
+ if (cs->typ != ISDN_CTYPE_HFC_PCI)
+ return(0);
+
+ i = 0;
+ while (id_list[i].vendor_id) {
+ tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+ id_list[i].device_id,
+ dev_hfcpci);
+ i++;
if (tmp_hfcpci) {
- i--;
- dev_hfcpci = tmp_hfcpci; /* old device */
- cs->hw.hfcpci.dev = dev_hfcpci;
- cs->irq = dev_hfcpci->irq;
- if (!cs->irq) {
- printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
- return (0);
- }
- cs->hw.hfcpci.pci_io = (char *)(unsigned long)dev_hfcpci->resource[1].start;
- printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
- } else {
- printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
- return (0);
- }
- if (!cs->hw.hfcpci.pci_io) {
- printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
- return (0);
- }
- /* Allocate memory for FIFOS */
- /* Because the HFC-PCI needs a 32K physical alignment, we */
- /* need to allocate the double mem and align the address */
- if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
- printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
- return 0;
+ if (pci_enable_device(tmp_hfcpci))
+ continue;
+ pci_set_master(tmp_hfcpci);
+ if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
+ continue;
+ else
+ break;
}
- cs->hw.hfcpci.fifos = (void *)
- (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
- pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
- cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
- printk(KERN_INFO
- "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
- cs->hw.hfcpci.pci_io,
- cs->hw.hfcpci.fifos,
- (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
- cs->irq, HZ);
- spin_lock_irqsave(&cs->lock, flags);
- pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
- cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
- cs->hw.hfcpci.int_m1 = 0;
- Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
- Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
- /* At this point the needed PCI config is done */
- /* fifos are still not enabled */
- INIT_WORK(&cs->tqueue, hfcpci_bh);
- cs->setstack_d = setstack_hfcpci;
- cs->BC_Send_Data = &hfcpci_send_data;
- cs->readisac = NULL;
- cs->writeisac = NULL;
- cs->readisacfifo = NULL;
- cs->writeisacfifo = NULL;
- cs->BC_Read_Reg = NULL;
- cs->BC_Write_Reg = NULL;
- cs->irq_func = &hfcpci_interrupt;
- cs->irq_flags |= IRQF_SHARED;
- cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
- cs->hw.hfcpci.timer.data = (long) cs;
- init_timer(&cs->hw.hfcpci.timer);
- cs->cardmsg = &hfcpci_card_msg;
- cs->auxcmd = &hfcpci_auxcmd;
- spin_unlock_irqrestore(&cs->lock, flags);
- return (1);
- } else
- return (0); /* no valid card type */
-#else
- printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
- return (0);
-#endif /* CONFIG_PCI */
+ }
+
+ if (!tmp_hfcpci) {
+ printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+ return (0);
+ }
+
+ i--;
+ dev_hfcpci = tmp_hfcpci; /* old device */
+ cs->hw.hfcpci.dev = dev_hfcpci;
+ cs->irq = dev_hfcpci->irq;
+ if (!cs->irq) {
+ printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+ return (0);
+ }
+ cs->hw.hfcpci.pci_io = (char *)(unsigned long)dev_hfcpci->resource[1].start;
+ printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
+
+ if (!cs->hw.hfcpci.pci_io) {
+ printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
+ return (0);
+ }
+ /* Allocate memory for FIFOS */
+ /* Because the HFC-PCI needs a 32K physical alignment, we */
+ /* need to allocate the double mem and align the address */
+ if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
+ printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+ return 0;
+ }
+ cs->hw.hfcpci.fifos = (void *)
+ (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
+ pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+ cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
+ printk(KERN_INFO
+ "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
+ cs->hw.hfcpci.pci_io,
+ cs->hw.hfcpci.fifos,
+ (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
+ cs->irq, HZ);
+
+ spin_lock_irqsave(&cs->lock, flags);
+
+ pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
+ cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
+ cs->hw.hfcpci.int_m1 = 0;
+ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+ /* At this point the needed PCI config is done */
+ /* fifos are still not enabled */
+
+ INIT_WORK(&cs->tqueue, hfcpci_bh);
+ cs->setstack_d = setstack_hfcpci;
+ cs->BC_Send_Data = &hfcpci_send_data;
+ cs->readisac = NULL;
+ cs->writeisac = NULL;
+ cs->readisacfifo = NULL;
+ cs->writeisacfifo = NULL;
+ cs->BC_Read_Reg = NULL;
+ cs->BC_Write_Reg = NULL;
+ cs->irq_func = &hfcpci_interrupt;
+ cs->irq_flags |= IRQF_SHARED;
+ cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
+ cs->hw.hfcpci.timer.data = (long) cs;
+ init_timer(&cs->hw.hfcpci.timer);
+ cs->cardmsg = &hfcpci_card_msg;
+ cs->auxcmd = &hfcpci_auxcmd;
+
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ return (1);
}
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index c09ffb135330..fa2db87667c8 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -148,107 +148,87 @@ NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_netjet __devinitdata = NULL;
-
-int __devinit
-setup_netjet_s(struct IsdnCard *card)
+static int __devinit njs_pci_probe(struct pci_dev *dev_netjet,
+ struct IsdnCardState *cs)
{
- int bytecnt,cfg;
- struct IsdnCardState *cs = card->cs;
- char tmp[64];
+ int cfg;
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
- strcpy(tmp, NETjet_S_revision);
- printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
- if (cs->typ != ISDN_CTYPE_NETJET_S)
+ if (pci_enable_device(dev_netjet))
return(0);
- test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ pci_set_master(dev_netjet);
+ cs->irq = dev_netjet->irq;
+ if (!cs->irq) {
+ printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
+ return(0);
+ }
+ cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+ if (!cs->hw.njet.base) {
+ printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
+ return(0);
+ }
+ /* the TJ300 and TJ320 must be detected, the IRQ handling is different
+ * unfortunatly the chips use the same device ID, but the TJ320 has
+ * the bit20 in status PCI cfg register set
+ */
+ pci_read_config_dword(dev_netjet, 0x04, &cfg);
+ if (cfg & 0x00100000)
+ cs->subtyp = 1; /* TJ320 */
+ else
+ cs->subtyp = 0; /* TJ300 */
+ /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+ if ((dev_netjet->subsystem_vendor == 0x55) &&
+ (dev_netjet->subsystem_device == 0x02)) {
+ printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
+ printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
+ return(0);
+ }
+ /* end new code */
-#ifdef CONFIG_PCI
+ return(1);
+}
- for ( ;; )
- {
- if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
- PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
- if (pci_enable_device(dev_netjet))
- return(0);
- pci_set_master(dev_netjet);
- cs->irq = dev_netjet->irq;
- if (!cs->irq) {
- printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
- return(0);
- }
- cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
- if (!cs->hw.njet.base) {
- printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
- return(0);
- }
- /* the TJ300 and TJ320 must be detected, the IRQ handling is different
- * unfortunatly the chips use the same device ID, but the TJ320 has
- * the bit20 in status PCI cfg register set
- */
- pci_read_config_dword(dev_netjet, 0x04, &cfg);
- if (cfg & 0x00100000)
- cs->subtyp = 1; /* TJ320 */
- else
- cs->subtyp = 0; /* TJ300 */
- /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
- if ((dev_netjet->subsystem_vendor == 0x55) &&
- (dev_netjet->subsystem_device == 0x02)) {
- printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
- printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
- return(0);
- }
- /* end new code */
- } else {
- printk(KERN_WARNING "NETjet-S: No PCI card found\n");
- return(0);
- }
+static int __devinit njs_cs_init(struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
- cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
- cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+ cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
- cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
- byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
- mdelay(10);
+ cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
+ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ mdelay(10);
- cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
- byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
- mdelay(10);
+ cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
+ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ mdelay(10);
- cs->hw.njet.auxd = 0xC0;
- cs->hw.njet.dmactrl = 0;
+ cs->hw.njet.auxd = 0xC0;
+ cs->hw.njet.dmactrl = 0;
- byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
- byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
- byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+ byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+ byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+ byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
- switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
- {
- case 0 :
- break;
+ switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
+ {
+ case 0 :
+ return 1; /* end loop */
- case 3 :
- printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
- continue;
+ case 3 :
+ printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
+ return -1; /* continue looping */
- default :
- printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
- return 0;
- }
- break;
+ default :
+ printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
+ return 0; /* end loop & function */
}
-#else
-
- printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n");
- printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n");
- return (0);
-
-#endif /* CONFIG_PCI */
+ return 1; /* end loop */
+}
- bytecnt = 256;
+static int __devinit njs_cs_init_rest(struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
+ const int bytecnt = 256;
printk(KERN_INFO
"NETjet-S: %s card configured at %#lx IRQ %d\n",
@@ -273,5 +253,47 @@ setup_netjet_s(struct IsdnCard *card)
cs->irq_func = &netjet_s_interrupt;
cs->irq_flags |= IRQF_SHARED;
ISACVersion(cs, "NETjet-S:");
+
return (1);
}
+
+static struct pci_dev *dev_netjet __devinitdata = NULL;
+
+int __devinit
+setup_netjet_s(struct IsdnCard *card)
+{
+ int ret;
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+ strcpy(tmp, NETjet_S_revision);
+ printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_NETJET_S)
+ return(0);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+ for ( ;; )
+ {
+ if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+ PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
+ ret = njs_pci_probe(dev_netjet, cs);
+ if (!ret)
+ return(0);
+ } else {
+ printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+ return(0);
+ }
+
+ ret = njs_cs_init(card, cs);
+ if (!ret)
+ return(0);
+ if (ret > 0)
+ break;
+ /* otherwise, ret < 0, continue looping */
+ }
+
+ return njs_cs_init_rest(card, cs);
+}
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 8202cf34ecae..f017d3816b1d 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -128,93 +128,69 @@ NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_netjet __devinitdata = NULL;
-
-int __devinit
-setup_netjet_u(struct IsdnCard *card)
+static int __devinit nju_pci_probe(struct pci_dev *dev_netjet,
+ struct IsdnCardState *cs)
{
- int bytecnt;
- struct IsdnCardState *cs = card->cs;
- char tmp[64];
-#ifdef CONFIG_PCI
-#endif
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
- strcpy(tmp, NETjet_U_revision);
- printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
- if (cs->typ != ISDN_CTYPE_NETJET_U)
+ if (pci_enable_device(dev_netjet))
return(0);
- test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-
-#ifdef CONFIG_PCI
+ pci_set_master(dev_netjet);
+ cs->irq = dev_netjet->irq;
+ if (!cs->irq) {
+ printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
+ return(0);
+ }
+ cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
+ if (!cs->hw.njet.base) {
+ printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
+ return(0);
+ }
- for ( ;; )
- {
- if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
- PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
- if (pci_enable_device(dev_netjet))
- return(0);
- pci_set_master(dev_netjet);
- cs->irq = dev_netjet->irq;
- if (!cs->irq) {
- printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
- return(0);
- }
- cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
- if (!cs->hw.njet.base) {
- printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
- return(0);
- }
- } else {
- printk(KERN_WARNING "NETspider-U: No PCI card found\n");
- return(0);
- }
+ return (1);
+}
- cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
- cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
- mdelay(10);
+static int __devinit nju_cs_init(struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
+ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+ cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+ mdelay(10);
- cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
- byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
- mdelay(10);
+ cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
+ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ mdelay(10);
- cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
- byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
- mdelay(10);
+ cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
+ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ mdelay(10);
- cs->hw.njet.auxd = 0xC0;
- cs->hw.njet.dmactrl = 0;
+ cs->hw.njet.auxd = 0xC0;
+ cs->hw.njet.dmactrl = 0;
- byteout(cs->hw.njet.auxa, 0);
- byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
- byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
- byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+ byteout(cs->hw.njet.auxa, 0);
+ byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+ byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+ byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
- switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
- {
- case 3 :
- break;
+ switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
+ {
+ case 3 :
+ return 1; /* end loop */
- case 0 :
- printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
- continue;
+ case 0 :
+ printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
+ return -1; /* continue looping */
- default :
- printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
- return 0;
- }
- break;
+ default :
+ printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
+ return 0; /* end loop & function */
}
-#else
-
- printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n");
- printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n");
- return (0);
-
-#endif /* CONFIG_PCI */
+ return 1; /* end loop */
+}
- bytecnt = 256;
+static int __devinit nju_cs_init_rest(struct IsdnCard *card,
+ struct IsdnCardState *cs)
+{
+ const int bytecnt = 256;
printk(KERN_INFO
"NETspider-U: PCI card configured at %#lx IRQ %d\n",
@@ -239,5 +215,48 @@ setup_netjet_u(struct IsdnCard *card)
cs->irq_func = &netjet_u_interrupt;
cs->irq_flags |= IRQF_SHARED;
ICCVersion(cs, "NETspider-U:");
+
return (1);
}
+
+static struct pci_dev *dev_netjet __devinitdata = NULL;
+
+int __devinit
+setup_netjet_u(struct IsdnCard *card)
+{
+ int ret;
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+
+ strcpy(tmp, NETjet_U_revision);
+ printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_NETJET_U)
+ return(0);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
+ for ( ;; )
+ {
+ if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+ PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
+ ret = nju_pci_probe(dev_netjet, cs);
+ if (!ret)
+ return(0);
+ } else {
+ printk(KERN_WARNING "NETspider-U: No PCI card found\n");
+ return(0);
+ }
+
+ ret = nju_cs_init(card, cs);
+ if (!ret)
+ return (0);
+ if (ret > 0)
+ break;
+ /* ret < 0 == continue looping */
+ }
+
+ return nju_cs_init_rest(card, cs);
+}
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 030d1625c5c6..ad06f3cc60fb 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -451,6 +451,9 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
spin_unlock_irqrestore(&cs->lock, flags);
return(0);
case CARD_RELEASE:
+ if (cs->hw.sedl.bus == SEDL_BUS_PCI)
+ /* disable all IRQ */
+ byteout(cs->hw.sedl.cfg_reg+ 5, 0);
if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
spin_lock_irqsave(&cs->lock, flags);
writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
@@ -468,6 +471,9 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
case CARD_INIT:
spin_lock_irqsave(&cs->lock, flags);
+ if (cs->hw.sedl.bus == SEDL_BUS_PCI)
+ /* enable all IRQ */
+ byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
reset_sedlbauer(cs);
if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
clear_pending_isac_ints(cs);
@@ -667,7 +673,7 @@ setup_sedlbauer(struct IsdnCard *card)
byteout(cs->hw.sedl.cfg_reg, 0xff);
byteout(cs->hw.sedl.cfg_reg, 0x00);
byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
- byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+ byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */
byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
mdelay(2);
byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 3ef567b99c74..e91c187992dd 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -86,7 +86,6 @@ config ISDN_X25
menu "ISDN feature submodules"
- depends on ISDN
config ISDN_DRV_LOOP
tristate "isdnloop support"
@@ -100,7 +99,7 @@ config ISDN_DRV_LOOP
config ISDN_DIVERSION
tristate "Support isdn diversion services"
- depends on ISDN && ISDN_I4L
+ depends on ISDN_I4L
help
This option allows you to use some supplementary diversion
services in conjunction with the HiSax driver on an EURO/DSS1
@@ -120,13 +119,13 @@ config ISDN_DIVERSION
endmenu
comment "ISDN4Linux hardware drivers"
- depends on NET && ISDN && ISDN_I4L
+ depends on ISDN_I4L
source "drivers/isdn/hisax/Kconfig"
menu "Active cards"
- depends on NET && ISDN && ISDN_I4L!=n
+ depends on ISDN_I4L!=n
source "drivers/isdn/icn/Kconfig"
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 34c3572b3cd1..ccb9627c04f3 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -2987,13 +2987,13 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
case CPU_UP_CANCELED_FROZEN:
printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
cpu);
- on_cpu(cpu, hardware_disable, NULL, 0, 1);
+ smp_call_function_single(cpu, hardware_disable, NULL, 0, 1);
break;
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
cpu);
- on_cpu(cpu, hardware_enable, NULL, 0, 1);
+ smp_call_function_single(cpu, hardware_enable, NULL, 0, 1);
break;
}
return NOTIFY_OK;
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index adfea3c7c62a..bc77c5e2ca9f 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -248,21 +248,15 @@ static int adb_scan_bus(void)
static int
adb_probe_task(void *x)
{
- sigset_t blocked;
-
strcpy(current->comm, "kadbprobe");
- sigfillset(&blocked);
- sigprocmask(SIG_BLOCK, &blocked, NULL);
- flush_signals(current);
-
printk(KERN_INFO "adb: starting probe task...\n");
do_adb_reset_bus();
printk(KERN_INFO "adb: finished probe task...\n");
-
+
adb_probe_task_pid = 0;
up(&adb_probe_mutex);
-
+
return 0;
}
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index bd55e6ab99fc..f25685b9b7cf 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -335,6 +335,7 @@ static int monitor_task(void *arg)
{
struct thermostat* th = arg;
+ set_freezable();
while(!kthread_should_stop()) {
try_to_freeze();
msleep_interruptible(2000);
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 4fcb245ba184..e18d265d5d33 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -92,6 +92,7 @@ static int wf_thread_func(void *data)
DBG("wf: thread started\n");
+ set_freezable();
while(!kthread_should_stop()) {
if (time_after_eq(jiffies, next)) {
wf_notify(WF_EVENT_TICK, NULL);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 64bf3a81db93..531d4d17d011 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -2,19 +2,17 @@
# Block device driver configuration
#
-if BLOCK
-
-menu "Multi-device support (RAID and LVM)"
-
-config MD
+menuconfig MD
bool "Multiple devices driver support (RAID and LVM)"
+ depends on BLOCK
help
Support multiple physical spindles through a single logical device.
Required for RAID and logical volume management.
+if MD
+
config BLK_DEV_MD
tristate "RAID support"
- depends on MD
---help---
This driver lets you combine several hard disk partitions into one
logical block device. This can be used to simply append one
@@ -191,7 +189,6 @@ config MD_FAULTY
config BLK_DEV_DM
tristate "Device mapper support"
- depends on MD
---help---
Device-mapper is a low level volume manager. It works by allowing
people to specify mappings for ranges of logical sectors. Various
@@ -279,6 +276,4 @@ config DM_DELAY
If unsure, say N.
-endmenu
-
-endif
+endif # MD
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 9620d452d030..927cb34c4805 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -268,6 +268,31 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
if (page->index == bitmap->file_pages-1)
size = roundup(bitmap->last_page_size,
bdev_hardsect_size(rdev->bdev));
+ /* Just make sure we aren't corrupting data or
+ * metadata
+ */
+ if (bitmap->offset < 0) {
+ /* DATA BITMAP METADATA */
+ if (bitmap->offset
+ + page->index * (PAGE_SIZE/512)
+ + size/512 > 0)
+ /* bitmap runs in to metadata */
+ return -EINVAL;
+ if (rdev->data_offset + mddev->size*2
+ > rdev->sb_offset*2 + bitmap->offset)
+ /* data runs in to bitmap */
+ return -EINVAL;
+ } else if (rdev->sb_offset*2 < rdev->data_offset) {
+ /* METADATA BITMAP DATA */
+ if (rdev->sb_offset*2
+ + bitmap->offset
+ + page->index*(PAGE_SIZE/512) + size/512
+ > rdev->data_offset)
+ /* bitmap runs in to data */
+ return -EINVAL;
+ } else {
+ /* DATA METADATA BITMAP - no problems */
+ }
md_super_write(mddev, rdev,
(rdev->sb_offset<<1) + bitmap->offset
+ page->index * (PAGE_SIZE/512),
@@ -280,32 +305,38 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
return 0;
}
+static void bitmap_file_kick(struct bitmap *bitmap);
/*
* write out a page to a file
*/
-static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+static void write_page(struct bitmap *bitmap, struct page *page, int wait)
{
struct buffer_head *bh;
- if (bitmap->file == NULL)
- return write_sb_page(bitmap, page, wait);
+ if (bitmap->file == NULL) {
+ switch (write_sb_page(bitmap, page, wait)) {
+ case -EINVAL:
+ bitmap->flags |= BITMAP_WRITE_ERROR;
+ }
+ } else {
- bh = page_buffers(page);
+ bh = page_buffers(page);
- while (bh && bh->b_blocknr) {
- atomic_inc(&bitmap->pending_writes);
- set_buffer_locked(bh);
- set_buffer_mapped(bh);
- submit_bh(WRITE, bh);
- bh = bh->b_this_page;
- }
+ while (bh && bh->b_blocknr) {
+ atomic_inc(&bitmap->pending_writes);
+ set_buffer_locked(bh);
+ set_buffer_mapped(bh);
+ submit_bh(WRITE, bh);
+ bh = bh->b_this_page;
+ }
- if (wait) {
- wait_event(bitmap->write_wait,
- atomic_read(&bitmap->pending_writes)==0);
- return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
+ if (wait) {
+ wait_event(bitmap->write_wait,
+ atomic_read(&bitmap->pending_writes)==0);
+ }
}
- return 0;
+ if (bitmap->flags & BITMAP_WRITE_ERROR)
+ bitmap_file_kick(bitmap);
}
static void end_bitmap_write(struct buffer_head *bh, int uptodate)
@@ -425,17 +456,17 @@ out:
*/
/* update the event counter and sync the superblock to disk */
-int bitmap_update_sb(struct bitmap *bitmap)
+void bitmap_update_sb(struct bitmap *bitmap)
{
bitmap_super_t *sb;
unsigned long flags;
if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
- return 0;
+ return;
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->sb_page) { /* no superblock */
spin_unlock_irqrestore(&bitmap->lock, flags);
- return 0;
+ return;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
@@ -443,7 +474,7 @@ int bitmap_update_sb(struct bitmap *bitmap)
if (!bitmap->mddev->degraded)
sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
kunmap_atomic(sb, KM_USER0);
- return write_page(bitmap, bitmap->sb_page, 1);
+ write_page(bitmap, bitmap->sb_page, 1);
}
/* print out the bitmap file superblock */
@@ -572,20 +603,22 @@ enum bitmap_mask_op {
MASK_UNSET
};
-/* record the state of the bitmap in the superblock */
-static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
- enum bitmap_mask_op op)
+/* record the state of the bitmap in the superblock. Return the old value */
+static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+ enum bitmap_mask_op op)
{
bitmap_super_t *sb;
unsigned long flags;
+ int old;
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->sb_page) { /* can't set the state */
spin_unlock_irqrestore(&bitmap->lock, flags);
- return;
+ return 0;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+ old = le32_to_cpu(sb->state) & bits;
switch (op) {
case MASK_SET: sb->state |= cpu_to_le32(bits);
break;
@@ -594,6 +627,7 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
default: BUG();
}
kunmap_atomic(sb, KM_USER0);
+ return old;
}
/*
@@ -687,18 +721,23 @@ static void bitmap_file_kick(struct bitmap *bitmap)
{
char *path, *ptr = NULL;
- bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
- bitmap_update_sb(bitmap);
+ if (bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET) == 0) {
+ bitmap_update_sb(bitmap);
- if (bitmap->file) {
- path = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (path)
- ptr = file_path(bitmap->file, path, PAGE_SIZE);
+ if (bitmap->file) {
+ path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (path)
+ ptr = file_path(bitmap->file, path, PAGE_SIZE);
- printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
- bmname(bitmap), ptr ? ptr : "");
+ printk(KERN_ALERT
+ "%s: kicking failed bitmap file %s from array!\n",
+ bmname(bitmap), ptr ? ptr : "");
- kfree(path);
+ kfree(path);
+ } else
+ printk(KERN_ALERT
+ "%s: disabling internal bitmap due to errors\n",
+ bmname(bitmap));
}
bitmap_file_put(bitmap);
@@ -769,16 +808,15 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
/* this gets called when the md device is ready to unplug its underlying
* (slave) device queues -- before we let any writes go down, we need to
* sync the dirty pages of the bitmap file to disk */
-int bitmap_unplug(struct bitmap *bitmap)
+void bitmap_unplug(struct bitmap *bitmap)
{
unsigned long i, flags;
int dirty, need_write;
struct page *page;
int wait = 0;
- int err;
if (!bitmap)
- return 0;
+ return;
/* look at each page to see if there are any set bits that need to be
* flushed out to disk */
@@ -786,7 +824,7 @@ int bitmap_unplug(struct bitmap *bitmap)
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->filemap) {
spin_unlock_irqrestore(&bitmap->lock, flags);
- return 0;
+ return;
}
page = bitmap->filemap[i];
dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
@@ -798,7 +836,7 @@ int bitmap_unplug(struct bitmap *bitmap)
spin_unlock_irqrestore(&bitmap->lock, flags);
if (dirty | need_write)
- err = write_page(bitmap, page, 0);
+ write_page(bitmap, page, 0);
}
if (wait) { /* if any writes were performed, we need to wait on them */
if (bitmap->file)
@@ -809,7 +847,6 @@ int bitmap_unplug(struct bitmap *bitmap)
}
if (bitmap->flags & BITMAP_WRITE_ERROR)
bitmap_file_kick(bitmap);
- return 0;
}
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
@@ -858,21 +895,21 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
bmname(bitmap),
(unsigned long) i_size_read(file->f_mapping->host),
bytes + sizeof(bitmap_super_t));
- goto out;
+ goto err;
}
ret = -ENOMEM;
bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
if (!bitmap->filemap)
- goto out;
+ goto err;
/* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
bitmap->filemap_attr = kzalloc(
roundup( DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
GFP_KERNEL);
if (!bitmap->filemap_attr)
- goto out;
+ goto err;
oldindex = ~0L;
@@ -905,7 +942,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
}
if (IS_ERR(page)) { /* read error */
ret = PTR_ERR(page);
- goto out;
+ goto err;
}
oldindex = index;
@@ -920,11 +957,13 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
memset(paddr + offset, 0xff,
PAGE_SIZE - offset);
kunmap_atomic(paddr, KM_USER0);
- ret = write_page(bitmap, page, 1);
- if (ret) {
+ write_page(bitmap, page, 1);
+
+ ret = -EIO;
+ if (bitmap->flags & BITMAP_WRITE_ERROR) {
/* release, page not in filemap yet */
put_page(page);
- goto out;
+ goto err;
}
}
@@ -956,11 +995,15 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
md_wakeup_thread(bitmap->mddev->thread);
}
-out:
printk(KERN_INFO "%s: bitmap initialized from disk: "
- "read %lu/%lu pages, set %lu bits, status: %d\n",
- bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
+ "read %lu/%lu pages, set %lu bits\n",
+ bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt);
+
+ return 0;
+ err:
+ printk(KERN_INFO "%s: bitmap initialisation failed: %d\n",
+ bmname(bitmap), ret);
return ret;
}
@@ -997,19 +1040,18 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
* out to disk
*/
-int bitmap_daemon_work(struct bitmap *bitmap)
+void bitmap_daemon_work(struct bitmap *bitmap)
{
unsigned long j;
unsigned long flags;
struct page *page = NULL, *lastpage = NULL;
- int err = 0;
int blocks;
void *paddr;
if (bitmap == NULL)
- return 0;
+ return;
if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
- return 0;
+ return;
bitmap->daemon_lastrun = jiffies;
for (j = 0; j < bitmap->chunks; j++) {
@@ -1032,14 +1074,8 @@ int bitmap_daemon_work(struct bitmap *bitmap)
clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
- if (need_write) {
- switch (write_page(bitmap, page, 0)) {
- case 0:
- break;
- default:
- bitmap_file_kick(bitmap);
- }
- }
+ if (need_write)
+ write_page(bitmap, page, 0);
continue;
}
@@ -1048,13 +1084,11 @@ int bitmap_daemon_work(struct bitmap *bitmap)
if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
- err = write_page(bitmap, lastpage, 0);
+ write_page(bitmap, lastpage, 0);
} else {
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
}
- if (err)
- bitmap_file_kick(bitmap);
} else
spin_unlock_irqrestore(&bitmap->lock, flags);
lastpage = page;
@@ -1097,14 +1131,13 @@ int bitmap_daemon_work(struct bitmap *bitmap)
if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
- err = write_page(bitmap, lastpage, 0);
+ write_page(bitmap, lastpage, 0);
} else {
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
}
}
- return err;
}
static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1517,7 +1550,9 @@ int bitmap_create(mddev_t *mddev)
mddev->thread->timeout = bitmap->daemon_sleep * HZ;
- return bitmap_update_sb(bitmap);
+ bitmap_update_sb(bitmap);
+
+ return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
error:
bitmap_free(bitmap);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index f4f7d35561ab..846614e676c6 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -161,9 +161,7 @@ static void local_exit(void)
{
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
-
- if (unregister_blkdev(_major, _name) < 0)
- DMERR("unregister_blkdev failed");
+ unregister_blkdev(_major, _name);
_major = 0;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 33beaa7da085..65ddc887dfd7 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1640,7 +1640,6 @@ static void sync_sbs(mddev_t * mddev, int nospares)
static void md_update_sb(mddev_t * mddev, int force_change)
{
- int err;
struct list_head *tmp;
mdk_rdev_t *rdev;
int sync_req;
@@ -1727,7 +1726,7 @@ repeat:
"md: updating %s RAID superblock on device (in sync %d)\n",
mdname(mddev),mddev->in_sync);
- err = bitmap_update_sb(mddev->bitmap);
+ bitmap_update_sb(mddev->bitmap);
ITERATE_RDEV(mddev,rdev,tmp) {
char b[BDEVNAME_SIZE];
dprintk(KERN_INFO "md: ");
@@ -2073,9 +2072,11 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
err = super_types[super_format].
load_super(rdev, NULL, super_minor);
if (err == -EINVAL) {
- printk(KERN_WARNING
- "md: %s has invalid sb, not importing!\n",
- bdevname(rdev->bdev,b));
+ printk(KERN_WARNING
+ "md: %s does not have a valid v%d.%d "
+ "superblock, not importing!\n",
+ bdevname(rdev->bdev,b),
+ super_format, super_minor);
goto abort_free;
}
if (err < 0) {
@@ -3174,13 +3175,33 @@ static int do_md_run(mddev_t * mddev)
* Drop all container device buffers, from now on
* the only valid external interface is through the md
* device.
- * Also find largest hardsector size
*/
ITERATE_RDEV(mddev,rdev,tmp) {
if (test_bit(Faulty, &rdev->flags))
continue;
sync_blockdev(rdev->bdev);
invalidate_bdev(rdev->bdev);
+
+ /* perform some consistency tests on the device.
+ * We don't want the data to overlap the metadata,
+ * Internal Bitmap issues has handled elsewhere.
+ */
+ if (rdev->data_offset < rdev->sb_offset) {
+ if (mddev->size &&
+ rdev->data_offset + mddev->size*2
+ > rdev->sb_offset*2) {
+ printk("md: %s: data overlaps metadata\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ } else {
+ if (rdev->sb_offset*2 + rdev->sb_size/512
+ > rdev->data_offset) {
+ printk("md: %s: metadata overlaps data\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ }
}
md_probe(mddev->unit, NULL, NULL);
@@ -4642,7 +4663,6 @@ static int md_thread(void * arg)
* many dirty RAID5 blocks.
*/
- current->flags |= PF_NOFREEZE;
allow_signal(SIGKILL);
while (!kthread_should_stop()) {
@@ -5090,7 +5110,7 @@ static int is_mddev_idle(mddev_t *mddev)
mdk_rdev_t * rdev;
struct list_head *tmp;
int idle;
- unsigned long curr_events;
+ long curr_events;
idle = 1;
ITERATE_RDEV(mddev,rdev,tmp) {
@@ -5098,20 +5118,29 @@ static int is_mddev_idle(mddev_t *mddev)
curr_events = disk_stat_read(disk, sectors[0]) +
disk_stat_read(disk, sectors[1]) -
atomic_read(&disk->sync_io);
- /* The difference between curr_events and last_events
- * will be affected by any new non-sync IO (making
- * curr_events bigger) and any difference in the amount of
- * in-flight syncio (making current_events bigger or smaller)
- * The amount in-flight is currently limited to
- * 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6
- * which is at most 4096 sectors.
- * These numbers are fairly fragile and should be made
- * more robust, probably by enforcing the
- * 'window size' that md_do_sync sort-of uses.
+ /* sync IO will cause sync_io to increase before the disk_stats
+ * as sync_io is counted when a request starts, and
+ * disk_stats is counted when it completes.
+ * So resync activity will cause curr_events to be smaller than
+ * when there was no such activity.
+ * non-sync IO will cause disk_stat to increase without
+ * increasing sync_io so curr_events will (eventually)
+ * be larger than it was before. Once it becomes
+ * substantially larger, the test below will cause
+ * the array to appear non-idle, and resync will slow
+ * down.
+ * If there is a lot of outstanding resync activity when
+ * we set last_event to curr_events, then all that activity
+ * completing might cause the array to appear non-idle
+ * and resync will be slowed down even though there might
+ * not have been non-resync activity. This will only
+ * happen once though. 'last_events' will soon reflect
+ * the state where there is little or no outstanding
+ * resync requests, and further resync activity will
+ * always make curr_events less than last_events.
*
- * Note: the following is an unsigned comparison.
*/
- if ((long)curr_events - (long)rdev->last_events > 4096) {
+ if (curr_events - rdev->last_events > 4096) {
rdev->last_events = curr_events;
idle = 0;
}
@@ -5772,7 +5801,7 @@ static void autostart_arrays(int part)
for (i = 0; i < dev_cnt; i++) {
dev_t dev = detected_devices[i];
- rdev = md_import_device(dev,0, 0);
+ rdev = md_import_device(dev,0, 90);
if (IS_ERR(rdev))
continue;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 46677d7d9980..00c78b77b13d 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1526,8 +1526,7 @@ static void raid1d(mddev_t *mddev)
blk_remove_plug(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags);
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
- if (bitmap_unplug(mddev->bitmap) != 0)
- printk("%s: bitmap file write failed!\n", mdname(mddev));
+ bitmap_unplug(mddev->bitmap);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9eb66c1b523b..a95ada1cfac4 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1510,8 +1510,7 @@ static void raid10d(mddev_t *mddev)
blk_remove_plug(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags);
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
- if (bitmap_unplug(mddev->bitmap) != 0)
- printk("%s: bitmap file write failed!\n", mdname(mddev));
+ bitmap_unplug(mddev->bitmap);
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index f4e4ca2dcade..b6c7f6610ec5 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -523,6 +523,7 @@ static int dvb_frontend_thread(void *data)
dvb_frontend_init(fe);
+ set_freezable();
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
restart:
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 259ea08e784f..1cc2d286a1cb 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -906,6 +906,7 @@ int cx88_audio_thread(void *data)
u32 mode = 0;
dprintk("cx88: tvaudio thread started\n");
+ set_freezable();
for (;;) {
msleep_interruptible(1000);
if (kthread_should_stop())
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index e1821eb82fb5..d5ee2629121e 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/freezer.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
@@ -468,6 +469,7 @@ int msp3400c_thread(void *data)
v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+ set_freezable();
for (;;) {
v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
msp_sleep(state, -1);
@@ -646,7 +648,7 @@ int msp3410d_thread(void *data)
int val, i, std, count;
v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
-
+ set_freezable();
for (;;) {
v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
msp_sleep(state,-1);
@@ -940,7 +942,7 @@ int msp34xxg_thread(void *data)
int val, i;
v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
-
+ set_freezable();
for (;;) {
v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
msp_sleep(state, -1);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index c9bf9dbc2ea3..9da338dc4f3b 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -271,7 +271,7 @@ static int chip_thread(void *data)
struct CHIPDESC *desc = chiplist + chip->type;
v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
-
+ set_freezable();
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (!kthread_should_stop())
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index fcc5467e7636..e617925ba31e 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -47,6 +47,7 @@ static int videobuf_dvb_thread(void *data)
int err;
dprintk("dvb thread started\n");
+ set_freezable();
videobuf_read_start(&dvb->dvbq);
for (;;) {
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index f7e1d1910374..3ef4d0159c33 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -573,6 +573,7 @@ static int vivi_thread(void *data)
dprintk(1,"thread started\n");
mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ set_freezable();
for (;;) {
vivi_sleep(dma_q);
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index f4ac21e5771e..5afa0e393ecf 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -1,9 +1,6 @@
-menu "I2O device support"
- depends on PCI
-
-config I2O
- tristate "I2O support"
+menuconfig I2O
+ tristate "I2O device support"
depends on PCI
---help---
The Intelligent Input/Output (I2O) architecture allows hardware
@@ -25,9 +22,10 @@ config I2O
If unsure, say N.
+if I2O
+
config I2O_LCT_NOTIFY_ON_CHANGES
bool "Enable LCT notification"
- depends on I2O
default y
---help---
Only say N here if you have a I2O controller from SUN. The SUN
@@ -39,7 +37,6 @@ config I2O_LCT_NOTIFY_ON_CHANGES
config I2O_EXT_ADAPTEC
bool "Enable Adaptec extensions"
- depends on I2O
default y
---help---
Say Y for support of raidutils for Adaptec I2O controllers. You also
@@ -57,7 +54,7 @@ config I2O_EXT_ADAPTEC_DMA64
config I2O_CONFIG
tristate "I2O Configuration support"
- depends on I2O
+ depends on VIRT_TO_BUS
---help---
Say Y for support of the configuration interface for the I2O adapters.
If you have a RAID controller from Adaptec and you want to use the
@@ -78,7 +75,6 @@ config I2O_CONFIG_OLD_IOCTL
config I2O_BUS
tristate "I2O Bus Adapter OSM"
- depends on I2O
---help---
Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
provides access to the busses on the I2O controller. The main purpose
@@ -89,7 +85,7 @@ config I2O_BUS
config I2O_BLOCK
tristate "I2O Block OSM"
- depends on I2O && BLOCK
+ depends on BLOCK
---help---
Include support for the I2O Block OSM. The Block OSM presents disk
and other structured block devices to the operating system. If you
@@ -102,7 +98,7 @@ config I2O_BLOCK
config I2O_SCSI
tristate "I2O SCSI OSM"
- depends on I2O && SCSI
+ depends on SCSI
---help---
Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
I2O controller. You can use both the SCSI and Block OSM together if
@@ -114,7 +110,6 @@ config I2O_SCSI
config I2O_PROC
tristate "I2O /proc support"
- depends on I2O
---help---
If you say Y here and to "/proc file system support", you will be
able to read I2O related information from the virtual directory
@@ -123,5 +118,4 @@ config I2O_PROC
To compile this support as a module, choose M here: the
module will be called i2o_proc.
-endmenu
-
+endif # I2O
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 8abe45e49ad7..ce62d8bfe1c8 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -24,7 +24,7 @@ void i2o_report_status(const char *severity, const char *str,
if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
return; // No status in this reply
- printk(KERN_DEBUG "%s%s: ", severity, str);
+ printk("%s%s: ", severity, str);
if (cmd < 0x1F) // Utility cmd
i2o_report_util_cmd(cmd);
@@ -32,7 +32,7 @@ void i2o_report_status(const char *severity, const char *str,
else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd
i2o_report_exec_cmd(cmd);
else
- printk(KERN_DEBUG "Cmd = %0#2x, ", cmd); // Other cmds
+ printk("Cmd = %0#2x, ", cmd); // Other cmds
if (msg[0] & MSG_FAIL) {
i2o_report_fail_status(req_status, msg);
@@ -44,7 +44,7 @@ void i2o_report_status(const char *severity, const char *str,
if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
i2o_report_common_dsc(detailed_status);
else
- printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n",
+ printk(" / DetailedStatus = %0#4x.\n",
detailed_status);
}
@@ -89,10 +89,10 @@ static void i2o_report_fail_status(u8 req_status, u32 * msg)
};
if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
- printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
+ printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
req_status);
else
- printk(KERN_DEBUG "TRANSPORT_%s.\n",
+ printk("TRANSPORT_%s.\n",
FAIL_STATUS[req_status & 0x0F]);
/* Dump some details */
@@ -104,7 +104,7 @@ static void i2o_report_fail_status(u8 req_status, u32 * msg)
printk(KERN_ERR " FailingHostUnit = 0x%04X, FailingIOP = 0x%03X\n",
msg[5] >> 16, msg[5] & 0xFFF);
- printk(KERN_ERR " Severity: 0x%02X ", (msg[4] >> 16) & 0xFF);
+ printk(KERN_ERR " Severity: 0x%02X\n", (msg[4] >> 16) & 0xFF);
if (msg[4] & (1 << 16))
printk(KERN_DEBUG "(FormatError), "
"this msg can never be delivered/processed.\n");
@@ -142,9 +142,9 @@ static void i2o_report_common_status(u8 req_status)
};
if (req_status >= ARRAY_SIZE(REPLY_STATUS))
- printk(KERN_DEBUG "RequestStatus = %0#2x", req_status);
+ printk("RequestStatus = %0#2x", req_status);
else
- printk(KERN_DEBUG "%s", REPLY_STATUS[req_status]);
+ printk("%s", REPLY_STATUS[req_status]);
}
/*
@@ -187,10 +187,10 @@ static void i2o_report_common_dsc(u16 detailed_status)
};
if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
- printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n",
+ printk(" / DetailedStatus = %0#4x.\n",
detailed_status);
else
- printk(KERN_DEBUG " / %s.\n", COMMON_DSC[detailed_status]);
+ printk(" / %s.\n", COMMON_DSC[detailed_status]);
}
/*
@@ -200,49 +200,49 @@ static void i2o_report_util_cmd(u8 cmd)
{
switch (cmd) {
case I2O_CMD_UTIL_NOP:
- printk(KERN_DEBUG "UTIL_NOP, ");
+ printk("UTIL_NOP, ");
break;
case I2O_CMD_UTIL_ABORT:
- printk(KERN_DEBUG "UTIL_ABORT, ");
+ printk("UTIL_ABORT, ");
break;
case I2O_CMD_UTIL_CLAIM:
- printk(KERN_DEBUG "UTIL_CLAIM, ");
+ printk("UTIL_CLAIM, ");
break;
case I2O_CMD_UTIL_RELEASE:
- printk(KERN_DEBUG "UTIL_CLAIM_RELEASE, ");
+ printk("UTIL_CLAIM_RELEASE, ");
break;
case I2O_CMD_UTIL_CONFIG_DIALOG:
- printk(KERN_DEBUG "UTIL_CONFIG_DIALOG, ");
+ printk("UTIL_CONFIG_DIALOG, ");
break;
case I2O_CMD_UTIL_DEVICE_RESERVE:
- printk(KERN_DEBUG "UTIL_DEVICE_RESERVE, ");
+ printk("UTIL_DEVICE_RESERVE, ");
break;
case I2O_CMD_UTIL_DEVICE_RELEASE:
- printk(KERN_DEBUG "UTIL_DEVICE_RELEASE, ");
+ printk("UTIL_DEVICE_RELEASE, ");
break;
case I2O_CMD_UTIL_EVT_ACK:
- printk(KERN_DEBUG "UTIL_EVENT_ACKNOWLEDGE, ");
+ printk("UTIL_EVENT_ACKNOWLEDGE, ");
break;
case I2O_CMD_UTIL_EVT_REGISTER:
- printk(KERN_DEBUG "UTIL_EVENT_REGISTER, ");
+ printk("UTIL_EVENT_REGISTER, ");
break;
case I2O_CMD_UTIL_LOCK:
- printk(KERN_DEBUG "UTIL_LOCK, ");
+ printk("UTIL_LOCK, ");
break;
case I2O_CMD_UTIL_LOCK_RELEASE:
- printk(KERN_DEBUG "UTIL_LOCK_RELEASE, ");
+ printk("UTIL_LOCK_RELEASE, ");
break;
case I2O_CMD_UTIL_PARAMS_GET:
- printk(KERN_DEBUG "UTIL_PARAMS_GET, ");
+ printk("UTIL_PARAMS_GET, ");
break;
case I2O_CMD_UTIL_PARAMS_SET:
- printk(KERN_DEBUG "UTIL_PARAMS_SET, ");
+ printk("UTIL_PARAMS_SET, ");
break;
case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY:
- printk(KERN_DEBUG "UTIL_REPLY_FAULT_NOTIFY, ");
+ printk("UTIL_REPLY_FAULT_NOTIFY, ");
break;
default:
- printk(KERN_DEBUG "Cmd = %0#2x, ", cmd);
+ printk("Cmd = %0#2x, ", cmd);
}
}
@@ -253,106 +253,106 @@ static void i2o_report_exec_cmd(u8 cmd)
{
switch (cmd) {
case I2O_CMD_ADAPTER_ASSIGN:
- printk(KERN_DEBUG "EXEC_ADAPTER_ASSIGN, ");
+ printk("EXEC_ADAPTER_ASSIGN, ");
break;
case I2O_CMD_ADAPTER_READ:
- printk(KERN_DEBUG "EXEC_ADAPTER_READ, ");
+ printk("EXEC_ADAPTER_READ, ");
break;
case I2O_CMD_ADAPTER_RELEASE:
- printk(KERN_DEBUG "EXEC_ADAPTER_RELEASE, ");
+ printk("EXEC_ADAPTER_RELEASE, ");
break;
case I2O_CMD_BIOS_INFO_SET:
- printk(KERN_DEBUG "EXEC_BIOS_INFO_SET, ");
+ printk("EXEC_BIOS_INFO_SET, ");
break;
case I2O_CMD_BOOT_DEVICE_SET:
- printk(KERN_DEBUG "EXEC_BOOT_DEVICE_SET, ");
+ printk("EXEC_BOOT_DEVICE_SET, ");
break;
case I2O_CMD_CONFIG_VALIDATE:
- printk(KERN_DEBUG "EXEC_CONFIG_VALIDATE, ");
+ printk("EXEC_CONFIG_VALIDATE, ");
break;
case I2O_CMD_CONN_SETUP:
- printk(KERN_DEBUG "EXEC_CONN_SETUP, ");
+ printk("EXEC_CONN_SETUP, ");
break;
case I2O_CMD_DDM_DESTROY:
- printk(KERN_DEBUG "EXEC_DDM_DESTROY, ");
+ printk("EXEC_DDM_DESTROY, ");
break;
case I2O_CMD_DDM_ENABLE:
- printk(KERN_DEBUG "EXEC_DDM_ENABLE, ");
+ printk("EXEC_DDM_ENABLE, ");
break;
case I2O_CMD_DDM_QUIESCE:
- printk(KERN_DEBUG "EXEC_DDM_QUIESCE, ");
+ printk("EXEC_DDM_QUIESCE, ");
break;
case I2O_CMD_DDM_RESET:
- printk(KERN_DEBUG "EXEC_DDM_RESET, ");
+ printk("EXEC_DDM_RESET, ");
break;
case I2O_CMD_DDM_SUSPEND:
- printk(KERN_DEBUG "EXEC_DDM_SUSPEND, ");
+ printk("EXEC_DDM_SUSPEND, ");
break;
case I2O_CMD_DEVICE_ASSIGN:
- printk(KERN_DEBUG "EXEC_DEVICE_ASSIGN, ");
+ printk("EXEC_DEVICE_ASSIGN, ");
break;
case I2O_CMD_DEVICE_RELEASE:
- printk(KERN_DEBUG "EXEC_DEVICE_RELEASE, ");
+ printk("EXEC_DEVICE_RELEASE, ");
break;
case I2O_CMD_HRT_GET:
- printk(KERN_DEBUG "EXEC_HRT_GET, ");
+ printk("EXEC_HRT_GET, ");
break;
case I2O_CMD_ADAPTER_CLEAR:
- printk(KERN_DEBUG "EXEC_IOP_CLEAR, ");
+ printk("EXEC_IOP_CLEAR, ");
break;
case I2O_CMD_ADAPTER_CONNECT:
- printk(KERN_DEBUG "EXEC_IOP_CONNECT, ");
+ printk("EXEC_IOP_CONNECT, ");
break;
case I2O_CMD_ADAPTER_RESET:
- printk(KERN_DEBUG "EXEC_IOP_RESET, ");
+ printk("EXEC_IOP_RESET, ");
break;
case I2O_CMD_LCT_NOTIFY:
- printk(KERN_DEBUG "EXEC_LCT_NOTIFY, ");
+ printk("EXEC_LCT_NOTIFY, ");
break;
case I2O_CMD_OUTBOUND_INIT:
- printk(KERN_DEBUG "EXEC_OUTBOUND_INIT, ");
+ printk("EXEC_OUTBOUND_INIT, ");
break;
case I2O_CMD_PATH_ENABLE:
- printk(KERN_DEBUG "EXEC_PATH_ENABLE, ");
+ printk("EXEC_PATH_ENABLE, ");
break;
case I2O_CMD_PATH_QUIESCE:
- printk(KERN_DEBUG "EXEC_PATH_QUIESCE, ");
+ printk("EXEC_PATH_QUIESCE, ");
break;
case I2O_CMD_PATH_RESET:
- printk(KERN_DEBUG "EXEC_PATH_RESET, ");
+ printk("EXEC_PATH_RESET, ");
break;
case I2O_CMD_STATIC_MF_CREATE:
- printk(KERN_DEBUG "EXEC_STATIC_MF_CREATE, ");
+ printk("EXEC_STATIC_MF_CREATE, ");
break;
case I2O_CMD_STATIC_MF_RELEASE:
- printk(KERN_DEBUG "EXEC_STATIC_MF_RELEASE, ");
+ printk("EXEC_STATIC_MF_RELEASE, ");
break;
case I2O_CMD_STATUS_GET:
- printk(KERN_DEBUG "EXEC_STATUS_GET, ");
+ printk("EXEC_STATUS_GET, ");
break;
case I2O_CMD_SW_DOWNLOAD:
- printk(KERN_DEBUG "EXEC_SW_DOWNLOAD, ");
+ printk("EXEC_SW_DOWNLOAD, ");
break;
case I2O_CMD_SW_UPLOAD:
- printk(KERN_DEBUG "EXEC_SW_UPLOAD, ");
+ printk("EXEC_SW_UPLOAD, ");
break;
case I2O_CMD_SW_REMOVE:
- printk(KERN_DEBUG "EXEC_SW_REMOVE, ");
+ printk("EXEC_SW_REMOVE, ");
break;
case I2O_CMD_SYS_ENABLE:
- printk(KERN_DEBUG "EXEC_SYS_ENABLE, ");
+ printk("EXEC_SYS_ENABLE, ");
break;
case I2O_CMD_SYS_MODIFY:
- printk(KERN_DEBUG "EXEC_SYS_MODIFY, ");
+ printk("EXEC_SYS_MODIFY, ");
break;
case I2O_CMD_SYS_QUIESCE:
- printk(KERN_DEBUG "EXEC_SYS_QUIESCE, ");
+ printk("EXEC_SYS_QUIESCE, ");
break;
case I2O_CMD_SYS_TAB_SET:
- printk(KERN_DEBUG "EXEC_SYS_TAB_SET, ");
+ printk("EXEC_SYS_TAB_SET, ");
break;
default:
- printk(KERN_DEBUG "Cmd = %#02x, ", cmd);
+ printk("Cmd = %#02x, ", cmd);
}
}
@@ -361,28 +361,28 @@ void i2o_debug_state(struct i2o_controller *c)
printk(KERN_INFO "%s: State = ", c->name);
switch (((i2o_status_block *) c->status_block.virt)->iop_state) {
case 0x01:
- printk(KERN_DEBUG "INIT\n");
+ printk("INIT\n");
break;
case 0x02:
- printk(KERN_DEBUG "RESET\n");
+ printk("RESET\n");
break;
case 0x04:
- printk(KERN_DEBUG "HOLD\n");
+ printk("HOLD\n");
break;
case 0x05:
- printk(KERN_DEBUG "READY\n");
+ printk("READY\n");
break;
case 0x08:
- printk(KERN_DEBUG "OPERATIONAL\n");
+ printk("OPERATIONAL\n");
break;
case 0x10:
- printk(KERN_DEBUG "FAILED\n");
+ printk("FAILED\n");
break;
case 0x11:
- printk(KERN_DEBUG "FAULTED\n");
+ printk("FAULTED\n");
break;
default:
- printk(KERN_DEBUG "%x (unknown !!)\n",
+ printk("%x (unknown !!)\n",
((i2o_status_block *) c->status_block.virt)->iop_state);
}
};
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 611adc3c0f74..489d7c5c4965 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -62,7 +62,7 @@ int i2o_device_claim(struct i2o_device *dev)
{
int rc = 0;
- down(&dev->lock);
+ mutex_lock(&dev->lock);
rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
if (!rc)
@@ -72,7 +72,7 @@ int i2o_device_claim(struct i2o_device *dev)
pr_debug("i2o: claim of device %d failed %d\n",
dev->lct_data.tid, rc);
- up(&dev->lock);
+ mutex_unlock(&dev->lock);
return rc;
}
@@ -96,7 +96,7 @@ int i2o_device_claim_release(struct i2o_device *dev)
int tries;
int rc = 0;
- down(&dev->lock);
+ mutex_lock(&dev->lock);
/*
* If the controller takes a nonblocking approach to
@@ -118,7 +118,7 @@ int i2o_device_claim_release(struct i2o_device *dev)
pr_debug("i2o: claim release of device %d failed %d\n",
dev->lct_data.tid, rc);
- up(&dev->lock);
+ mutex_unlock(&dev->lock);
return rc;
}
@@ -198,7 +198,7 @@ static struct i2o_device *i2o_device_alloc(void)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&dev->list);
- init_MUTEX(&dev->lock);
+ mutex_init(&dev->lock);
dev->device.bus = &i2o_bus_type;
dev->device.release = &i2o_device_release;
@@ -326,7 +326,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
u16 table_size;
u32 buf;
- down(&c->lct_lock);
+ mutex_lock(&c->lct_lock);
kfree(c->lct);
@@ -335,7 +335,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
if (!lct) {
- up(&c->lct_lock);
+ mutex_unlock(&c->lct_lock);
return -ENOMEM;
}
@@ -408,7 +408,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
i2o_device_remove(dev);
}
- up(&c->lct_lock);
+ mutex_unlock(&c->lct_lock);
return 0;
}
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 5278aad92bc4..8c83ee3b0920 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -131,8 +131,10 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
int rc = 0;
wait = i2o_exec_wait_alloc();
- if (!wait)
+ if (!wait) {
+ i2o_msg_nop(c, msg);
return -ENOMEM;
+ }
if (tcntxt == 0xffffffff)
tcntxt = 0x80000000;
@@ -337,6 +339,8 @@ static int i2o_exec_probe(struct device *dev)
rc = device_create_file(dev, &dev_attr_product_id);
if (rc) goto err_vid;
+ i2o_dev->iop->exec = i2o_dev;
+
return 0;
err_vid:
@@ -537,7 +541,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
struct device *dev;
struct i2o_message *msg;
- down(&c->lct_lock);
+ mutex_lock(&c->lct_lock);
dev = &c->pdev->dev;
@@ -561,7 +565,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
i2o_msg_post(c, msg);
- up(&c->lct_lock);
+ mutex_unlock(&c->lct_lock);
return 0;
};
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index b17c4b2bc9ef..64a52bd7544a 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -215,7 +215,7 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
struct i2o_message *msg;
msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
+ if (IS_ERR(msg))
return PTR_ERR(msg);
msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 8ba275a12773..84e046e94f5f 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -554,8 +554,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
return -ENXIO;
}
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
-
sb = c->status_block.virt;
if (get_user(size, &user_msg[0])) {
@@ -573,24 +571,30 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
size <<= 2; // Convert to bytes
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ rcode = -EFAULT;
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) {
osm_warn("unable to copy user message\n");
- return -EFAULT;
+ goto out;
}
i2o_dump_message(msg);
if (get_user(reply_size, &user_reply[0]) < 0)
- return -EFAULT;
+ goto out;
reply_size >>= 16;
reply_size <<= 2;
+ rcode = -ENOMEM;
reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
- return -ENOMEM;
+ goto out;
}
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -661,13 +665,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
rcode = i2o_msg_post_wait(c, msg, 60);
+ msg = NULL;
if (rcode) {
reply[4] = ((u32) rcode) << 24;
goto sg_list_cleanup;
}
if (sg_offset) {
- u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
+ u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
/* Copy back the Scatter Gather buffers back to user space */
u32 j;
// TODO 64bit fix
@@ -675,7 +680,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
int sg_size;
// re-acquire the original message to handle correctly the sg copy operation
- memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
+ memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
@@ -684,7 +689,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
size = size >> 16;
size *= 4;
/* Copy in the user's I2O command */
- if (copy_from_user(msg, user_msg, size)) {
+ if (copy_from_user(rmsg, user_msg, size)) {
rcode = -EFAULT;
goto sg_list_cleanup;
}
@@ -692,7 +697,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
(size - sg_offset * 4) / sizeof(struct sg_simple_element);
// TODO 64bit fix
- sg = (struct sg_simple_element *)(msg + sg_offset);
+ sg = (struct sg_simple_element *)(rmsg + sg_offset);
for (j = 0; j < sg_count; j++) {
/* Copy out the SG list to user's buffer if necessary */
if (!
@@ -714,7 +719,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
- sg_list_cleanup:
+sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
@@ -723,7 +728,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
"%s: Could not copy message context FROM user\n",
c->name);
rcode = -EFAULT;
- goto sg_list_cleanup;
}
if (copy_to_user(user_reply, reply, reply_size)) {
printk(KERN_WARNING
@@ -731,12 +735,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
rcode = -EFAULT;
}
}
-
for (i = 0; i < sg_index; i++)
i2o_dma_free(&c->pdev->dev, &sg_list[i]);
- cleanup:
+cleanup:
kfree(reply);
+out:
+ if (msg)
+ i2o_msg_nop(c, msg);
return rcode;
}
@@ -793,8 +799,6 @@ static int i2o_cfg_passthru(unsigned long arg)
return -ENXIO;
}
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
-
sb = c->status_block.virt;
if (get_user(size, &user_msg[0]))
@@ -810,12 +814,17 @@ static int i2o_cfg_passthru(unsigned long arg)
size <<= 2; // Convert to bytes
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ rcode = -EFAULT;
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size))
- return -EFAULT;
+ goto out;
if (get_user(reply_size, &user_reply[0]) < 0)
- return -EFAULT;
+ goto out;
reply_size >>= 16;
reply_size <<= 2;
@@ -824,7 +833,8 @@ static int i2o_cfg_passthru(unsigned long arg)
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
- return -ENOMEM;
+ rcode = -ENOMEM;
+ goto out;
}
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -891,13 +901,14 @@ static int i2o_cfg_passthru(unsigned long arg)
}
rcode = i2o_msg_post_wait(c, msg, 60);
+ msg = NULL;
if (rcode) {
reply[4] = ((u32) rcode) << 24;
goto sg_list_cleanup;
}
if (sg_offset) {
- u32 msg[128];
+ u32 rmsg[128];
/* Copy back the Scatter Gather buffers back to user space */
u32 j;
// TODO 64bit fix
@@ -905,7 +916,7 @@ static int i2o_cfg_passthru(unsigned long arg)
int sg_size;
// re-acquire the original message to handle correctly the sg copy operation
- memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
+ memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
@@ -914,7 +925,7 @@ static int i2o_cfg_passthru(unsigned long arg)
size = size >> 16;
size *= 4;
/* Copy in the user's I2O command */
- if (copy_from_user(msg, user_msg, size)) {
+ if (copy_from_user(rmsg, user_msg, size)) {
rcode = -EFAULT;
goto sg_list_cleanup;
}
@@ -922,7 +933,7 @@ static int i2o_cfg_passthru(unsigned long arg)
(size - sg_offset * 4) / sizeof(struct sg_simple_element);
// TODO 64bit fix
- sg = (struct sg_simple_element *)(msg + sg_offset);
+ sg = (struct sg_simple_element *)(rmsg + sg_offset);
for (j = 0; j < sg_count; j++) {
/* Copy out the SG list to user's buffer if necessary */
if (!
@@ -944,7 +955,7 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
- sg_list_cleanup:
+sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
@@ -964,8 +975,11 @@ static int i2o_cfg_passthru(unsigned long arg)
for (i = 0; i < sg_index; i++)
kfree(sg_list[i]);
- cleanup:
+cleanup:
kfree(reply);
+out:
+ if (msg)
+ i2o_msg_nop(c, msg);
return rcode;
}
#endif
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 3305c12372a2..a1ec16a075c6 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -1067,7 +1067,7 @@ struct i2o_controller *i2o_iop_alloc(void)
INIT_LIST_HEAD(&c->devices);
spin_lock_init(&c->lock);
- init_MUTEX(&c->lct_lock);
+ mutex_init(&c->lct_lock);
device_initialize(&c->device);
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 38e815a2e871..fdbaa776f249 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -209,6 +209,7 @@ static int ucb1x00_thread(void *_ts)
DECLARE_WAITQUEUE(wait, tsk);
int valid = 0;
+ set_freezable();
add_wait_queue(&ts->irq_wait, &wait);
while (!kthread_should_stop()) {
unsigned int x, y, p;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index bd601efa7bd1..1d516f24ba53 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -2,11 +2,15 @@
# Misc strange devices
#
-menu "Misc devices"
+menuconfig MISC_DEVICES
+ bool "Misc devices"
+ default y
+
+if MISC_DEVICES
config IBM_ASM
tristate "Device driver for IBM RSA service processor"
- depends on X86 && PCI && EXPERIMENTAL
+ depends on X86 && PCI && INPUT && EXPERIMENTAL
---help---
This option enables device driver support for in-band access to the
IBM RSA (Condor) service processor in eServer xSeries systems.
@@ -192,4 +196,4 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
-endmenu
+endif # MISC_DEVICES
diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
index 07a085ccbd5b..b5df347c81b9 100644
--- a/drivers/misc/ibmasm/command.c
+++ b/drivers/misc/ibmasm/command.c
@@ -18,7 +18,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -72,7 +72,7 @@ struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_s
static void free_command(struct kobject *kobj)
{
struct command *cmd = to_command(kobj);
-
+
list_del(&cmd->queue_node);
atomic_dec(&command_count);
dbg("command count: %d\n", atomic_read(&command_count));
@@ -113,14 +113,14 @@ static inline void do_exec_command(struct service_processor *sp)
exec_next_command(sp);
}
}
-
+
/**
* exec_command
* send a command to a service processor
* Commands are executed sequentially. One command (sp->current_command)
* is sent to the service processor. Once the interrupt handler gets a
* message of type command_response, the message is copied into
- * the current commands buffer,
+ * the current commands buffer,
*/
void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
{
@@ -160,7 +160,7 @@ static void exec_next_command(struct service_processor *sp)
}
}
-/**
+/**
* Sleep until a command has failed or a response has been received
* and the command status been updated by the interrupt handler.
* (see receive_response).
@@ -182,8 +182,8 @@ void ibmasm_receive_command_response(struct service_processor *sp, void *respons
{
struct command *cmd = sp->current_command;
- if (!sp->current_command)
- return;
+ if (!sp->current_command)
+ return;
memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
cmd->status = IBMASM_CMD_COMPLETE;
diff --git a/drivers/misc/ibmasm/dot_command.c b/drivers/misc/ibmasm/dot_command.c
index 13c52f866e2e..3dd2dfb8da17 100644
--- a/drivers/misc/ibmasm/dot_command.c
+++ b/drivers/misc/ibmasm/dot_command.c
@@ -17,7 +17,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -44,11 +44,11 @@ void ibmasm_receive_message(struct service_processor *sp, void *message, int mes
size = message_size;
switch (header->type) {
- case sp_event:
+ case sp_event:
ibmasm_receive_event(sp, message, size);
break;
case sp_command_response:
- ibmasm_receive_command_response(sp, message, size);
+ ibmasm_receive_command_response(sp, message, size);
break;
case sp_heartbeat:
ibmasm_receive_heartbeat(sp, message, size);
@@ -95,7 +95,7 @@ int ibmasm_send_driver_vpd(struct service_processor *sp)
strcat(vpd_data, IBMASM_DRIVER_VPD);
vpd_data[10] = 0;
vpd_data[15] = 0;
-
+
ibmasm_exec_command(sp, command);
ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL);
@@ -118,7 +118,7 @@ struct os_state_command {
* During driver init this function is called with os state "up".
* This causes the service processor to start sending heartbeats the
* driver.
- * During driver exit the function is called with os state "down",
+ * During driver exit the function is called with os state "down",
* causing the service processor to stop the heartbeats.
*/
int ibmasm_send_os_state(struct service_processor *sp, int os_state)
diff --git a/drivers/misc/ibmasm/dot_command.h b/drivers/misc/ibmasm/dot_command.h
index 2d21c2741b6a..6cbba1afef35 100644
--- a/drivers/misc/ibmasm/dot_command.h
+++ b/drivers/misc/ibmasm/dot_command.h
@@ -17,7 +17,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c
index fe1e819235a4..fda6a4d3bf23 100644
--- a/drivers/misc/ibmasm/event.c
+++ b/drivers/misc/ibmasm/event.c
@@ -18,7 +18,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -51,7 +51,7 @@ static void wake_up_event_readers(struct service_processor *sp)
* event readers.
* There is no reader marker in the buffer, therefore readers are
* responsible for keeping up with the writer, or they will loose events.
- */
+ */
void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size)
{
struct event_buffer *buffer = sp->event_buffer;
@@ -77,13 +77,13 @@ void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int
static inline int event_available(struct event_buffer *b, struct event_reader *r)
{
- return (r->next_serial_number < b->next_serial_number);
+ return (r->next_serial_number < b->next_serial_number);
}
/**
* get_next_event
* Called by event readers (initiated from user space through the file
- * system).
+ * system).
* Sleeps until a new event is available.
*/
int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader)
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index 7fd7a43e38de..3036e785b3e4 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -18,7 +18,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
diff --git a/drivers/misc/ibmasm/i2o.h b/drivers/misc/ibmasm/i2o.h
index 958c957a5e75..bf2c738d2b72 100644
--- a/drivers/misc/ibmasm/i2o.h
+++ b/drivers/misc/ibmasm/i2o.h
@@ -17,7 +17,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -26,9 +26,9 @@ struct i2o_header {
u8 version;
u8 message_flags;
u16 message_size;
- u8 target;
+ u8 target;
u8 initiator_and_target;
- u8 initiator;
+ u8 initiator;
u8 function;
u32 initiator_context;
};
@@ -64,12 +64,12 @@ static inline unsigned short outgoing_message_size(unsigned int data_size)
size = sizeof(struct i2o_header) + data_size;
i2o_size = size / sizeof(u32);
-
+
if (size % sizeof(u32))
i2o_size++;
return i2o_size;
-}
+}
static inline u32 incoming_data_size(struct i2o_message *i2o_message)
{
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 48d5abebfc30..de860bc6d3f5 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -18,7 +18,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -58,8 +58,8 @@ static inline char *get_timestamp(char *buf)
return buf;
}
-#define IBMASM_CMD_PENDING 0
-#define IBMASM_CMD_COMPLETE 1
+#define IBMASM_CMD_PENDING 0
+#define IBMASM_CMD_COMPLETE 1
#define IBMASM_CMD_FAILED 2
#define IBMASM_CMD_TIMEOUT_NORMAL 45
@@ -163,55 +163,55 @@ struct service_processor {
};
/* command processing */
-extern struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
-extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
-extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
-extern void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size);
+struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
+void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
+void ibmasm_wait_for_response(struct command *cmd, int timeout);
+void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size);
/* event processing */
-extern int ibmasm_event_buffer_init(struct service_processor *sp);
-extern void ibmasm_event_buffer_exit(struct service_processor *sp);
-extern void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size);
-extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
-extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
-extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
-extern void ibmasm_cancel_next_event(struct event_reader *reader);
+int ibmasm_event_buffer_init(struct service_processor *sp);
+void ibmasm_event_buffer_exit(struct service_processor *sp);
+void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size);
+void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
+void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
+int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
+void ibmasm_cancel_next_event(struct event_reader *reader);
/* heartbeat - from SP to OS */
-extern void ibmasm_register_panic_notifier(void);
-extern void ibmasm_unregister_panic_notifier(void);
-extern int ibmasm_heartbeat_init(struct service_processor *sp);
-extern void ibmasm_heartbeat_exit(struct service_processor *sp);
-extern void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size);
+void ibmasm_register_panic_notifier(void);
+void ibmasm_unregister_panic_notifier(void);
+int ibmasm_heartbeat_init(struct service_processor *sp);
+void ibmasm_heartbeat_exit(struct service_processor *sp);
+void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size);
/* reverse heartbeat - from OS to SP */
-extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
-extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
-extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
+void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
+int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
+void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
/* dot commands */
-extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
-extern int ibmasm_send_driver_vpd(struct service_processor *sp);
-extern int ibmasm_send_os_state(struct service_processor *sp, int os_state);
+void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
+int ibmasm_send_driver_vpd(struct service_processor *sp);
+int ibmasm_send_os_state(struct service_processor *sp, int os_state);
/* low level message processing */
-extern int ibmasm_send_i2o_message(struct service_processor *sp);
-extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
+int ibmasm_send_i2o_message(struct service_processor *sp);
+irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
/* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
-extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
-extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
+int ibmasm_init_remote_input_dev(struct service_processor *sp);
+void ibmasm_free_remote_input_dev(struct service_processor *sp);
/* file system */
-extern int ibmasmfs_register(void);
-extern void ibmasmfs_unregister(void);
-extern void ibmasmfs_add_sp(struct service_processor *sp);
+int ibmasmfs_register(void);
+void ibmasmfs_unregister(void);
+void ibmasmfs_add_sp(struct service_processor *sp);
/* uart */
#ifdef CONFIG_SERIAL_8250
-extern void ibmasm_register_uart(struct service_processor *sp);
-extern void ibmasm_unregister_uart(struct service_processor *sp);
+void ibmasm_register_uart(struct service_processor *sp);
+void ibmasm_unregister_uart(struct service_processor *sp);
#else
#define ibmasm_register_uart(sp) do { } while(0)
#define ibmasm_unregister_uart(sp) do { } while(0)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index c436d3de8b8b..eb7b073734b8 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -17,12 +17,12 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
/*
- * Parts of this code are based on an article by Jonathan Corbet
+ * Parts of this code are based on an article by Jonathan Corbet
* that appeared in Linux Weekly News.
*/
@@ -55,22 +55,22 @@
* For each service processor the following files are created:
*
* command: execute dot commands
- * write: execute a dot command on the service processor
- * read: return the result of a previously executed dot command
+ * write: execute a dot command on the service processor
+ * read: return the result of a previously executed dot command
*
* events: listen for service processor events
- * read: sleep (interruptible) until an event occurs
+ * read: sleep (interruptible) until an event occurs
* write: wakeup sleeping event listener
*
* reverse_heartbeat: send a heartbeat to the service processor
- * read: sleep (interruptible) until the reverse heartbeat fails
+ * read: sleep (interruptible) until the reverse heartbeat fails
* write: wakeup sleeping heartbeat listener
*
* remote_video/width
* remote_video/height
* remote_video/width: control remote display settings
- * write: set value
- * read: read value
+ * write: set value
+ * read: read value
*/
#include <linux/fs.h>
@@ -155,7 +155,7 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
static struct dentry *ibmasmfs_create_file (struct super_block *sb,
struct dentry *parent,
- const char *name,
+ const char *name,
const struct file_operations *fops,
void *data,
int mode)
@@ -261,7 +261,7 @@ static int command_file_close(struct inode *inode, struct file *file)
struct ibmasmfs_command_data *command_data = file->private_data;
if (command_data->command)
- command_put(command_data->command);
+ command_put(command_data->command);
kfree(command_data);
return 0;
@@ -348,7 +348,7 @@ static ssize_t command_file_write(struct file *file, const char __user *ubuff, s
static int event_file_open(struct inode *inode, struct file *file)
{
struct ibmasmfs_event_data *event_data;
- struct service_processor *sp;
+ struct service_processor *sp;
if (!inode->i_private)
return -ENODEV;
@@ -573,7 +573,7 @@ static ssize_t remote_settings_file_write(struct file *file, const char __user *
kfree(buff);
return -EFAULT;
}
-
+
value = simple_strtoul(buff, NULL, 10);
writel(value, address);
kfree(buff);
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index a3c589b7cbfa..4b2398e27fd5 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -17,7 +17,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
diff --git a/drivers/misc/ibmasm/lowlevel.h b/drivers/misc/ibmasm/lowlevel.h
index e5ed59c589aa..766766523a60 100644
--- a/drivers/misc/ibmasm/lowlevel.h
+++ b/drivers/misc/ibmasm/lowlevel.h
@@ -17,7 +17,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -48,9 +48,9 @@
#define INTR_CONTROL_REGISTER 0x13A4
#define SCOUT_COM_A_BASE 0x0000
-#define SCOUT_COM_B_BASE 0x0100
-#define SCOUT_COM_C_BASE 0x0200
-#define SCOUT_COM_D_BASE 0x0300
+#define SCOUT_COM_B_BASE 0x0100
+#define SCOUT_COM_C_BASE 0x0200
+#define SCOUT_COM_D_BASE 0x0300
static inline int sp_interrupt_pending(void __iomem *base_address)
{
@@ -86,12 +86,12 @@ static inline void disable_sp_interrupts(void __iomem *base_address)
static inline void enable_uart_interrupts(void __iomem *base_address)
{
- ibmasm_enable_interrupts(base_address, UART_INTR_MASK);
+ ibmasm_enable_interrupts(base_address, UART_INTR_MASK);
}
static inline void disable_uart_interrupts(void __iomem *base_address)
{
- ibmasm_disable_interrupts(base_address, UART_INTR_MASK);
+ ibmasm_disable_interrupts(base_address, UART_INTR_MASK);
}
#define valid_mfa(mfa) ( (mfa) != NO_MFAS_AVAILABLE )
@@ -111,7 +111,7 @@ static inline u32 get_mfa_outbound(void __iomem *base_address)
static inline void set_mfa_outbound(void __iomem *base_address, u32 mfa)
{
- writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
+ writel(mfa, base_address + OUTBOUND_QUEUE_PORT);
}
static inline u32 get_mfa_inbound(void __iomem *base_address)
@@ -126,7 +126,7 @@ static inline u32 get_mfa_inbound(void __iomem *base_address)
static inline void set_mfa_inbound(void __iomem *base_address, u32 mfa)
{
- writel(mfa, base_address + INBOUND_QUEUE_PORT);
+ writel(mfa, base_address + INBOUND_QUEUE_PORT);
}
static inline struct i2o_message *get_i2o_message(void __iomem *base_address, u32 mfa)
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 2f3bddfab937..fb03a853fac4 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -18,9 +18,9 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
- * This driver is based on code originally written by Pete Reynolds
+ * This driver is based on code originally written by Pete Reynolds
* and others.
*
*/
@@ -30,13 +30,13 @@
*
* 1) When loaded it sends a message to the service processor,
* indicating that an OS is * running. This causes the service processor
- * to send periodic heartbeats to the OS.
+ * to send periodic heartbeats to the OS.
*
* 2) Answers the periodic heartbeats sent by the service processor.
* Failure to do so would result in system reboot.
*
* 3) Acts as a pass through for dot commands sent from user applications.
- * The interface for this is the ibmasmfs file system.
+ * The interface for this is the ibmasmfs file system.
*
* 4) Allows user applications to register for event notification. Events
* are sent to the driver through interrupts. They can be read from user
@@ -105,7 +105,7 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
}
sp->irq = pdev->irq;
- sp->base_address = ioremap(pci_resource_start(pdev, 0),
+ sp->base_address = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
if (sp->base_address == 0) {
dev_err(sp->dev, "Failed to ioremap pci memory\n");
diff --git a/drivers/misc/ibmasm/r_heartbeat.c b/drivers/misc/ibmasm/r_heartbeat.c
index f8fdb2d5417e..bec9e2c44bef 100644
--- a/drivers/misc/ibmasm/r_heartbeat.c
+++ b/drivers/misc/ibmasm/r_heartbeat.c
@@ -16,7 +16,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
@@ -36,10 +36,10 @@ static struct {
unsigned char command[3];
} rhb_dot_cmd = {
.header = {
- .type = sp_read,
+ .type = sp_read,
.command_size = 3,
.data_size = 0,
- .status = 0
+ .status = 0
},
.command = { 4, 3, 6 }
};
@@ -76,9 +76,9 @@ int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_
if (cmd->status != IBMASM_CMD_COMPLETE)
times_failed++;
- wait_event_interruptible_timeout(rhb->wait,
+ wait_event_interruptible_timeout(rhb->wait,
rhb->stopped,
- REVERSE_HEARTBEAT_TIMEOUT * HZ);
+ REVERSE_HEARTBEAT_TIMEOUT * HZ);
if (signal_pending(current) || rhb->stopped) {
result = -EINTR;
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index a40fda6c402c..0550ce075fc4 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -28,11 +28,10 @@
#include "ibmasm.h"
#include "remote.h"
-static int xmax = 1600;
-static int ymax = 1200;
+#define MOUSE_X_MAX 1600
+#define MOUSE_Y_MAX 1200
-
-static unsigned short xlate_high[XLATE_SIZE] = {
+static const unsigned short xlate_high[XLATE_SIZE] = {
[KEY_SYM_ENTER & 0xff] = KEY_ENTER,
[KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
[KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
@@ -81,7 +80,8 @@ static unsigned short xlate_high[XLATE_SIZE] = {
[KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
[KEY_SYM_SCR_LOCK & 0xff] = KEY_SCROLLLOCK,
};
-static unsigned short xlate[XLATE_SIZE] = {
+
+static const unsigned short xlate[XLATE_SIZE] = {
[NO_KEYCODE] = KEY_RESERVED,
[KEY_SYM_SPACE] = KEY_SPACE,
[KEY_SYM_TILDE] = KEY_GRAVE, [KEY_SYM_BKTIC] = KEY_GRAVE,
@@ -133,19 +133,16 @@ static unsigned short xlate[XLATE_SIZE] = {
[KEY_SYM_Z] = KEY_Z, [KEY_SYM_z] = KEY_Z,
};
-static char remote_mouse_name[] = "ibmasm RSA I remote mouse";
-static char remote_keybd_name[] = "ibmasm RSA I remote keyboard";
-
static void print_input(struct remote_input *input)
{
if (input->type == INPUT_TYPE_MOUSE) {
unsigned char buttons = input->mouse_buttons;
dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
input->data.mouse.x, input->data.mouse.y,
- (buttons)?" -- buttons:":"",
- (buttons & REMOTE_BUTTON_LEFT)?"left ":"",
- (buttons & REMOTE_BUTTON_MIDDLE)?"middle ":"",
- (buttons & REMOTE_BUTTON_RIGHT)?"right":""
+ (buttons) ? " -- buttons:" : "",
+ (buttons & REMOTE_BUTTON_LEFT) ? "left " : "",
+ (buttons & REMOTE_BUTTON_MIDDLE) ? "middle " : "",
+ (buttons & REMOTE_BUTTON_RIGHT) ? "right" : ""
);
} else {
dbg("remote keypress (code, flag, down):"
@@ -180,7 +177,7 @@ static void send_keyboard_event(struct input_dev *dev,
key = xlate_high[code & 0xff];
else
key = xlate[code];
- input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
+ input_report_key(dev, key, input->data.keyboard.key_down);
input_sync(dev);
}
@@ -228,20 +225,22 @@ int ibmasm_init_remote_input_dev(struct service_processor *sp)
mouse_dev->id.vendor = pdev->vendor;
mouse_dev->id.product = pdev->device;
mouse_dev->id.version = 1;
+ mouse_dev->dev.parent = sp->dev;
mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
set_bit(BTN_TOUCH, mouse_dev->keybit);
- mouse_dev->name = remote_mouse_name;
- input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
- input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
+ mouse_dev->name = "ibmasm RSA I remote mouse";
+ input_set_abs_params(mouse_dev, ABS_X, 0, MOUSE_X_MAX, 0, 0);
+ input_set_abs_params(mouse_dev, ABS_Y, 0, MOUSE_Y_MAX, 0, 0);
- mouse_dev->id.bustype = BUS_PCI;
+ keybd_dev->id.bustype = BUS_PCI;
keybd_dev->id.vendor = pdev->vendor;
keybd_dev->id.product = pdev->device;
- mouse_dev->id.version = 2;
+ keybd_dev->id.version = 2;
+ keybd_dev->dev.parent = sp->dev;
keybd_dev->evbit[0] = BIT(EV_KEY);
- keybd_dev->name = remote_keybd_name;
+ keybd_dev->name = "ibmasm RSA I remote keyboard";
for (i = 0; i < XLATE_SIZE; i++) {
if (xlate_high[i])
diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h
index b7076a8442d2..72acf5af7a2a 100644
--- a/drivers/misc/ibmasm/remote.h
+++ b/drivers/misc/ibmasm/remote.h
@@ -18,7 +18,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
* Orignally written by Pete Reynolds
*/
@@ -73,7 +73,7 @@ struct keyboard_input {
-struct remote_input {
+struct remote_input {
union {
struct mouse_input mouse;
struct keyboard_input keyboard;
@@ -85,7 +85,7 @@ struct remote_input {
unsigned char pad3;
};
-#define mouse_addr(sp) (sp->base_address + CONDOR_MOUSE_DATA)
+#define mouse_addr(sp) (sp->base_address + CONDOR_MOUSE_DATA)
#define display_width(sp) (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX)
#define display_height(sp) (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY)
#define display_depth(sp) (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS)
@@ -93,7 +93,7 @@ struct remote_input {
#define vnc_status(sp) (mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS)
#define isr_control(sp) (mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
-#define mouse_interrupt_pending(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
+#define mouse_interrupt_pending(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
#define clear_mouse_interrupt(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
#define enable_mouse_interrupts(sp) writel(1, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
#define disable_mouse_interrupts(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c
index 9783caf49696..93baa350d698 100644
--- a/drivers/misc/ibmasm/uart.c
+++ b/drivers/misc/ibmasm/uart.c
@@ -18,7 +18,7 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Author: Max Asböck <amax@us.ibm.com>
*
*/
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 8ee0321ef1c8..9623eaf4f89f 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1917,7 +1917,8 @@ end:
*/
static int sony_pic_disable(struct acpi_device *device)
{
- if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL)))
+ if (ACPI_FAILURE(acpi_evaluate_object(device->handle,
+ "_DIS", NULL, NULL)))
return -ENXIO;
dprintk("Device disabled\n");
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 4fb2089dc690..b53dac8d1b69 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -11,6 +11,7 @@
*/
#include <linux/module.h>
#include <linux/blkdev.h>
+#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/mmc/card.h>
@@ -44,11 +45,7 @@ static int mmc_queue_thread(void *d)
struct mmc_queue *mq = d;
struct request_queue *q = mq->queue;
- /*
- * Set iothread to ensure that we aren't put to sleep by
- * the process freezing. We handle suspension ourselves.
- */
- current->flags |= PF_MEMALLOC|PF_NOFREEZE;
+ current->flags |= PF_MEMALLOC;
down(&mq->thread_sem);
do {
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 51bc7e2f1f22..ef89780eb9d6 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -16,6 +16,7 @@
#include <linux/mtd/mtd.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/freezer.h>
#include <linux/spinlock.h>
#include <linux/hdreg.h>
#include <linux/init.h>
@@ -80,7 +81,7 @@ static int mtd_blktrans_thread(void *arg)
struct request_queue *rq = tr->blkcore_priv->rq;
/* we might get involved when memory gets low, so use PF_MEMALLOC */
- current->flags |= PF_MEMALLOC | PF_NOFREEZE;
+ current->flags |= PF_MEMALLOC;
spin_lock_irq(rq->queue_lock);
while (!kthread_should_stop()) {
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 74002945b71b..7c6b223b3f8a 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -368,7 +368,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf,
int err, pnum, scrub = 0, idx = vol_id2idx(ubi, vol_id);
struct ubi_vid_hdr *vid_hdr;
struct ubi_volume *vol = ubi->volumes[idx];
- uint32_t crc, crc1;
+ uint32_t uninitialized_var(crc);
err = leb_read_lock(ubi, vol_id, lnum);
if (err)
@@ -451,7 +451,7 @@ retry:
}
if (check) {
- crc1 = crc32(UBI_CRC32_INIT, buf, len);
+ uint32_t crc1 = crc32(UBI_CRC32_INIT, buf, len);
if (crc1 != crc) {
ubi_warn("CRC error: calculated %#08x, must be %#08x",
crc1, crc);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 9ecaf77eca9e..ab2174a56bc2 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1346,6 +1346,7 @@ static int ubi_thread(void *u)
ubi_msg("background thread \"%s\" started, PID %d",
ubi->bgt_name, current->pid);
+ set_freezable();
for (;;) {
int err;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 807e6992e614..e970e64bf966 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -26,7 +26,6 @@
TODO:
* Test Tx checksumming thoroughly
- * Implement dev->tx_timeout
Low priority TODO:
* Complete reset on PciErr
@@ -1218,6 +1217,30 @@ static int cp_close (struct net_device *dev)
return 0;
}
+static void cp_tx_timeout(struct net_device *dev)
+{
+ struct cp_private *cp = netdev_priv(dev);
+ unsigned long flags;
+ int rc;
+
+ printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n",
+ dev->name, cpr8(Cmd), cpr16(CpCmd),
+ cpr16(IntrStatus), cpr16(IntrMask));
+
+ spin_lock_irqsave(&cp->lock, flags);
+
+ cp_stop_hw(cp);
+ cp_clean_rings(cp);
+ rc = cp_init_rings(cp);
+ cp_start_hw(cp);
+
+ netif_wake_queue(dev);
+
+ spin_unlock_irqrestore(&cp->lock, flags);
+
+ return;
+}
+
#ifdef BROKEN
static int cp_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -1920,10 +1943,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->change_mtu = cp_change_mtu;
#endif
dev->ethtool_ops = &cp_ethtool_ops;
-#if 0
dev->tx_timeout = cp_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
-#endif
#if CP_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d17d64eb7065..43d03178064d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -205,7 +205,7 @@ config MII
config MACB
tristate "Atmel MACB support"
depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
- select MII
+ select PHYLIB
help
The Atmel MACB ethernet interface is found on many AT32 and AT91
parts. Say Y to include support for the MACB chip.
@@ -405,22 +405,6 @@ config ATARILANCE
on the AMD Lance chipset: RieblCard (with or without battery), or
PAMCard VME (also the version by Rhotron, with different addresses).
-config ATARI_BIONET
- tristate "BioNet-100 support"
- depends on ATARI && ATARI_ACSI && BROKEN
- help
- Say Y to include support for BioData's BioNet-100 Ethernet adapter
- for the ACSI port. The driver works (has to work...) with a polled
- I/O scheme, so it's rather slow :-(
-
-config ATARI_PAMSNET
- tristate "PAMsNet support"
- depends on ATARI && ATARI_ACSI && BROKEN
- help
- Say Y to include support for the PAMsNet Ethernet adapter for the
- ACSI port ("ACSI node"). The driver works (has to work...) with a
- polled I/O scheme, so it's rather slow :-(
-
config SUN3LANCE
tristate "Sun3/Sun3x on-board LANCE support"
depends on SUN3 || SUN3X
@@ -604,6 +588,12 @@ config CASSINI
Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
<http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+config SUNVNET
+ tristate "Sun Virtual Network support"
+ depends on SUN_LDOMS
+ help
+ Support for virtual network devices under Sun Logical Domains.
+
config NET_VENDOR_3COM
bool "3COM cards"
depends on ISA || EISA || MCA || PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c26b8674213c..eb4167622a6a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SUNBMAC) += sunbmac.o
obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
obj-$(CONFIG_CASSINI) += cassini.o
+obj-$(CONFIG_SUNVNET) += sunvnet.o
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_BMAC) += bmac.o
@@ -180,8 +181,6 @@ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o
-obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
-obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
obj-$(CONFIG_A2065) += a2065.o
obj-$(CONFIG_HYDRA) += hydra.o
obj-$(CONFIG_ARIADNE) += ariadne.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 1c3e293fbaf7..3b79c6cf21a3 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -75,8 +75,6 @@ extern struct net_device *atarilance_probe(int unit);
extern struct net_device *sun3lance_probe(int unit);
extern struct net_device *sun3_82586_probe(int unit);
extern struct net_device *apne_probe(int unit);
-extern struct net_device *bionet_probe(int unit);
-extern struct net_device *pamsnet_probe(int unit);
extern struct net_device *cs89x0_probe(int unit);
extern struct net_device *hplance_probe(int unit);
extern struct net_device *bagetlance_probe(int unit);
@@ -264,12 +262,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
#ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */
{apne_probe, 0},
#endif
-#ifdef CONFIG_ATARI_BIONET /* Atari Bionet Ethernet board */
- {bionet_probe, 0},
-#endif
-#ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */
- {pamsnet_probe, 0},
-#endif
#ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */
{mvme147lance_probe, 0},
#endif
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 5bf2d33887ac..f9cc2b621fe2 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -43,6 +43,7 @@ config ARM_AT91_ETHER
config EP93XX_ETH
tristate "EP93xx Ethernet support"
depends on ARM && ARCH_EP93XX
+ select MII
help
This is a driver for the ethernet hardware included in EP93xx CPUs.
Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
deleted file mode 100644
index 3d87bd2b4194..000000000000
--- a/drivers/net/atari_bionet.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* bionet.c BioNet-100 device driver for linux68k.
- *
- * Version: @(#)bionet.c 1.0 02/06/96
- *
- * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de>
- * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
- *
- * Little adaptions for integration into pl7 by Roman Hodek
- *
- * Some changes in bionet_poll_rx by Karl-Heinz Lohner
- *
- What is it ?
- ------------
- This driver controls the BIONET-100 LAN-Adapter which connects
- an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
-
- This version can be compiled as a loadable module (See the
- compile command at the bottom of this file).
- At load time, you can optionally set the debugging level and the
- fastest response time on the command line of 'insmod'.
-
- 'bionet_debug'
- controls the amount of diagnostic messages:
- 0 : no messages
- >0 : see code for meaning of printed messages
-
- 'bionet_min_poll_time' (always >=1)
- gives the time (in jiffies) between polls. Low values
- increase the system load (beware!)
-
- When loaded, a net device with the name 'bio0' becomes available,
- which can be controlled with the usual 'ifconfig' command.
-
- It is possible to compile this driver into the kernel like other
- (net) drivers. For this purpose, some source files (e.g. config-files
- makefiles, Space.c) must be changed accordingly. (You may refer to
- other drivers how to do it.) In this case, the device will be detected
- at boot time and (probably) appear as 'eth0'.
-
- This code is based on several sources:
- - The driver code for a parallel port ethernet adapter by
- Donald Becker (see file 'atp.c' from the PC linux distribution)
- - The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support
- and DMA handling.
- - Very limited information about moving packets in and out of the
- BIONET-adapter from the TCP package for TOS by BioData GmbH.
-
- Theory of Operation
- -------------------
- Because the ATARI DMA port is usually shared between several
- devices (eg. harddisk, floppy) we cannot block the ACSI bus
- while waiting for interrupts. Therefore we use a polling mechanism
- to fetch packets from the adapter. For the same reason, we send
- packets without checking that the previous packet has been sent to
- the LAN. We rely on the higher levels of the networking code to detect
- missing packets and resend them.
-
- Before we access the ATARI DMA controller, we check if another
- process is using the DMA. If not, we lock the DMA, perform one or
- more packet transfers and unlock the DMA before returning.
- We do not use 'stdma_lock' unconditionally because it is unclear
- if the networking code can be set to sleep, which will happen if
- another (possibly slow) device is using the DMA controller.
-
- The polling is done via timer interrupts which periodically
- 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
- between polls varies depending on an estimate of the net activity.
- The allowed range is given by the variable 'bionet_min_poll_time'
- for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
- for the higher (slowest) limit.
-
- Whenever a packet arrives, we switch to fastest response by setting
- the polling time to its lowest limit. If the following poll fails,
- because no packets have arrived, we increase the time for the next
- poll. When the net activity is low, the polling time effectively
- stays at its maximum value, resulting in the lowest load for the
- machine.
- */
-
-#define MAX_POLL_TIME 10
-
-static char version[] =
- "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-
-
-/* use 0 for production, 1 for verification, >2 for debug
- */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-/*
- * Global variable 'bionet_debug'. Can be set at load time by 'insmod'
- */
-unsigned int bionet_debug = NET_DEBUG;
-module_param(bionet_debug, int, 0);
-MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
-MODULE_LICENSE("GPL");
-
-static unsigned int bionet_min_poll_time = 2;
-
-
-/* Information that need to be kept for each board.
- */
-struct net_local {
- struct net_device_stats stats;
- long open_time; /* for debugging */
- int poll_time; /* polling time varies with net load */
-};
-
-static struct nic_pkt_s { /* packet format */
- unsigned char status;
- unsigned char dummy;
- unsigned char l_lo, l_hi;
- unsigned char buffer[3000];
-} *nic_packet;
-unsigned char *phys_nic_packet;
-
-/* Index to functions, as function prototypes.
- */
-static int bionet_open(struct net_device *dev);
-static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void bionet_poll_rx(struct net_device *);
-static int bionet_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void bionet_tick(unsigned long);
-
-static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0);
-
-#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
-
-/* The following routines access the ethernet board connected to the
- * ACSI port via the st_dma chip.
- */
-#define NODE_ADR 0x60
-
-#define C_READ 8
-#define C_WRITE 0x0a
-#define C_GETEA 0x0f
-#define C_SETCR 0x0e
-
-static int
-sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) {
- unsigned int c;
-
- dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88);
- dma_wd.fdc_acces_seccount = cmd;
- dma_wd.dma_mode_status = (mod | 0x8a);
-
- if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */
- return -1; /* timeout */
-
- c = dma_wd.fdc_acces_seccount;
- return (c & 0xff);
-}
-
-
-static void
-set_status(int cr) {
- sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */
- sendcmd(1,0x100,cr);
-
- dma_wd.dma_mode_status = 0x80;
-}
-
-static int
-get_status(unsigned char *adr) {
- int i,c;
-
- DISABLE_IRQ();
- c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/
- if( c < 0 ) goto gsend;
-
- /* now read status bytes */
-
- for (i=0; i<6; i++) {
- dma_wd.fdc_acces_seccount = 0; /* request next byte */
-
- if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */
- c = -1;
- goto gsend; /* timeout */
- }
- c = dma_wd.fdc_acces_seccount;
- *adr++ = (unsigned char)c;
- }
- c = 1;
-gsend:
- dma_wd.dma_mode_status = 0x80;
- return c;
-}
-
-static irqreturn_t
-bionet_intr(int irq, void *data) {
- return IRQ_HANDLED;
-}
-
-
-static int
-get_frame(unsigned long paddr, int odd) {
- int c;
- unsigned long flags;
-
- DISABLE_IRQ();
- local_irq_save(flags);
-
- dma_wd.dma_mode_status = 0x9a;
- dma_wd.dma_mode_status = 0x19a;
- dma_wd.dma_mode_status = 0x9a;
- dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */
- dma_wd.dma_lo = (unsigned char)paddr;
- paddr >>= 8;
- dma_wd.dma_md = (unsigned char)paddr;
- paddr >>= 8;
- dma_wd.dma_hi = (unsigned char)paddr;
- local_irq_restore(flags);
-
- c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */
- if( c < 128 ) goto rend;
-
- /* now read block */
-
- c = sendcmd(1,0x00,odd); /* odd flag for address shift */
- dma_wd.dma_mode_status = 0x0a;
-
- if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */
- c = -1;
- goto rend;
- }
- dma_wd.dma_mode_status = 0x8a;
- dma_wd.dma_mode_status = 0x18a;
- dma_wd.dma_mode_status = 0x8a;
- c = dma_wd.fdc_acces_seccount;
-
- dma_wd.dma_mode_status = 0x88;
- c = dma_wd.fdc_acces_seccount;
- c = 1;
-
-rend:
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ(20);
- return c;
-}
-
-
-static int
-hardware_send_packet(unsigned long paddr, int cnt) {
- unsigned int c;
- unsigned long flags;
-
- DISABLE_IRQ();
- local_irq_save(flags);
-
- dma_wd.dma_mode_status = 0x19a;
- dma_wd.dma_mode_status = 0x9a;
- dma_wd.dma_mode_status = 0x19a;
- dma_wd.dma_lo = (unsigned char)paddr;
- paddr >>= 8;
- dma_wd.dma_md = (unsigned char)paddr;
- paddr >>= 8;
- dma_wd.dma_hi = (unsigned char)paddr;
-
- dma_wd.fdc_acces_seccount = 0x4; /* sector count */
- local_irq_restore(flags);
-
- c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */
- c = sendcmd(1,0x100,cnt&0xff);
- c = sendcmd(1,0x100,cnt>>8);
-
- /* now write block */
-
- dma_wd.dma_mode_status = 0x10a; /* DMA enable */
- if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */
- goto end;
-
- dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */
- c = dma_wd.fdc_acces_seccount;
-
-end:
- c = sendcmd(1,0x100,0);
- c = sendcmd(1,0x100,0);
-
- dma_wd.dma_mode_status = 0x180;
- udelay(40);
- acsi_wait_for_noIRQ(20);
- return( c & 0x02);
-}
-
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
- */
-struct net_device * __init bionet_probe(int unit)
-{
- struct net_device *dev;
- unsigned char station_addr[6];
- static unsigned version_printed;
- static int no_more_found; /* avoid "Probing for..." printed 4 times */
- int i;
- int err;
-
- if (!MACH_IS_ATARI || no_more_found)
- return ERR_PTR(-ENODEV);
-
- dev = alloc_etherdev(sizeof(struct net_local));
- if (!dev)
- return ERR_PTR(-ENOMEM);
- if (unit >= 0) {
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- }
- SET_MODULE_OWNER(dev);
-
- printk("Probing for BioNet 100 Adapter...\n");
-
- stdma_lock(bionet_intr, NULL);
- i = get_status(station_addr); /* Read the station address PROM. */
- ENABLE_IRQ();
- stdma_release();
-
- /* Check the first three octets of the S.A. for the manufactor's code.
- */
-
- if( i < 0
- || station_addr[0] != 'B'
- || station_addr[1] != 'I'
- || station_addr[2] != 'O' ) {
- no_more_found = 1;
- printk( "No BioNet 100 found.\n" );
- free_netdev(dev);
- return ERR_PTR(-ENODEV);
- }
-
- if (bionet_debug > 0 && version_printed++ == 0)
- printk(version);
-
- printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n",
- dev->name, "BioNet 100",
- station_addr[0], station_addr[1], station_addr[2],
- station_addr[3], station_addr[4], station_addr[5]);
-
- /* Initialize the device structure. */
-
- nic_packet = (struct nic_pkt_s *)acsi_buffer;
- phys_nic_packet = (unsigned char *)phys_acsi_buffer;
- if (bionet_debug > 0) {
- printk("nic_packet at 0x%p, phys at 0x%p\n",
- nic_packet, phys_nic_packet );
- }
-
- dev->open = bionet_open;
- dev->stop = bionet_close;
- dev->hard_start_xmit = bionet_send_packet;
- dev->get_stats = net_get_stats;
-
- /* Fill in the fields of the device structure with ethernet-generic
- * values. This should be in a common file instead of per-driver.
- */
-
- for (i = 0; i < ETH_ALEN; i++) {
-#if 0
- dev->broadcast[i] = 0xff;
-#endif
- dev->dev_addr[i] = station_addr[i];
- }
- err = register_netdev(dev);
- if (!err)
- return dev;
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
-/* Open/initialize the board. This is called (in the current kernel)
- sometime after booting when the 'ifconfig' program is run.
-
- This routine should set everything up anew at each open, even
- registers that "should" only need to be set once at boot, so that
- there is non-reboot way to recover if something goes wrong.
- */
-static int
-bionet_open(struct net_device *dev) {
- struct net_local *lp = netdev_priv(dev);
-
- if (bionet_debug > 0)
- printk("bionet_open\n");
- stdma_lock(bionet_intr, NULL);
-
- /* Reset the hardware here.
- */
- set_status(4);
- lp->open_time = 0; /*jiffies*/
- lp->poll_time = MAX_POLL_TIME;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
- stdma_release();
- bionet_timer.data = (long)dev;
- bionet_timer.expires = jiffies + lp->poll_time;
- add_timer(&bionet_timer);
- return 0;
-}
-
-static int
-bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
- struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
-
- /* Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
- */
- local_irq_save(flags);
-
- if (stdma_islocked()) {
- local_irq_restore(flags);
- lp->stats.tx_errors++;
- }
- else {
- int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned long buf = virt_to_phys(skb->data);
- int stat;
-
- stdma_lock(bionet_intr, NULL);
- local_irq_restore(flags);
- if( !STRAM_ADDR(buf+length-1) ) {
- skb_copy_from_linear_data(skb, nic_packet->buffer,
- length);
- buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
- }
-
- if (bionet_debug >1) {
- u_char *data = nic_packet->buffer, *p;
- int i;
-
- printk( "%s: TX pkt type 0x%4x from ", dev->name,
- ((u_short *)data)[6]);
-
- for( p = &data[6], i = 0; i < 6; i++ )
- printk("%02x%s", *p++,i != 5 ? ":" : "" );
- printk(" to ");
-
- for( p = data, i = 0; i < 6; i++ )
- printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
-
- printk( "%s: ", dev->name );
- printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
- " %02x%02x%02x%02x len %d\n",
- data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
- data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
- data[28], data[29], data[30], data[31], data[32], data[33],
- length );
- }
- dma_cache_maintenance(buf, length, 1);
-
- stat = hardware_send_packet(buf, length);
- ENABLE_IRQ();
- stdma_release();
-
- dev->trans_start = jiffies;
- dev->tbusy = 0;
- lp->stats.tx_packets++;
- lp->stats.tx_bytes+=length;
- }
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-/* We have a good packet(s), get it/them out of the buffers.
- */
-static void
-bionet_poll_rx(struct net_device *dev) {
- struct net_local *lp = netdev_priv(dev);
- int boguscount = 10;
- int pkt_len, status;
- unsigned long flags;
-
- local_irq_save(flags);
- /* ++roman: Take care at locking the ST-DMA... This must be done with ints
- * off, since otherwise an int could slip in between the question and the
- * locking itself, and then we'd go to sleep... And locking itself is
- * necessary to keep the floppy_change timer from working with ST-DMA
- * registers. */
- if (stdma_islocked()) {
- local_irq_restore(flags);
- return;
- }
- stdma_lock(bionet_intr, NULL);
- DISABLE_IRQ();
- local_irq_restore(flags);
-
- if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
-
- while(boguscount--) {
- status = get_frame((unsigned long)phys_nic_packet, 0);
-
- if( status == 0 ) break;
-
- /* Good packet... */
-
- dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0);
-
- pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo;
-
- lp->poll_time = bionet_min_poll_time; /* fast poll */
- if( pkt_len >= 60 && pkt_len <= 1520 ) {
- /* ^^^^ war 1514 KHL */
- /* Malloc up new buffer.
- */
- struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 );
- if (skb == NULL) {
- printk("%s: Memory squeeze, dropping packet.\n",
- dev->name);
- lp->stats.rx_dropped++;
- break;
- }
-
- skb_reserve( skb, 2 ); /* 16 Byte align */
- skb_put( skb, pkt_len ); /* make room */
-
- /* 'skb->data' points to the start of sk_buff data area.
- */
- skb_copy_to_linear_data(skb, nic_packet->buffer,
- pkt_len);
- skb->protocol = eth_type_trans( skb, dev );
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes+=pkt_len;
-
- /* If any worth-while packets have been received, dev_rint()
- has done a mark_bh(INET_BH) for us and will work on them
- when we get to the bottom-half routine.
- */
-
- if (bionet_debug >1) {
- u_char *data = nic_packet->buffer, *p;
- int i;
-
- printk( "%s: RX pkt type 0x%4x from ", dev->name,
- ((u_short *)data)[6]);
-
-
- for( p = &data[6], i = 0; i < 6; i++ )
- printk("%02x%s", *p++,i != 5 ? ":" : "" );
- printk(" to ");
- for( p = data, i = 0; i < 6; i++ )
- printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" );
-
- printk( "%s: ", dev->name );
- printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x"
- " %02x%02x%02x%02x len %d\n",
- data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19],
- data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27],
- data[28], data[29], data[30], data[31], data[32], data[33],
- pkt_len );
- }
- }
- else {
- printk(" Packet has wrong length: %04d bytes\n", pkt_len);
- lp->stats.rx_errors++;
- }
- }
- stdma_release();
- ENABLE_IRQ();
- return;
-}
-
-/* bionet_tick: called by bionet_timer. Reads packets from the adapter,
- * passes them to the higher layers and restarts the timer.
- */
-static void
-bionet_tick(unsigned long data) {
- struct net_device *dev = (struct net_device *)data;
- struct net_local *lp = netdev_priv(dev);
-
- if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 )
- printk("bionet_tick: %ld\n", lp->open_time);
-
- if( !stdma_islocked() ) bionet_poll_rx(dev);
-
- bionet_timer.expires = jiffies + lp->poll_time;
- add_timer(&bionet_timer);
-}
-
-/* The inverse routine to bionet_open().
- */
-static int
-bionet_close(struct net_device *dev) {
- struct net_local *lp = netdev_priv(dev);
-
- if (bionet_debug > 0)
- printk("bionet_close, open_time=%ld\n", lp->open_time);
- del_timer(&bionet_timer);
- stdma_lock(bionet_intr, NULL);
-
- set_status(0);
- lp->open_time = 0;
-
- dev->tbusy = 1;
- dev->start = 0;
-
- stdma_release();
- return 0;
-}
-
-/* Get the current statistics.
- This may be called with the card open or closed.
- */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- return &lp->stats;
-}
-
-
-#ifdef MODULE
-
-static struct net_device *bio_dev;
-
-int init_module(void)
-{
- bio_dev = bionet_probe(-1);
- if (IS_ERR(bio_dev))
- return PTR_ERR(bio_dev);
- return 0;
-}
-
-void cleanup_module(void)
-{
- unregister_netdev(bio_dev);
- free_netdev(bio_dev);
-}
-
-#endif /* MODULE */
-
-/* Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
- -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
- -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 8
- * End:
- */
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
deleted file mode 100644
index f7356374a2e7..000000000000
--- a/drivers/net/atari_pamsnet.c
+++ /dev/null
@@ -1,878 +0,0 @@
-/* atari_pamsnet.c PAMsNet device driver for linux68k.
- *
- * Version: @(#)PAMsNet.c 0.2ß 03/31/96
- *
- * Author: Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de>
- * <Torsten.Lang@jung.de>
- *
- * This driver is based on my driver PAMSDMA.c for MiNT-Net and
- * on the driver bionet.c written by
- * Hartmut Laue <laue@ifk-mp.uni-kiel.de>
- * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de>
- *
- * Little adaptions for integration into pl7 by Roman Hodek
- *
- What is it ?
- ------------
- This driver controls the PAMsNet LAN-Adapter which connects
- an ATARI ST/TT via the ACSI-port to an Ethernet-based network.
-
- This version can be compiled as a loadable module (See the
- compile command at the bottom of this file).
- At load time, you can optionally set the debugging level and the
- fastest response time on the command line of 'insmod'.
-
- 'pamsnet_debug'
- controls the amount of diagnostic messages:
- 0 : no messages
- >0 : see code for meaning of printed messages
-
- 'pamsnet_min_poll_time' (always >=1)
- gives the time (in jiffies) between polls. Low values
- increase the system load (beware!)
-
- When loaded, a net device with the name 'eth?' becomes available,
- which can be controlled with the usual 'ifconfig' command.
-
- It is possible to compile this driver into the kernel like other
- (net) drivers. For this purpose, some source files (e.g. config-files
- makefiles, Space.c) must be changed accordingly. (You may refer to
- other drivers how to do it.) In this case, the device will be detected
- at boot time and (probably) appear as 'eth0'.
-
- Theory of Operation
- -------------------
- Because the ATARI DMA port is usually shared between several
- devices (eg. harddisk, floppy) we cannot block the ACSI bus
- while waiting for interrupts. Therefore we use a polling mechanism
- to fetch packets from the adapter. For the same reason, we send
- packets without checking that the previous packet has been sent to
- the LAN. We rely on the higher levels of the networking code to detect
- missing packets and resend them.
-
- Before we access the ATARI DMA controller, we check if another
- process is using the DMA. If not, we lock the DMA, perform one or
- more packet transfers and unlock the DMA before returning.
- We do not use 'stdma_lock' unconditionally because it is unclear
- if the networking code can be set to sleep, which will happen if
- another (possibly slow) device is using the DMA controller.
-
- The polling is done via timer interrupts which periodically
- 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies)
- between polls varies depending on an estimate of the net activity.
- The allowed range is given by the variable 'bionet_min_poll_time'
- for the lower (fastest) limit and the constant 'MAX_POLL_TIME'
- for the higher (slowest) limit.
-
- Whenever a packet arrives, we switch to fastest response by setting
- the polling time to its lowest limit. If the following poll fails,
- because no packets have arrived, we increase the time for the next
- poll. When the net activity is low, the polling time effectively
- stays at its maximum value, resulting in the lowest load for the
- machine.
- */
-
-#define MAX_POLL_TIME 10
-
-static char *version =
- "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_acsi.h>
-
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#undef READ
-#undef WRITE
-
-/* use 0 for production, 1 for verification, >2 for debug
- */
-#ifndef NET_DEBUG
-#define NET_DEBUG 0
-#endif
-/*
- * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod'
- */
-unsigned int pamsnet_debug = NET_DEBUG;
-module_param(pamsnet_debug, int, 0);
-MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
-MODULE_LICENSE("GPL");
-
-static unsigned int pamsnet_min_poll_time = 2;
-
-
-/* Information that need to be kept for each board.
- */
-struct net_local {
- struct net_device_stats stats;
- long open_time; /* for debugging */
- int poll_time; /* polling time varies with net load */
-};
-
-static struct nic_pkt_s { /* packet format */
- unsigned char buffer[2048];
-} *nic_packet = 0;
-unsigned char *phys_nic_packet;
-
-typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */
-
-/* Index to functions, as function prototypes.
- */
-static void start (int target);
-static int stop (int target);
-static int testpkt (int target);
-static int sendpkt (int target, unsigned char *buffer, int length);
-static int receivepkt (int target, unsigned char *buffer);
-static int inquiry (int target, unsigned char *buffer);
-static HADDR *read_hw_addr(int target, unsigned char *buffer);
-static void setup_dma (void *address, unsigned rw_flag, int num_blocks);
-static int send_first (int target, unsigned char byte);
-static int send_1_5 (int lun, unsigned char *command, int dma);
-static int get_status (void);
-static int calc_received (void *start_address);
-
-static int pamsnet_open(struct net_device *dev);
-static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void pamsnet_poll_rx(struct net_device *);
-static int pamsnet_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void pamsnet_tick(unsigned long);
-
-static irqreturn_t pamsnet_intr(int irq, void *data);
-
-static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
-
-#define STRAM_ADDR(a) (((a) & 0xff000000) == 0)
-
-typedef struct
-{
- unsigned char reserved1[0x38];
- HADDR hwaddr;
- unsigned char reserved2[0x1c2];
-} DMAHWADDR;
-
-/*
- * Definitions of commands understood by the PAMs DMA adaptor.
- *
- * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable
- * by the PAM's Net software.
- *
- * LUN 0 works as a harddisk. You can boot the PAM's Net driver there.
- * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW
- * area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address
- * of the adaptor.
- * LUN 6 works as a harddisk and lets you access the firmware ROM.
- * LUN 7 lets you send and receive packets.
- *
- * Some commands like the INQUIRY command work identical on all used LUNs.
- *
- * UNKNOWN1 seems to read some data.
- * Command length is 6 bytes.
- * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The
- * following bytes seem to be something like an allocation length.
- * Command length is 6 bytes.
- * READPKT reads a packet received by the DMA adaptor.
- * Command length is 6 bytes.
- * WRITEPKT sends a packet transferred by the following DMA phase. The length
- * of the packet is transferred in command bytes 3 and 4.
- * The adaptor automatically replaces the src hw address in an ethernet
- * packet by its own hw address.
- * Command length is 6 bytes.
- * INQUIRY has the same function as the INQUIRY command supported by harddisks
- * and other SCSI devices. It lets you detect which device you found
- * at a given address.
- * Command length is 6 bytes.
- * START initializes the DMA adaptor. After this command it is able to send
- * and receive packets. There is no status byte returned!
- * Command length is 1 byte.
- * NUMPKTS gives back the number of received packets waiting in the queue in
- * the status byte.
- * Command length is 1 byte.
- * UNKNOWN3
- * UNKNOWN4 Function of these three commands is unknown.
- * UNKNOWN5 The command length of these three commands is 1 byte.
- * DESELECT immediately deselects the DMA adaptor. May important with interrupt
- * driven operation.
- * Command length is 1 byte.
- * STOP resets the DMA adaptor. After this command packets can no longer
- * be received or transferred.
- * Command length is 6 byte.
- */
-
-enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START,
- NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP};
-
-#define READSECTOR READPKT
-#define WRITESECTOR WRITEPKT
-
-u_char *inquire8="MV PAM's NET/GK";
-
-#define DMALOW dma_wd.dma_lo
-#define DMAMID dma_wd.dma_md
-#define DMAHIGH dma_wd.dma_hi
-#define DACCESS dma_wd.fdc_acces_seccount
-
-#define MFP_GPIP mfp.par_dt_reg
-
-/* Some useful functions */
-
-#define INT (!(MFP_GPIP & 0x20))
-#define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;})
-#define WRITEMODE(value) \
- ({ u_short dummy = value; \
- __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy)); \
- DELAY; \
- })
-#define WRITEBOTH(value1, value2) \
- ({ u_long dummy = (u_long)(value1)<<16 | (u_short)(value2); \
- __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy)); \
- DELAY; \
- })
-
-/* Definitions for DMODE */
-
-#define READ 0x000
-#define WRITE 0x100
-
-#define DMA_FDC 0x080
-#define DMA_ACSI 0x000
-
-#define DMA_DISABLE 0x040
-
-#define SEC_COUNT 0x010
-#define DMA_WINDOW 0x000
-
-#define REG_ACSI 0x008
-#define REG_FDC 0x000
-
-#define A1 0x002
-
-/* Timeout constants */
-
-#define TIMEOUTCMD HZ/2 /* ca. 500ms */
-#define TIMEOUTDMA HZ /* ca. 1s */
-#define COMMAND_DELAY 500 /* ca. 0.5ms */
-
-unsigned rw;
-int lance_target = -1;
-int if_up = 0;
-
-/* The following routines access the ethernet board connected to the
- * ACSI port via the st_dma chip.
- */
-
-/* The following lowlevel routines work on physical addresses only and assume
- * that eventually needed buffers are
- * - completely located in ST RAM
- * - are contigous in the physical address space
- */
-
-/* Setup the DMA counter */
-
-static void
-setup_dma (void *address, unsigned rw_flag, int num_blocks)
-{
- WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI |
- A1);
- WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI |
- A1);
- WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI |
- A1);
- DMALOW = (unsigned char)((unsigned long)address & 0xFF);
- DMAMID = (unsigned char)(((unsigned long)address >> 8) & 0xFF);
- DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF);
- WRITEBOTH((unsigned)num_blocks & 0xFF,
- rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
- rw = rw_flag;
-}
-
-/* Send the first byte of an command block */
-
-static int
-send_first (int target, unsigned char byte)
-{
- rw = READ;
- acsi_delay_end(COMMAND_DELAY);
- /*
- * wake up ACSI
- */
- WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI);
- /*
- * write command byte
- */
- WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC |
- DMA_WINDOW | REG_ACSI | A1);
- return (!acsi_wait_for_IRQ(TIMEOUTCMD));
-}
-
-/* Send the rest of an command block */
-
-static int
-send_1_5 (int lun, unsigned char *command, int dma)
-{
- int i, j;
-
- for (i=0; i<5; i++) {
- WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F))
- : command[i]),
- rw | REG_ACSI | DMA_WINDOW |
- ((i < 4) ? DMA_FDC
- : (dma ? DMA_ACSI
- : DMA_FDC)) | A1);
- if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD)))
- return (j);
- }
- return (0);
-}
-
-/* Read a status byte */
-
-static int
-get_status (void)
-{
- WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1);
- acsi_delay_start();
- return ((int)(DACCESS & 0xFF));
-}
-
-/* Calculate the number of received bytes */
-
-static int
-calc_received (void *start_address)
-{
- return (int)(
- (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
- - (unsigned long)start_address);
-}
-
-/* The following midlevel routines still work on physical addresses ... */
-
-/* start() starts the PAM's DMA adaptor */
-
-static void
-start (int target)
-{
- send_first(target, START);
-}
-
-/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
-
-static int
-stop (int target)
-{
- int ret = -1;
- unsigned char cmd_buffer[5];
-
- if (send_first(target, STOP))
- goto bad;
- cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] =
- cmd_buffer[3] = cmd_buffer[4] = 0;
- if (send_1_5(7, cmd_buffer, 0) ||
- !acsi_wait_for_IRQ(TIMEOUTDMA) ||
- get_status())
- goto bad;
- ret = 0;
-bad:
- return (ret);
-}
-
-/* testpkt() returns the number of received packets waiting in the queue */
-
-static int
-testpkt(int target)
-{
- int ret = -1;
-
- if (send_first(target, NUMPKTS))
- goto bad;
- ret = get_status();
-bad:
- return (ret);
-}
-
-/* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */
-/* Please note: The buffer is for internal use only but must be defined! */
-
-static int
-inquiry (int target, unsigned char *buffer)
-{
- int ret = -1;
- unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
- unsigned char cmd_buffer[5];
-
- if (send_first(target, INQUIRY))
- goto bad;
- setup_dma(buffer, READ, 1);
- vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */
- cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
- cmd_buffer[3] = 48;
- if (send_1_5(5, cmd_buffer, 1) ||
- !acsi_wait_for_IRQ(TIMEOUTDMA) ||
- get_status() ||
- (calc_received(buffer) < 32))
- goto bad;
- dma_cache_maintenance((unsigned long)(buffer+8), 20, 0);
- if (memcmp(inquire8, vbuffer+8, 20))
- goto bad;
- ret = 0;
-bad:
- if (!!NET_DEBUG) {
- vbuffer[8+20]=0;
- printk("inquiry of target %d: %s\n", target, vbuffer+8);
- }
- return (ret);
-}
-
-/*
- * read_hw_addr() reads the sector containing the hwaddr and returns
- * a pointer to it (virtual address!) or 0 in case of an error
- */
-
-static HADDR
-*read_hw_addr(int target, unsigned char *buffer)
-{
- HADDR *ret = 0;
- unsigned char cmd_buffer[5];
-
- if (send_first(target, READSECTOR))
- goto bad;
- setup_dma(buffer, READ, 1);
- cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
- cmd_buffer[3] = 1;
- if (send_1_5(5, cmd_buffer, 1) ||
- !acsi_wait_for_IRQ(TIMEOUTDMA) ||
- get_status())
- goto bad;
- ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr));
- dma_cache_maintenance((unsigned long)buffer, 512, 0);
-bad:
- return (ret);
-}
-
-static irqreturn_t
-pamsnet_intr(int irq, void *data)
-{
- return IRQ_HANDLED;
-}
-
-/* receivepkt() loads a packet to a given buffer and returns its length */
-
-static int
-receivepkt (int target, unsigned char *buffer)
-{
- int ret = -1;
- unsigned char cmd_buffer[5];
-
- if (send_first(target, READPKT))
- goto bad;
- setup_dma(buffer, READ, 3);
- cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0;
- cmd_buffer[3] = 3;
- if (send_1_5(7, cmd_buffer, 1) ||
- !acsi_wait_for_IRQ(TIMEOUTDMA) ||
- get_status())
- goto bad;
- ret = calc_received(buffer);
-bad:
- return (ret);
-}
-
-/* sendpkt() sends a packet and returns a value of zero when the packet was sent
- successfully */
-
-static int
-sendpkt (int target, unsigned char *buffer, int length)
-{
- int ret = -1;
- unsigned char cmd_buffer[5];
-
- if (send_first(target, WRITEPKT))
- goto bad;
- setup_dma(buffer, WRITE, 3);
- cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0;
- cmd_buffer[2] = length >> 8;
- cmd_buffer[3] = length & 0xFF;
- if (send_1_5(7, cmd_buffer, 1) ||
- !acsi_wait_for_IRQ(TIMEOUTDMA) ||
- get_status())
- goto bad;
- ret = 0;
-bad:
- return (ret);
-}
-
-/* The following higher level routines work on virtual addresses and convert them to
- * physical addresses when passed to the lowlevel routines. It's up to the higher level
- * routines to copy data from Alternate RAM to ST RAM if neccesary!
- */
-
-/* Check for a network adaptor of this type, and return '0' if one exists.
- */
-
-struct net_device * __init pamsnet_probe (int unit)
-{
- struct net_device *dev;
- int i;
- HADDR *hwaddr;
- int err;
-
- unsigned char station_addr[6];
- static unsigned version_printed;
- /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */
- static int no_more_found;
-
- if (no_more_found)
- return ERR_PTR(-ENODEV);
- no_more_found = 1;
-
- dev = alloc_etherdev(sizeof(struct net_local));
- if (!dev)
- return ERR_PTR(-ENOMEM);
- if (unit >= 0) {
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- }
- SET_MODULE_OWNER(dev);
-
- printk("Probing for PAM's Net/GK Adapter...\n");
-
- /* Allocate the DMA buffer here since we need it for probing! */
-
- nic_packet = (struct nic_pkt_s *)acsi_buffer;
- phys_nic_packet = (unsigned char *)phys_acsi_buffer;
- if (pamsnet_debug > 0) {
- printk("nic_packet at 0x%p, phys at 0x%p\n",
- nic_packet, phys_nic_packet );
- }
-
- stdma_lock(pamsnet_intr, NULL);
- DISABLE_IRQ();
-
- for (i=0; i<8; i++) {
- /* Do two inquiries to cover cases with strange equipment on previous ID */
- /* blocking the ACSI bus (like the SLMC804 laser printer controller... */
- inquiry(i, phys_nic_packet);
- if (!inquiry(i, phys_nic_packet)) {
- lance_target = i;
- break;
- }
- }
-
- if (!!NET_DEBUG)
- printk("ID: %d\n",i);
-
- if (lance_target >= 0) {
- if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet)))
- lance_target = -1;
- else
- memcpy (station_addr, hwaddr, ETH_ALEN);
- }
-
- ENABLE_IRQ();
- stdma_release();
-
- if (lance_target < 0) {
- printk("No PAM's Net/GK found.\n");
- free_netdev(dev);
- return ERR_PTR(-ENODEV);
- }
-
- if (pamsnet_debug > 0 && version_printed++ == 0)
- printk(version);
-
- printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n",
- dev->name, "PAM's Net/GK", lance_target,
- station_addr[0], station_addr[1], station_addr[2],
- station_addr[3], station_addr[4], station_addr[5]);
-
- /* Initialize the device structure. */
- dev->open = pamsnet_open;
- dev->stop = pamsnet_close;
- dev->hard_start_xmit = pamsnet_send_packet;
- dev->get_stats = net_get_stats;
-
- /* Fill in the fields of the device structure with ethernet-generic
- * values. This should be in a common file instead of per-driver.
- */
-
- for (i = 0; i < ETH_ALEN; i++) {
-#if 0
- dev->broadcast[i] = 0xff;
-#endif
- dev->dev_addr[i] = station_addr[i];
- }
- err = register_netdev(dev);
- if (!err)
- return dev;
-
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
-/* Open/initialize the board. This is called (in the current kernel)
- sometime after booting when the 'ifconfig' program is run.
-
- This routine should set everything up anew at each open, even
- registers that "should" only need to be set once at boot, so that
- there is non-reboot way to recover if something goes wrong.
- */
-static int
-pamsnet_open(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- if (pamsnet_debug > 0)
- printk("pamsnet_open\n");
- stdma_lock(pamsnet_intr, NULL);
- DISABLE_IRQ();
-
- /* Reset the hardware here.
- */
- if (!if_up)
- start(lance_target);
- if_up = 1;
- lp->open_time = 0; /*jiffies*/
- lp->poll_time = MAX_POLL_TIME;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
- ENABLE_IRQ();
- stdma_release();
- pamsnet_timer.data = (long)dev;
- pamsnet_timer.expires = jiffies + lp->poll_time;
- add_timer(&pamsnet_timer);
- return 0;
-}
-
-static int
-pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
-
- /* Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
- */
- local_irq_save(flags);
-
- if (stdma_islocked()) {
- local_irq_restore(flags);
- lp->stats.tx_errors++;
- }
- else {
- int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned long buf = virt_to_phys(skb->data);
- int stat;
-
- stdma_lock(pamsnet_intr, NULL);
- DISABLE_IRQ();
-
- local_irq_restore(flags);
- if( !STRAM_ADDR(buf+length-1) ) {
- skb_copy_from_linear_data(skb, nic_packet->buffer,
- length);
- buf = (unsigned long)phys_nic_packet;
- }
-
- dma_cache_maintenance(buf, length, 1);
-
- stat = sendpkt(lance_target, (unsigned char *)buf, length);
- ENABLE_IRQ();
- stdma_release();
-
- dev->trans_start = jiffies;
- dev->tbusy = 0;
- lp->stats.tx_packets++;
- lp->stats.tx_bytes+=length;
- }
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-/* We have a good packet(s), get it/them out of the buffers.
- */
-static void
-pamsnet_poll_rx(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- int boguscount;
- int pkt_len;
- struct sk_buff *skb;
- unsigned long flags;
-
- local_irq_save(flags);
- /* ++roman: Take care at locking the ST-DMA... This must be done with ints
- * off, since otherwise an int could slip in between the question and the
- * locking itself, and then we'd go to sleep... And locking itself is
- * necessary to keep the floppy_change timer from working with ST-DMA
- * registers. */
- if (stdma_islocked()) {
- local_irq_restore(flags);
- return;
- }
- stdma_lock(pamsnet_intr, NULL);
- DISABLE_IRQ();
- local_irq_restore(flags);
-
- boguscount = testpkt(lance_target);
- if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
-
- while(boguscount--) {
- pkt_len = receivepkt(lance_target, phys_nic_packet);
-
- if( pkt_len < 60 ) break;
-
- /* Good packet... */
-
- dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0);
-
- lp->poll_time = pamsnet_min_poll_time; /* fast poll */
- if( pkt_len >= 60 && pkt_len <= 2048 ) {
- if (pkt_len > 1514)
- pkt_len = 1514;
-
- /* Malloc up new buffer.
- */
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
- if (skb == NULL) {
- printk("%s: Memory squeeze, dropping packet.\n",
- dev->name);
- lp->stats.rx_dropped++;
- break;
- }
- skb->len = pkt_len;
- skb->dev = dev;
-
- /* 'skb->data' points to the start of sk_buff data area.
- */
- skb_copy_to_linear_data(skb, nic_packet->buffer,
- pkt_len);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes+=pkt_len;
- }
- }
-
- /* If any worth-while packets have been received, dev_rint()
- has done a mark_bh(INET_BH) for us and will work on them
- when we get to the bottom-half routine.
- */
-
- ENABLE_IRQ();
- stdma_release();
- return;
-}
-
-/* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter,
- * passes them to the higher layers and restarts the timer.
- */
-static void
-pamsnet_tick(unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- struct net_local *lp = netdev_priv(dev);
-
- if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 )
- printk("pamsnet_tick: %ld\n", lp->open_time);
-
- pamsnet_poll_rx(dev);
-
- pamsnet_timer.expires = jiffies + lp->poll_time;
- add_timer(&pamsnet_timer);
-}
-
-/* The inverse routine to pamsnet_open().
- */
-static int
-pamsnet_close(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- if (pamsnet_debug > 0)
- printk("pamsnet_close, open_time=%ld\n", lp->open_time);
- del_timer(&pamsnet_timer);
- stdma_lock(pamsnet_intr, NULL);
- DISABLE_IRQ();
-
- if (if_up)
- stop(lance_target);
- if_up = 0;
-
- lp->open_time = 0;
-
- dev->tbusy = 1;
- dev->start = 0;
-
- ENABLE_IRQ();
- stdma_release();
- return 0;
-}
-
-/* Get the current statistics.
- This may be called with the card open or closed.
- */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- return &lp->stats;
-}
-
-
-#ifdef MODULE
-
-static struct net_device *pam_dev;
-
-int init_module(void)
-{
- pam_dev = pamsnet_probe(-1);
- if (IS_ERR(pam_dev))
- return PTR_ERR(pam_dev);
- return 0;
-}
-
-void cleanup_module(void)
-{
- unregister_netdev(pam_dev);
- free_netdev(pam_dev);
-}
-
-#endif /* MODULE */
-
-/* Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include
- -b m68k-linuxaout -Wall -Wstrict-prototypes -O2
- -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 8
- * End:
- */
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
index df4c1a0071aa..ff4765f6c3de 100644
--- a/drivers/net/atl1/atl1.h
+++ b/drivers/net/atl1/atl1.h
@@ -43,6 +43,7 @@ extern const struct ethtool_ops atl1_ethtool_ops;
struct atl1_adapter;
#define ATL1_MAX_INTR 3
+#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */
#define ATL1_DEFAULT_TPD 256
#define ATL1_MAX_TPD 1024
@@ -57,29 +58,45 @@ struct atl1_adapter;
#define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc)
/*
+ * This detached comment is preserved for documentation purposes only.
+ * It was originally attached to some code that got deleted, but seems
+ * important enough to keep around...
+ *
+ * <begin detached comment>
* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
* but cannot process phy register reads/writes faster than millisecond
* intervals...and we establish link due to a "link status change" interrupt.
+ * <end detached comment>
+ */
+
+/*
+ * atl1_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
*/
+struct atl1_ring_header {
+ void *desc; /* virtual address */
+ dma_addr_t dma; /* physical address*/
+ unsigned int size; /* length in bytes */
+};
/*
- * wrapper around a pointer to a socket buffer,
- * so a DMA handle can be stored along with the buffer
+ * atl1_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
*/
struct atl1_buffer {
- struct sk_buff *skb;
- u16 length;
- u16 alloced;
+ struct sk_buff *skb; /* socket buffer */
+ u16 length; /* rx buffer length */
+ u16 alloced; /* 1 if skb allocated */
dma_addr_t dma;
};
-#define MAX_TX_BUF_LEN 0x3000 /* 12KB */
-
+/* transmit packet descriptor (tpd) ring */
struct atl1_tpd_ring {
- void *desc; /* pointer to the descriptor ring memory */
- dma_addr_t dma; /* physical adress of the descriptor ring */
- u16 size; /* length of descriptor ring in bytes */
+ void *desc; /* descriptor ring virtual address */
+ dma_addr_t dma; /* descriptor ring physical address */
+ u16 size; /* descriptor ring length in bytes */
u16 count; /* number of descriptors in the ring */
u16 hw_idx; /* hardware index */
atomic_t next_to_clean;
@@ -87,36 +104,34 @@ struct atl1_tpd_ring {
struct atl1_buffer *buffer_info;
};
+/* receive free descriptor (rfd) ring */
struct atl1_rfd_ring {
- void *desc;
- dma_addr_t dma;
- u16 size;
- u16 count;
+ void *desc; /* descriptor ring virtual address */
+ dma_addr_t dma; /* descriptor ring physical address */
+ u16 size; /* descriptor ring length in bytes */
+ u16 count; /* number of descriptors in the ring */
atomic_t next_to_use;
u16 next_to_clean;
struct atl1_buffer *buffer_info;
};
+/* receive return descriptor (rrd) ring */
struct atl1_rrd_ring {
- void *desc;
- dma_addr_t dma;
- unsigned int size;
- u16 count;
+ void *desc; /* descriptor ring virtual address */
+ dma_addr_t dma; /* descriptor ring physical address */
+ unsigned int size; /* descriptor ring length in bytes */
+ u16 count; /* number of descriptors in the ring */
u16 next_to_use;
atomic_t next_to_clean;
};
-struct atl1_ring_header {
- void *desc; /* pointer to the descriptor ring memory */
- dma_addr_t dma; /* physical adress of the descriptor ring */
- unsigned int size; /* length of descriptor ring in bytes */
-};
-
+/* coalescing message block (cmb) */
struct atl1_cmb {
struct coals_msg_block *cmb;
dma_addr_t dma;
};
+/* statistics message block (smb) */
struct atl1_smb {
struct stats_msg_block *smb;
dma_addr_t dma;
@@ -141,24 +156,26 @@ struct atl1_sft_stats {
u64 tx_aborted_errors;
u64 tx_window_errors;
u64 tx_carrier_errors;
-
- u64 tx_pause; /* num Pause packet transmitted. */
- u64 excecol; /* num tx packets aborted due to excessive collisions. */
- u64 deffer; /* num deferred tx packets */
- u64 scc; /* num packets subsequently transmitted successfully w/ single prior collision. */
- u64 mcc; /* num packets subsequently transmitted successfully w/ multiple prior collisions. */
+ u64 tx_pause; /* num pause packets transmitted. */
+ u64 excecol; /* num tx packets w/ excessive collisions. */
+ u64 deffer; /* num tx packets deferred */
+ u64 scc; /* num packets subsequently transmitted
+ * successfully w/ single prior collision. */
+ u64 mcc; /* num packets subsequently transmitted
+ * successfully w/ multiple prior collisions. */
u64 latecol; /* num tx packets w/ late collisions. */
- u64 tx_underun; /* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
- u64 tx_trunc; /* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */
+ u64 tx_underun; /* num tx packets aborted due to transmit
+ * FIFO underrun, or TRD FIFO underrun */
+ u64 tx_trunc; /* num tx packets truncated due to size
+ * exceeding MTU, regardless whether truncated
+ * by the chip or not. (The name doesn't really
+ * reflect the meaning in this case.) */
u64 rx_pause; /* num Pause packets received. */
u64 rx_rrd_ov;
u64 rx_trunc;
};
-/* board specific private data structure */
-#define ATL1_REGS_LEN 8
-
-/* Structure containing variables used by the shared code */
+/* hardware structure */
struct atl1_hw {
u8 __iomem *hw_addr;
struct atl1_adapter *back;
@@ -167,24 +184,35 @@ struct atl1_hw {
enum atl1_dma_req_block dmar_block;
enum atl1_dma_req_block dmaw_block;
u8 preamble_len;
- u8 max_retry; /* Retransmission maximum, after which the packet will be discarded */
- u8 jam_ipg; /* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */
- u8 ipgt; /* Desired back to back inter-packet gap. The default is 96-bit time */
- u8 min_ifg; /* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */
+ u8 max_retry; /* Retransmission maximum, after which the
+ * packet will be discarded */
+ u8 jam_ipg; /* IPG to start JAM for collision based flow
+ * control in half-duplex mode. In units of
+ * 8-bit time */
+ u8 ipgt; /* Desired back to back inter-packet gap.
+ * The default is 96-bit time */
+ u8 min_ifg; /* Minimum number of IFG to enforce in between
+ * receive frames. Frame gap below such IFP
+ * is dropped */
u8 ipgr1; /* 64bit Carrier-Sense window */
u8 ipgr2; /* 96-bit IPG window */
- u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */
- u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */
+ u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned
+ * burst. Each TPD is 16 bytes long */
+ u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned
+ * burst. Each RFD is 12 bytes long */
u8 rfd_fetch_gap;
- u8 rrd_burst; /* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */
+ u8 rrd_burst; /* Threshold number of RRDs that can be retired
+ * in a burst. Each RRD is 16 bytes long */
u8 tpd_fetch_th;
u8 tpd_fetch_gap;
u16 tx_jumbo_task_th;
- u16 txf_burst; /* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is
- 8 bytes long */
- u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */
+ u16 txf_burst; /* Number of data bytes to read in a cache-
+ * aligned burst. Each SRAM entry is 8 bytes */
+ u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN
+ * packets should add 4 bytes */
u16 rx_jumbo_lkah;
- u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after every 512ns passes. */
+ u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after
+ * every 512ns passes. */
u16 lcol; /* Collision Window */
u16 cmb_tpd;
@@ -194,48 +222,35 @@ struct atl1_hw {
u32 smb_timer;
u16 media_type;
u16 autoneg_advertised;
- u16 pci_cmd_word;
u16 mii_autoneg_adv_reg;
u16 mii_1000t_ctrl_reg;
- u32 mem_rang;
- u32 txcw;
u32 max_frame_size;
u32 min_frame_size;
- u32 mc_filter_type;
- u32 num_mc_addrs;
- u32 collision_delta;
- u32 tx_packet_delta;
- u16 phy_spd_default;
u16 dev_rev;
/* spi flash */
u8 flash_vendor;
- u8 dma_fairness;
u8 mac_addr[ETH_ALEN];
u8 perm_mac_addr[ETH_ALEN];
- /* bool phy_preamble_sup; */
bool phy_configured;
};
struct atl1_adapter {
- /* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
struct net_device_stats net_stats;
struct atl1_sft_stats soft_stats;
-
struct vlan_group *vlgrp;
u32 rx_buffer_len;
u32 wol;
u16 link_speed;
u16 link_duplex;
spinlock_t lock;
- atomic_t irq_sem;
struct work_struct tx_timeout_task;
struct work_struct link_chg_task;
struct work_struct pcie_dma_to_rst_task;
@@ -243,9 +258,7 @@ struct atl1_adapter {
struct timer_list phy_config_timer;
bool phy_timer_pending;
- bool mac_disabled;
-
- /* All descriptor rings' memory */
+ /* all descriptor rings' memory */
struct atl1_ring_header ring_header;
/* TX */
@@ -258,25 +271,16 @@ struct atl1_adapter {
u64 hw_csum_err;
u64 hw_csum_good;
- u32 gorcl;
- u64 gorcl_old;
-
- /* Interrupt Moderator timer ( 2us resolution) */
- u16 imt;
- /* Interrupt Clear timer (2us resolution) */
- u16 ict;
-
- /* MII interface info */
- struct mii_if_info mii;
+ u16 imt; /* interrupt moderator timer (2us resolution */
+ u16 ict; /* interrupt clear timer (2us resolution */
+ struct mii_if_info mii; /* MII interface info */
/* structs defined in atl1_hw.h */
- u32 bd_number; /* board number */
+ u32 bd_number; /* board number */
bool pci_using_64;
struct atl1_hw hw;
struct atl1_smb smb;
struct atl1_cmb cmb;
-
- u32 pci_state[16];
};
#endif /* _ATL1_H_ */
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 501919eb7f5e..fd1e156f1747 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -38,7 +38,7 @@
* TODO:
* Fix TSO; tx performance is horrible with TSO enabled.
* Wake on LAN.
- * Add more ethtool functions, including set ring parameters.
+ * Add more ethtool functions.
* Fix abstruse irq enable/disable condition described here:
* http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
*
@@ -75,6 +75,7 @@
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/mii.h>
+#include <linux/interrupt.h>
#include <net/checksum.h>
#include <asm/atomic.h>
@@ -158,13 +159,70 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
hw->cmb_tx_timer = 1; /* about 2us */
hw->smb_timer = 100000; /* about 200ms */
- atomic_set(&adapter->irq_sem, 0);
spin_lock_init(&adapter->lock);
spin_lock_init(&adapter->mb_lock);
return 0;
}
+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+ return result;
+}
+
+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+ int val)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ atl1_write_phy_reg(&adapter->hw, reg_num, val);
+}
+
+/*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ int retval;
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+
+ return retval;
+}
+
+/*
+ * atl1_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ return atl1_mii_ioctl(netdev, ifr, cmd);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
/*
* atl1_setup_mem_resources - allocate Tx / RX descriptor resources
* @adapter: board private structure
@@ -188,19 +246,22 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
goto err_nomem;
}
rfd_ring->buffer_info =
- (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+ (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
- /* real ring DMA buffer */
- ring_header->size = size = sizeof(struct tx_packet_desc) *
- tpd_ring->count
- + sizeof(struct rx_free_desc) * rfd_ring->count
- + sizeof(struct rx_return_desc) * rrd_ring->count
- + sizeof(struct coals_msg_block)
- + sizeof(struct stats_msg_block)
- + 40; /* "40: for 8 bytes align" huh? -- CHS */
+ /* real ring DMA buffer
+ * each ring/block may need up to 8 bytes for alignment, hence the
+ * additional 40 bytes tacked onto the end.
+ */
+ ring_header->size = size =
+ sizeof(struct tx_packet_desc) * tpd_ring->count
+ + sizeof(struct rx_free_desc) * rfd_ring->count
+ + sizeof(struct rx_return_desc) * rrd_ring->count
+ + sizeof(struct coals_msg_block)
+ + sizeof(struct stats_msg_block)
+ + 40;
ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
- &ring_header->dma);
+ &ring_header->dma);
if (unlikely(!ring_header->desc)) {
dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
goto err_nomem;
@@ -214,8 +275,6 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
tpd_ring->dma += offset;
tpd_ring->desc = (u8 *) ring_header->desc + offset;
tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
- atomic_set(&tpd_ring->next_to_use, 0);
- atomic_set(&tpd_ring->next_to_clean, 0);
/* init RFD ring */
rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
@@ -223,9 +282,7 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
rfd_ring->dma += offset;
rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
- rfd_ring->next_to_clean = 0;
- /* rfd_ring->next_to_use = rfd_ring->count - 1; */
- atomic_set(&rfd_ring->next_to_use, 0);
+
/* init RRD ring */
rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
@@ -233,23 +290,22 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
rrd_ring->dma += offset;
rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
- rrd_ring->next_to_use = 0;
- atomic_set(&rrd_ring->next_to_clean, 0);
+
/* init CMB */
adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
adapter->cmb.dma += offset;
- adapter->cmb.cmb =
- (struct coals_msg_block *) ((u8 *) rrd_ring->desc +
- (rrd_ring->size + offset));
+ adapter->cmb.cmb = (struct coals_msg_block *)
+ ((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
/* init SMB */
adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
adapter->smb.dma += offset;
adapter->smb.smb = (struct stats_msg_block *)
- ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset));
+ ((u8 *) adapter->cmb.cmb +
+ (sizeof(struct coals_msg_block) + offset));
return ATL1_SUCCESS;
@@ -258,559 +314,133 @@ err_nomem:
return -ENOMEM;
}
-/*
- * atl1_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- */
-static void atl1_irq_enable(struct atl1_adapter *adapter)
-{
- if (likely(!atomic_dec_and_test(&adapter->irq_sem)))
- iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
-}
-
-static void atl1_clear_phy_int(struct atl1_adapter *adapter)
-{
- u16 phy_data;
- unsigned long flags;
-
- spin_lock_irqsave(&adapter->lock, flags);
- atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
- spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-static void atl1_inc_smb(struct atl1_adapter *adapter)
-{
- struct stats_msg_block *smb = adapter->smb.smb;
-
- /* Fill out the OS statistics structure */
- adapter->soft_stats.rx_packets += smb->rx_ok;
- adapter->soft_stats.tx_packets += smb->tx_ok;
- adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
- adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
- adapter->soft_stats.multicast += smb->rx_mcast;
- adapter->soft_stats.collisions += (smb->tx_1_col +
- smb->tx_2_col * 2 +
- smb->tx_late_col +
- smb->tx_abort_col *
- adapter->hw.max_retry);
-
- /* Rx Errors */
- adapter->soft_stats.rx_errors += (smb->rx_frag +
- smb->rx_fcs_err +
- smb->rx_len_err +
- smb->rx_sz_ov +
- smb->rx_rxf_ov +
- smb->rx_rrd_ov + smb->rx_align_err);
- adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
- adapter->soft_stats.rx_length_errors += smb->rx_len_err;
- adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
- adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
- adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
- smb->rx_rxf_ov);
-
- adapter->soft_stats.rx_pause += smb->rx_pause;
- adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
- adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
-
- /* Tx Errors */
- adapter->soft_stats.tx_errors += (smb->tx_late_col +
- smb->tx_abort_col +
- smb->tx_underrun + smb->tx_trunc);
- adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
- adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
- adapter->soft_stats.tx_window_errors += smb->tx_late_col;
-
- adapter->soft_stats.excecol += smb->tx_abort_col;
- adapter->soft_stats.deffer += smb->tx_defer;
- adapter->soft_stats.scc += smb->tx_1_col;
- adapter->soft_stats.mcc += smb->tx_2_col;
- adapter->soft_stats.latecol += smb->tx_late_col;
- adapter->soft_stats.tx_underun += smb->tx_underrun;
- adapter->soft_stats.tx_trunc += smb->tx_trunc;
- adapter->soft_stats.tx_pause += smb->tx_pause;
-
- adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
- adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
- adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
- adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
- adapter->net_stats.multicast = adapter->soft_stats.multicast;
- adapter->net_stats.collisions = adapter->soft_stats.collisions;
- adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
- adapter->net_stats.rx_over_errors =
- adapter->soft_stats.rx_missed_errors;
- adapter->net_stats.rx_length_errors =
- adapter->soft_stats.rx_length_errors;
- adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
- adapter->net_stats.rx_frame_errors =
- adapter->soft_stats.rx_frame_errors;
- adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
- adapter->net_stats.rx_missed_errors =
- adapter->soft_stats.rx_missed_errors;
- adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
- adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
- adapter->net_stats.tx_aborted_errors =
- adapter->soft_stats.tx_aborted_errors;
- adapter->net_stats.tx_window_errors =
- adapter->soft_stats.tx_window_errors;
- adapter->net_stats.tx_carrier_errors =
- adapter->soft_stats.tx_carrier_errors;
-}
-
-static void atl1_rx_checksum(struct atl1_adapter *adapter,
- struct rx_return_desc *rrd,
- struct sk_buff *skb)
+void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
{
- skb->ip_summed = CHECKSUM_NONE;
-
- if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
- if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
- ERR_FLAG_CODE | ERR_FLAG_OV)) {
- adapter->hw_csum_err++;
- dev_dbg(&adapter->pdev->dev, "rx checksum error\n");
- return;
- }
- }
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
- /* not IPv4 */
- if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
- /* checksum is invalid, but it's not an IPv4 pkt, so ok */
- return;
+ atomic_set(&tpd_ring->next_to_use, 0);
+ atomic_set(&tpd_ring->next_to_clean, 0);
- /* IPv4 packet */
- if (likely(!(rrd->err_flg &
- (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- adapter->hw_csum_good++;
- return;
- }
+ rfd_ring->next_to_clean = 0;
+ atomic_set(&rfd_ring->next_to_use, 0);
- /* IPv4, but hardware thinks its checksum is wrong */
- dev_dbg(&adapter->pdev->dev,
- "hw csum wrong, pkt_flag:%x, err_flag:%x\n",
- rrd->pkt_flg, rrd->err_flg);
- skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
- adapter->hw_csum_err++;
- return;
+ rrd_ring->next_to_use = 0;
+ atomic_set(&rrd_ring->next_to_clean, 0);
}
/*
- * atl1_alloc_rx_buffers - Replace used receive buffers
- * @adapter: address of board private structure
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
*/
-static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
-{
- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
- struct pci_dev *pdev = adapter->pdev;
- struct page *page;
- unsigned long offset;
- struct atl1_buffer *buffer_info, *next_info;
- struct sk_buff *skb;
- u16 num_alloc = 0;
- u16 rfd_next_to_use, next_next;
- struct rx_free_desc *rfd_desc;
-
- next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
- if (++next_next == rfd_ring->count)
- next_next = 0;
- buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
- next_info = &rfd_ring->buffer_info[next_next];
-
- while (!buffer_info->alloced && !next_info->alloced) {
- if (buffer_info->skb) {
- buffer_info->alloced = 1;
- goto next;
- }
-
- rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
-
- skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
- if (unlikely(!skb)) { /* Better luck next round */
- adapter->net_stats.rx_dropped++;
- break;
- }
-
- /*
- * Make buffer alignment 2 beyond a 16 byte boundary
- * this will result in a 16 byte aligned IP header after
- * the 14 byte MAC header is removed
- */
- skb_reserve(skb, NET_IP_ALIGN);
-
- buffer_info->alloced = 1;
- buffer_info->skb = skb;
- buffer_info->length = (u16) adapter->rx_buffer_len;
- page = virt_to_page(skb->data);
- offset = (unsigned long)skb->data & ~PAGE_MASK;
- buffer_info->dma = pci_map_page(pdev, page, offset,
- adapter->rx_buffer_len,
- PCI_DMA_FROMDEVICE);
- rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
- rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
- rfd_desc->coalese = 0;
-
-next:
- rfd_next_to_use = next_next;
- if (unlikely(++next_next == rfd_ring->count))
- next_next = 0;
-
- buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
- next_info = &rfd_ring->buffer_info[next_next];
- num_alloc++;
- }
-
- if (num_alloc) {
- /*
- * Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64).
- */
- wmb();
- atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
- }
- return num_alloc;
-}
-
-static void atl1_intr_rx(struct atl1_adapter *adapter)
+static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
{
- int i, count;
- u16 length;
- u16 rrd_next_to_clean;
- u32 value;
struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1_buffer *buffer_info;
- struct rx_return_desc *rrd;
- struct sk_buff *skb;
-
- count = 0;
-
- rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
-
- while (1) {
- rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
- i = 1;
- if (likely(rrd->xsz.valid)) { /* packet valid */
-chk_rrd:
- /* check rrd status */
- if (likely(rrd->num_buf == 1))
- goto rrd_ok;
-
- /* rrd seems to be bad */
- if (unlikely(i-- > 0)) {
- /* rrd may not be DMAed completely */
- dev_dbg(&adapter->pdev->dev,
- "incomplete RRD DMA transfer\n");
- udelay(1);
- goto chk_rrd;
- }
- /* bad rrd */
- dev_dbg(&adapter->pdev->dev, "bad RRD\n");
- /* see if update RFD index */
- if (rrd->num_buf > 1) {
- u16 num_buf;
- num_buf =
- (rrd->xsz.xsum_sz.pkt_size +
- adapter->rx_buffer_len -
- 1) / adapter->rx_buffer_len;
- if (rrd->num_buf == num_buf) {
- /* clean alloc flag for bad rrd */
- while (rfd_ring->next_to_clean !=
- (rrd->buf_indx + num_buf)) {
- rfd_ring->buffer_info[rfd_ring->
- next_to_clean].alloced = 0;
- if (++rfd_ring->next_to_clean ==
- rfd_ring->count) {
- rfd_ring->
- next_to_clean = 0;
- }
- }
- }
- }
-
- /* update rrd */
- rrd->xsz.valid = 0;
- if (++rrd_next_to_clean == rrd_ring->count)
- rrd_next_to_clean = 0;
- count++;
- continue;
- } else { /* current rrd still not be updated */
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
- break;
- }
-rrd_ok:
- /* clean alloc flag for bad rrd */
- while (rfd_ring->next_to_clean != rrd->buf_indx) {
- rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced =
- 0;
- if (++rfd_ring->next_to_clean == rfd_ring->count)
- rfd_ring->next_to_clean = 0;
+ /* Free all the Rx ring sk_buffs */
+ for (i = 0; i < rfd_ring->count; i++) {
+ buffer_info = &rfd_ring->buffer_info[i];
+ if (buffer_info->dma) {
+ pci_unmap_page(pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
}
-
- buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
- if (++rfd_ring->next_to_clean == rfd_ring->count)
- rfd_ring->next_to_clean = 0;
-
- /* update rrd next to clean */
- if (++rrd_next_to_clean == rrd_ring->count)
- rrd_next_to_clean = 0;
- count++;
-
- if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
- if (!(rrd->err_flg &
- (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
- | ERR_FLAG_LEN))) {
- /* packet error, don't need upstream */
- buffer_info->alloced = 0;
- rrd->xsz.valid = 0;
- continue;
- }
+ if (buffer_info->skb) {
+ dev_kfree_skb(buffer_info->skb);
+ buffer_info->skb = NULL;
}
-
- /* Good Receive */
- pci_unmap_page(adapter->pdev, buffer_info->dma,
- buffer_info->length, PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
- length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
-
- skb_put(skb, length - ETHERNET_FCS_SIZE);
-
- /* Receive Checksum Offload */
- atl1_rx_checksum(adapter, rrd, skb);
- skb->protocol = eth_type_trans(skb, adapter->netdev);
-
- if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
- u16 vlan_tag = (rrd->vlan_tag >> 4) |
- ((rrd->vlan_tag & 7) << 13) |
- ((rrd->vlan_tag & 8) << 9);
- vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
- } else
- netif_rx(skb);
-
- /* let protocol layer free skb */
- buffer_info->skb = NULL;
- buffer_info->alloced = 0;
- rrd->xsz.valid = 0;
-
- adapter->netdev->last_rx = jiffies;
}
- atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
-
- atl1_alloc_rx_buffers(adapter);
+ size = sizeof(struct atl1_buffer) * rfd_ring->count;
+ memset(rfd_ring->buffer_info, 0, size);
- /* update mailbox ? */
- if (count) {
- u32 tpd_next_to_use;
- u32 rfd_next_to_use;
- u32 rrd_next_to_clean;
+ /* Zero out the descriptor ring */
+ memset(rfd_ring->desc, 0, rfd_ring->size);
- spin_lock(&adapter->mb_lock);
+ rfd_ring->next_to_clean = 0;
+ atomic_set(&rfd_ring->next_to_use, 0);
- tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
- rfd_next_to_use =
- atomic_read(&adapter->rfd_ring.next_to_use);
- rrd_next_to_clean =
- atomic_read(&adapter->rrd_ring.next_to_clean);
- value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
- MB_RFD_PROD_INDX_SHIFT) |
- ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
- MB_RRD_CONS_INDX_SHIFT) |
- ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
- MB_TPD_PROD_INDX_SHIFT);
- iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
- spin_unlock(&adapter->mb_lock);
- }
+ rrd_ring->next_to_use = 0;
+ atomic_set(&rrd_ring->next_to_clean, 0);
}
-static void atl1_intr_tx(struct atl1_adapter *adapter)
+/*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
{
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct atl1_buffer *buffer_info;
- u16 sw_tpd_next_to_clean;
- u16 cmb_tpd_next_to_clean;
-
- sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
- cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
-
- while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
- struct tx_packet_desc *tpd;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
- tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
- buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+ /* Free all the Tx ring sk_buffs */
+ for (i = 0; i < tpd_ring->count; i++) {
+ buffer_info = &tpd_ring->buffer_info[i];
if (buffer_info->dma) {
- pci_unmap_page(adapter->pdev, buffer_info->dma,
- buffer_info->length, PCI_DMA_TODEVICE);
+ pci_unmap_page(pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_TODEVICE);
buffer_info->dma = 0;
}
+ }
+ for (i = 0; i < tpd_ring->count; i++) {
+ buffer_info = &tpd_ring->buffer_info[i];
if (buffer_info->skb) {
- dev_kfree_skb_irq(buffer_info->skb);
+ dev_kfree_skb_any(buffer_info->skb);
buffer_info->skb = NULL;
}
- tpd->buffer_addr = 0;
- tpd->desc.data = 0;
-
- if (++sw_tpd_next_to_clean == tpd_ring->count)
- sw_tpd_next_to_clean = 0;
}
- atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
-
- if (netif_queue_stopped(adapter->netdev)
- && netif_carrier_ok(adapter->netdev))
- netif_wake_queue(adapter->netdev);
-}
-
-static void atl1_check_for_link(struct atl1_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- u16 phy_data = 0;
-
- spin_lock(&adapter->lock);
- adapter->phy_timer_pending = false;
- atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
- atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
- spin_unlock(&adapter->lock);
-
- /* notify upper layer link down ASAP */
- if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */
- if (netif_carrier_ok(netdev)) { /* old link state: Up */
- dev_info(&adapter->pdev->dev, "%s link is down\n",
- netdev->name);
- adapter->link_speed = SPEED_0;
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- }
- }
- schedule_work(&adapter->link_chg_task);
-}
-
-/*
- * atl1_intr - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
- */
-static irqreturn_t atl1_intr(int irq, void *data)
-{
- /*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/
- struct atl1_adapter *adapter = netdev_priv(data);
- u32 status;
- u8 update_rx;
- int max_ints = 10;
-
- status = adapter->cmb.cmb->int_stats;
- if (!status)
- return IRQ_NONE;
-
- update_rx = 0;
-
- do {
- /* clear CMB interrupt status at once */
- adapter->cmb.cmb->int_stats = 0;
-
- if (status & ISR_GPHY) /* clear phy status */
- atl1_clear_phy_int(adapter);
-
- /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
- iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
-
- /* check if SMB intr */
- if (status & ISR_SMB)
- atl1_inc_smb(adapter);
-
- /* check if PCIE PHY Link down */
- if (status & ISR_PHY_LINKDOWN) {
- dev_dbg(&adapter->pdev->dev, "pcie phy link down %x\n",
- status);
- if (netif_running(adapter->netdev)) { /* reset MAC */
- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->pcie_dma_to_rst_task);
- return IRQ_HANDLED;
- }
- }
-
- /* check if DMA read/write error ? */
- if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
- dev_dbg(&adapter->pdev->dev,
- "pcie DMA r/w error (status = 0x%x)\n",
- status);
- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->pcie_dma_to_rst_task);
- return IRQ_HANDLED;
- }
-
- /* link event */
- if (status & ISR_GPHY) {
- adapter->soft_stats.tx_carrier_errors++;
- atl1_check_for_link(adapter);
- }
-
- /* transmit event */
- if (status & ISR_CMB_TX)
- atl1_intr_tx(adapter);
-
- /* rx exception */
- if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
- ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
- ISR_HOST_RRD_OV | ISR_CMB_RX))) {
- if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
- ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
- ISR_HOST_RRD_OV))
- dev_dbg(&adapter->pdev->dev,
- "rx exception, ISR = 0x%x\n", status);
- atl1_intr_rx(adapter);
- }
- if (--max_ints < 0)
- break;
+ size = sizeof(struct atl1_buffer) * tpd_ring->count;
+ memset(tpd_ring->buffer_info, 0, size);
- } while ((status = adapter->cmb.cmb->int_stats));
+ /* Zero out the descriptor ring */
+ memset(tpd_ring->desc, 0, tpd_ring->size);
- /* re-enable Interrupt */
- iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
- return IRQ_HANDLED;
+ atomic_set(&tpd_ring->next_to_use, 0);
+ atomic_set(&tpd_ring->next_to_clean, 0);
}
/*
- * atl1_set_multi - Multicast and Promiscuous mode set
- * @netdev: network interface device structure
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
*
- * The set_multi entry point is called whenever the multicast address
- * list or the network interface flags are updated. This routine is
- * responsible for configuring the hardware for proper multicast,
- * promiscuous mode, and all-multi behavior.
+ * Free all transmit software resources
*/
-static void atl1_set_multi(struct net_device *netdev)
+void atl1_free_ring_resources(struct atl1_adapter *adapter)
{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- struct atl1_hw *hw = &adapter->hw;
- struct dev_mc_list *mc_ptr;
- u32 rctl;
- u32 hash_value;
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_ring_header *ring_header = &adapter->ring_header;
- /* Check for Promiscuous and All Multicast modes */
- rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
- if (netdev->flags & IFF_PROMISC)
- rctl |= MAC_CTRL_PROMIS_EN;
- else if (netdev->flags & IFF_ALLMULTI) {
- rctl |= MAC_CTRL_MC_ALL_EN;
- rctl &= ~MAC_CTRL_PROMIS_EN;
- } else
- rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+ atl1_clean_tx_ring(adapter);
+ atl1_clean_rx_ring(adapter);
- iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+ kfree(tpd_ring->buffer_info);
+ pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+ ring_header->dma);
- /* clear the old settings from the multicast hash table */
- iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
- iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+ tpd_ring->buffer_info = NULL;
+ tpd_ring->desc = NULL;
+ tpd_ring->dma = 0;
- /* compute mc addresses' hash value ,and put it into hash table */
- for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
- hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
- atl1_hash_set(hw, hash_value);
- }
+ rfd_ring->buffer_info = NULL;
+ rfd_ring->desc = NULL;
+ rfd_ring->dma = 0;
+
+ rrd_ring->desc = NULL;
+ rrd_ring->dma = 0;
}
static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
@@ -851,6 +481,31 @@ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
}
+/*
+ * atl1_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_set_mac(struct net_device *netdev, void *p)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+ atl1_set_mac_addr(&adapter->hw);
+ return 0;
+}
+
static u32 atl1_check_link(struct atl1_adapter *adapter)
{
struct atl1_hw *hw = &adapter->hw;
@@ -958,6 +613,103 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
return ATL1_SUCCESS;
}
+static void atl1_check_for_link(struct atl1_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u16 phy_data = 0;
+
+ spin_lock(&adapter->lock);
+ adapter->phy_timer_pending = false;
+ atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ spin_unlock(&adapter->lock);
+
+ /* notify upper layer link down ASAP */
+ if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ dev_info(&adapter->pdev->dev, "%s link is down\n",
+ netdev->name);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ }
+ schedule_work(&adapter->link_chg_task);
+}
+
+/*
+ * atl1_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1_set_multi(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ struct dev_mc_list *mc_ptr;
+ u32 rctl;
+ u32 hash_value;
+
+ /* Check for Promiscuous and All Multicast modes */
+ rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+ if (netdev->flags & IFF_PROMISC)
+ rctl |= MAC_CTRL_PROMIS_EN;
+ else if (netdev->flags & IFF_ALLMULTI) {
+ rctl |= MAC_CTRL_MC_ALL_EN;
+ rctl &= ~MAC_CTRL_PROMIS_EN;
+ } else
+ rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+ iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+
+ /* clear the old settings from the multicast hash table */
+ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+ /* compute mc addresses' hash value ,and put it into hash table */
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+ hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+ atl1_hash_set(hw, hash_value);
+ }
+}
+
+/*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int old_mtu = netdev->mtu;
+ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+
+ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+ return -EINVAL;
+ }
+
+ adapter->hw.max_frame_size = max_frame;
+ adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+ adapter->rx_buffer_len = (max_frame + 7) & ~7;
+ adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+ netdev->mtu = new_mtu;
+ if ((old_mtu != new_mtu) && netif_running(netdev)) {
+ atl1_down(adapter);
+ atl1_up(adapter);
+ }
+
+ return 0;
+}
+
static void set_flow_ctrl_old(struct atl1_adapter *adapter)
{
u32 hi, lo, value;
@@ -970,7 +722,7 @@ static void set_flow_ctrl_old(struct atl1_adapter *adapter)
lo = value * 7 / 8;
value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
- ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
/* RRD Flow Control */
@@ -980,7 +732,7 @@ static void set_flow_ctrl_old(struct atl1_adapter *adapter)
if (lo < 2)
lo = 2;
value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
- ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
}
@@ -997,7 +749,7 @@ static void set_flow_ctrl_new(struct atl1_hw *hw)
if (hi < lo)
hi = lo + 16;
value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
- ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
/* RRD Flow Control */
@@ -1009,7 +761,7 @@ static void set_flow_ctrl_new(struct atl1_hw *hw)
if (hi < lo)
hi = lo + 3;
value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
- ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
}
@@ -1058,7 +810,8 @@ static u32 atl1_configure(struct atl1_adapter *adapter)
value <<= 16;
value += adapter->rfd_ring.count;
iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
- iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE);
+ iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+ REG_DESC_TPD_RING_SIZE);
/* Load Ptr */
iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
@@ -1066,31 +819,31 @@ static u32 atl1_configure(struct atl1_adapter *adapter)
/* config Mailbox */
value = ((atomic_read(&adapter->tpd_ring.next_to_use)
& MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
- ((atomic_read(&adapter->rrd_ring.next_to_clean)
- & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
- ((atomic_read(&adapter->rfd_ring.next_to_use)
- & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+ ((atomic_read(&adapter->rrd_ring.next_to_clean)
+ & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+ ((atomic_read(&adapter->rfd_ring.next_to_use)
+ & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
iowrite32(value, hw->hw_addr + REG_MAILBOX);
/* config IPG/IFG */
value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
<< MAC_IPG_IFG_IPGT_SHIFT) |
- (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
- << MAC_IPG_IFG_MIFG_SHIFT) |
- (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
- << MAC_IPG_IFG_IPGR1_SHIFT) |
- (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
- << MAC_IPG_IFG_IPGR2_SHIFT);
+ (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+ << MAC_IPG_IFG_MIFG_SHIFT) |
+ (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+ << MAC_IPG_IFG_IPGR1_SHIFT) |
+ (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+ << MAC_IPG_IFG_IPGR2_SHIFT);
iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
/* config Half-Duplex Control */
value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
- (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
- << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
- MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
- (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
- (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
- << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+ (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+ << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+ MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+ (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+ (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+ << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
/* set Interrupt Moderator Timer */
@@ -1106,10 +859,10 @@ static u32 atl1_configure(struct atl1_adapter *adapter)
/* jumbo size & rrd retirement timer */
value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
<< RXQ_JMBOSZ_TH_SHIFT) |
- (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
- << RXQ_JMBO_LKAH_SHIFT) |
- (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
- << RXQ_RRD_TIMER_SHIFT);
+ (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+ << RXQ_JMBO_LKAH_SHIFT) |
+ (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+ << RXQ_RRD_TIMER_SHIFT);
iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
/* Flow Control */
@@ -1128,35 +881,36 @@ static u32 atl1_configure(struct atl1_adapter *adapter)
/* config TXQ */
value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
<< TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
- (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
- << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
- (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
- << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN;
+ (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+ << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+ (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+ << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+ TXQ_CTRL_EN;
iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
- << TX_JUMBO_TASK_TH_SHIFT) |
- (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
- << TX_TPD_MIN_IPG_SHIFT);
+ << TX_JUMBO_TASK_TH_SHIFT) |
+ (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+ << TX_TPD_MIN_IPG_SHIFT);
iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
/* config RXQ */
value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
- << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
- (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
- << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
- (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
- << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) |
- RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+ << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+ (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+ << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+ (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+ << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+ RXQ_CTRL_EN;
iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
/* config DMA Engine */
value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
- << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
- ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
- << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
- DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN;
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+ ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+ DMA_CTRL_DMAW_EN;
value |= (u32) hw->dma_ord;
if (atl1_rcb_128 == hw->rcb_value)
value |= DMA_CTRL_RCB_VALUE;
@@ -1186,56 +940,495 @@ static u32 atl1_configure(struct atl1_adapter *adapter)
}
/*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+static void atl1_pcie_patch(struct atl1_adapter *adapter)
+{
+ u32 value;
+
+ /* much vendor magic here */
+ value = 0x6500;
+ iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+ /* pcie flow control mode change */
+ value = ioread32(adapter->hw.hw_addr + 0x1008);
+ value |= 0x8000;
+ iowrite32(value, adapter->hw.hw_addr + 0x1008);
+}
+
+/*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+static void atl1_via_workaround(struct atl1_adapter *adapter)
+{
+ unsigned long value;
+
+ value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+ if (value & PCI_COMMAND_INTX_DISABLE)
+ value &= ~PCI_COMMAND_INTX_DISABLE;
+ iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+}
+
+/*
+ * atl1_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static void atl1_irq_enable(struct atl1_adapter *adapter)
+{
+ iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+ ioread32(adapter->hw.hw_addr + REG_IMR);
+}
+
+/*
* atl1_irq_disable - Mask off interrupt generation on the NIC
* @adapter: board private structure
*/
static void atl1_irq_disable(struct atl1_adapter *adapter)
{
- atomic_inc(&adapter->irq_sem);
iowrite32(0, adapter->hw.hw_addr + REG_IMR);
ioread32(adapter->hw.hw_addr + REG_IMR);
synchronize_irq(adapter->pdev->irq);
}
-static void atl1_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
+static void atl1_clear_phy_int(struct atl1_adapter *adapter)
{
- struct atl1_adapter *adapter = netdev_priv(netdev);
+ u16 phy_data;
unsigned long flags;
- u32 ctrl;
spin_lock_irqsave(&adapter->lock, flags);
- /* atl1_irq_disable(adapter); */
- adapter->vlgrp = grp;
+ atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
- if (grp) {
- /* enable VLAN tag insert/strip */
- ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
- ctrl |= MAC_CTRL_RMV_VLAN;
- iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
- } else {
- /* disable VLAN tag insert/strip */
- ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
- ctrl &= ~MAC_CTRL_RMV_VLAN;
- iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+static void atl1_inc_smb(struct atl1_adapter *adapter)
+{
+ struct stats_msg_block *smb = adapter->smb.smb;
+
+ /* Fill out the OS statistics structure */
+ adapter->soft_stats.rx_packets += smb->rx_ok;
+ adapter->soft_stats.tx_packets += smb->tx_ok;
+ adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+ adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+ adapter->soft_stats.multicast += smb->rx_mcast;
+ adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+ smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
+
+ /* Rx Errors */
+ adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+ smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+ smb->rx_rrd_ov + smb->rx_align_err);
+ adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+ adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+ adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+ adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+ adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+ smb->rx_rxf_ov);
+
+ adapter->soft_stats.rx_pause += smb->rx_pause;
+ adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+ adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+
+ /* Tx Errors */
+ adapter->soft_stats.tx_errors += (smb->tx_late_col +
+ smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
+ adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+ adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+ adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+
+ adapter->soft_stats.excecol += smb->tx_abort_col;
+ adapter->soft_stats.deffer += smb->tx_defer;
+ adapter->soft_stats.scc += smb->tx_1_col;
+ adapter->soft_stats.mcc += smb->tx_2_col;
+ adapter->soft_stats.latecol += smb->tx_late_col;
+ adapter->soft_stats.tx_underun += smb->tx_underrun;
+ adapter->soft_stats.tx_trunc += smb->tx_trunc;
+ adapter->soft_stats.tx_pause += smb->tx_pause;
+
+ adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
+ adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
+ adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
+ adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
+ adapter->net_stats.multicast = adapter->soft_stats.multicast;
+ adapter->net_stats.collisions = adapter->soft_stats.collisions;
+ adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
+ adapter->net_stats.rx_over_errors =
+ adapter->soft_stats.rx_missed_errors;
+ adapter->net_stats.rx_length_errors =
+ adapter->soft_stats.rx_length_errors;
+ adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+ adapter->net_stats.rx_frame_errors =
+ adapter->soft_stats.rx_frame_errors;
+ adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+ adapter->net_stats.rx_missed_errors =
+ adapter->soft_stats.rx_missed_errors;
+ adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
+ adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+ adapter->net_stats.tx_aborted_errors =
+ adapter->soft_stats.tx_aborted_errors;
+ adapter->net_stats.tx_window_errors =
+ adapter->soft_stats.tx_window_errors;
+ adapter->net_stats.tx_carrier_errors =
+ adapter->soft_stats.tx_carrier_errors;
+}
+
+/*
+ * atl1_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ return &adapter->net_stats;
+}
+
+static void atl1_update_mailbox(struct atl1_adapter *adapter)
+{
+ unsigned long flags;
+ u32 tpd_next_to_use;
+ u32 rfd_next_to_use;
+ u32 rrd_next_to_clean;
+ u32 value;
+
+ spin_lock_irqsave(&adapter->mb_lock, flags);
+
+ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+ rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+ rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+ MB_RFD_PROD_INDX_SHIFT) |
+ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+ MB_RRD_CONS_INDX_SHIFT) |
+ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+ MB_TPD_PROD_INDX_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+ spin_unlock_irqrestore(&adapter->mb_lock, flags);
+}
+
+static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd, u16 offset)
+{
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+
+ while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+ rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+ if (++rfd_ring->next_to_clean == rfd_ring->count) {
+ rfd_ring->next_to_clean = 0;
+ }
}
+}
- /* atl1_irq_enable(adapter); */
- spin_unlock_irqrestore(&adapter->lock, flags);
+static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd)
+{
+ u16 num_buf;
+
+ num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+ adapter->rx_buffer_len;
+ if (rrd->num_buf == num_buf)
+ /* clean alloc flag for bad rrd */
+ atl1_clean_alloc_flag(adapter, rrd, num_buf);
}
-static void atl1_restore_vlan(struct atl1_adapter *adapter)
+static void atl1_rx_checksum(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd, struct sk_buff *skb)
{
- atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ struct pci_dev *pdev = adapter->pdev;
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+ if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+ ERR_FLAG_CODE | ERR_FLAG_OV)) {
+ adapter->hw_csum_err++;
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "rx checksum error\n");
+ return;
+ }
+ }
+
+ /* not IPv4 */
+ if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+ /* checksum is invalid, but it's not an IPv4 pkt, so ok */
+ return;
+
+ /* IPv4 packet */
+ if (likely(!(rrd->err_flg &
+ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ adapter->hw_csum_good++;
+ return;
+ }
+
+ /* IPv4, but hardware thinks its checksum is wrong */
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "hw csum wrong, pkt_flag:%x, err_flag:%x\n",
+ rrd->pkt_flg, rrd->err_flg);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
+ adapter->hw_csum_err++;
+ return;
+}
+
+/*
+ * atl1_alloc_rx_buffers - Replace used receive buffers
+ * @adapter: address of board private structure
+ */
+static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+{
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct pci_dev *pdev = adapter->pdev;
+ struct page *page;
+ unsigned long offset;
+ struct atl1_buffer *buffer_info, *next_info;
+ struct sk_buff *skb;
+ u16 num_alloc = 0;
+ u16 rfd_next_to_use, next_next;
+ struct rx_free_desc *rfd_desc;
+
+ next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
+ if (++next_next == rfd_ring->count)
+ next_next = 0;
+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+ next_info = &rfd_ring->buffer_info[next_next];
+
+ while (!buffer_info->alloced && !next_info->alloced) {
+ if (buffer_info->skb) {
+ buffer_info->alloced = 1;
+ goto next;
+ }
+
+ rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+ skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+ if (unlikely(!skb)) { /* Better luck next round */
+ adapter->net_stats.rx_dropped++;
+ break;
+ }
+
+ /*
+ * Make buffer alignment 2 beyond a 16 byte boundary
+ * this will result in a 16 byte aligned IP header after
+ * the 14 byte MAC header is removed
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ buffer_info->alloced = 1;
+ buffer_info->skb = skb;
+ buffer_info->length = (u16) adapter->rx_buffer_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(pdev, page, offset,
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
+ rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+ rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+ rfd_desc->coalese = 0;
+
+next:
+ rfd_next_to_use = next_next;
+ if (unlikely(++next_next == rfd_ring->count))
+ next_next = 0;
+
+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+ next_info = &rfd_ring->buffer_info[next_next];
+ num_alloc++;
+ }
+
+ if (num_alloc) {
+ /*
+ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+ atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+ }
+ return num_alloc;
+}
+
+static void atl1_intr_rx(struct atl1_adapter *adapter)
+{
+ int i, count;
+ u16 length;
+ u16 rrd_next_to_clean;
+ u32 value;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_buffer *buffer_info;
+ struct rx_return_desc *rrd;
+ struct sk_buff *skb;
+
+ count = 0;
+
+ rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+
+ while (1) {
+ rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+ i = 1;
+ if (likely(rrd->xsz.valid)) { /* packet valid */
+chk_rrd:
+ /* check rrd status */
+ if (likely(rrd->num_buf == 1))
+ goto rrd_ok;
+
+ /* rrd seems to be bad */
+ if (unlikely(i-- > 0)) {
+ /* rrd may not be DMAed completely */
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "incomplete RRD DMA transfer\n");
+ udelay(1);
+ goto chk_rrd;
+ }
+ /* bad rrd */
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "bad RRD\n");
+ /* see if update RFD index */
+ if (rrd->num_buf > 1)
+ atl1_update_rfd_index(adapter, rrd);
+
+ /* update rrd */
+ rrd->xsz.valid = 0;
+ if (++rrd_next_to_clean == rrd_ring->count)
+ rrd_next_to_clean = 0;
+ count++;
+ continue;
+ } else { /* current rrd still not be updated */
+
+ break;
+ }
+rrd_ok:
+ /* clean alloc flag for bad rrd */
+ atl1_clean_alloc_flag(adapter, rrd, 0);
+
+ buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+ if (++rfd_ring->next_to_clean == rfd_ring->count)
+ rfd_ring->next_to_clean = 0;
+
+ /* update rrd next to clean */
+ if (++rrd_next_to_clean == rrd_ring->count)
+ rrd_next_to_clean = 0;
+ count++;
+
+ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+ if (!(rrd->err_flg &
+ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+ | ERR_FLAG_LEN))) {
+ /* packet error, don't need upstream */
+ buffer_info->alloced = 0;
+ rrd->xsz.valid = 0;
+ continue;
+ }
+ }
+
+ /* Good Receive */
+ pci_unmap_page(adapter->pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_FROMDEVICE);
+ skb = buffer_info->skb;
+ length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+
+ skb_put(skb, length - ETHERNET_FCS_SIZE);
+
+ /* Receive Checksum Offload */
+ atl1_rx_checksum(adapter, rrd, skb);
+ skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+ if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+ u16 vlan_tag = (rrd->vlan_tag >> 4) |
+ ((rrd->vlan_tag & 7) << 13) |
+ ((rrd->vlan_tag & 8) << 9);
+ vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+ } else
+ netif_rx(skb);
+
+ /* let protocol layer free skb */
+ buffer_info->skb = NULL;
+ buffer_info->alloced = 0;
+ rrd->xsz.valid = 0;
+
+ adapter->netdev->last_rx = jiffies;
+ }
+
+ atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+
+ atl1_alloc_rx_buffers(adapter);
+
+ /* update mailbox ? */
+ if (count) {
+ u32 tpd_next_to_use;
+ u32 rfd_next_to_use;
+ u32 rrd_next_to_clean;
+
+ spin_lock(&adapter->mb_lock);
+
+ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+ rfd_next_to_use =
+ atomic_read(&adapter->rfd_ring.next_to_use);
+ rrd_next_to_clean =
+ atomic_read(&adapter->rrd_ring.next_to_clean);
+ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+ MB_RFD_PROD_INDX_SHIFT) |
+ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+ MB_RRD_CONS_INDX_SHIFT) |
+ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+ MB_TPD_PROD_INDX_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+ spin_unlock(&adapter->mb_lock);
+ }
+}
+
+static void atl1_intr_tx(struct atl1_adapter *adapter)
+{
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ u16 sw_tpd_next_to_clean;
+ u16 cmb_tpd_next_to_clean;
+
+ sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+ cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+
+ while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+ struct tx_packet_desc *tpd;
+
+ tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
+ buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+ if (buffer_info->dma) {
+ pci_unmap_page(adapter->pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+
+ if (buffer_info->skb) {
+ dev_kfree_skb_irq(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ tpd->buffer_addr = 0;
+ tpd->desc.data = 0;
+
+ if (++sw_tpd_next_to_clean == tpd_ring->count)
+ sw_tpd_next_to_clean = 0;
+ }
+ atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+
+ if (netif_queue_stopped(adapter->netdev)
+ && netif_carrier_ok(adapter->netdev))
+ netif_wake_queue(adapter->netdev);
}
static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring)
{
u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
- return ((next_to_clean >
- next_to_use) ? next_to_clean - next_to_use -
- 1 : tpd_ring->count + next_to_clean - next_to_use - 1);
+ return ((next_to_clean > next_to_use) ?
+ next_to_clean - next_to_use - 1 :
+ tpd_ring->count + next_to_clean - next_to_use - 1);
}
static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
@@ -1258,9 +1451,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
iph->tot_len = 0;
iph->check = 0;
tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ iph->daddr, 0, IPPROTO_TCP, 0);
ipofst = skb_network_offset(skb);
if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */
tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
@@ -1268,7 +1459,8 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
tso->tsopl |= (iph->ihl &
CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
tso->tsopl |= (tcp_hdrlen(skb) &
- TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT;
+ TSO_PARAM_TCPHDRLEN_MASK) <<
+ TSO_PARAM_TCPHDRLEN_SHIFT;
tso->tsopl |= (skb_shinfo(skb)->gso_size &
TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
@@ -1281,7 +1473,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
}
static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
- struct csum_param *csum)
+ struct csum_param *csum)
{
u8 css, cso;
@@ -1289,7 +1481,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
cso = skb_transport_offset(skb);
css = cso + skb->csum_offset;
if (unlikely(cso & 0x1)) {
- dev_dbg(&adapter->pdev->dev,
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
"payload offset not an even number\n");
return -1;
}
@@ -1304,8 +1496,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
return true;
}
-static void atl1_tx_map(struct atl1_adapter *adapter,
- struct sk_buff *skb, bool tcp_seg)
+static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+ bool tcp_seg)
{
/* We enter this function holding a spinlock. */
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -1342,26 +1534,25 @@ static void atl1_tx_map(struct atl1_adapter *adapter,
if (first_buf_len > proto_hdr_len) {
len12 = first_buf_len - proto_hdr_len;
- m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
for (i = 0; i < m; i++) {
buffer_info =
&tpd_ring->buffer_info[tpd_next_to_use];
buffer_info->skb = NULL;
buffer_info->length =
- (MAX_TX_BUF_LEN >=
- len12) ? MAX_TX_BUF_LEN : len12;
+ (ATL1_MAX_TX_BUF_LEN >=
+ len12) ? ATL1_MAX_TX_BUF_LEN : len12;
len12 -= buffer_info->length;
page = virt_to_page(skb->data +
- (proto_hdr_len +
- i * MAX_TX_BUF_LEN));
+ (proto_hdr_len +
+ i * ATL1_MAX_TX_BUF_LEN));
offset = (unsigned long)(skb->data +
- (proto_hdr_len +
- i * MAX_TX_BUF_LEN)) &
- ~PAGE_MASK;
- buffer_info->dma =
- pci_map_page(adapter->pdev, page, offset,
- buffer_info->length,
- PCI_DMA_TODEVICE);
+ (proto_hdr_len +
+ i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(adapter->pdev,
+ page, offset, buffer_info->length,
+ PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count)
tpd_next_to_use = 0;
}
@@ -1372,8 +1563,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter,
page = virt_to_page(skb->data);
offset = (unsigned long)skb->data & ~PAGE_MASK;
buffer_info->dma = pci_map_page(adapter->pdev, page,
- offset, first_buf_len,
- PCI_DMA_TODEVICE);
+ offset, first_buf_len, PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count)
tpd_next_to_use = 0;
}
@@ -1385,19 +1575,19 @@ static void atl1_tx_map(struct atl1_adapter *adapter,
frag = &skb_shinfo(skb)->frags[f];
lenf = frag->size;
- m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN;
for (i = 0; i < m; i++) {
buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
if (unlikely(buffer_info->skb))
BUG();
buffer_info->skb = NULL;
- buffer_info->length =
- (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf;
+ buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ?
+ ATL1_MAX_TX_BUF_LEN : lenf;
lenf -= buffer_info->length;
- buffer_info->dma =
- pci_map_page(adapter->pdev, frag->page,
- frag->page_offset + i * MAX_TX_BUF_LEN,
- buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = pci_map_page(adapter->pdev,
+ frag->page,
+ frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
+ buffer_info->length, PCI_DMA_TODEVICE);
if (++tpd_next_to_use == tpd_ring->count)
tpd_next_to_use = 0;
@@ -1409,7 +1599,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter,
}
static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
- union tpd_descr *descr)
+ union tpd_descr *descr)
{
/* We enter this function holding a spinlock. */
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
@@ -1453,31 +1643,6 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
}
-static void atl1_update_mailbox(struct atl1_adapter *adapter)
-{
- unsigned long flags;
- u32 tpd_next_to_use;
- u32 rfd_next_to_use;
- u32 rrd_next_to_clean;
- u32 value;
-
- spin_lock_irqsave(&adapter->mb_lock, flags);
-
- tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
- rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
- rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
-
- value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
- MB_RFD_PROD_INDX_SHIFT) |
- ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
- MB_RRD_CONS_INDX_SHIFT) |
- ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
- MB_TPD_PROD_INDX_SHIFT);
- iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
-
- spin_unlock_irqrestore(&adapter->mb_lock, flags);
-}
-
static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct atl1_adapter *adapter = netdev_priv(netdev);
@@ -1513,8 +1678,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
for (f = 0; f < nr_frags; f++) {
frag_size = skb_shinfo(skb)->frags[f].size;
if (frag_size)
- count +=
- (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
}
/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
@@ -1530,7 +1695,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* need additional TPD ? */
if (proto_hdr_len != len)
count += (len - proto_hdr_len +
- MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ ATL1_MAX_TX_BUF_LEN - 1) /
+ ATL1_MAX_TX_BUF_LEN;
}
}
@@ -1538,7 +1704,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (!spin_trylock(&adapter->lock)) {
/* Can't get lock - tell upper layer to requeue */
local_irq_restore(flags);
- dev_dbg(&adapter->pdev->dev, "tx locked\n");
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n");
return NETDEV_TX_LOCKED;
}
@@ -1546,7 +1712,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* not enough descriptors */
netif_stop_queue(netdev);
spin_unlock_irqrestore(&adapter->lock, flags);
- dev_dbg(&adapter->pdev->dev, "tx busy\n");
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n");
return NETDEV_TX_BUSY;
}
@@ -1588,131 +1754,208 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
/*
- * atl1_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
*/
-static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+static irqreturn_t atl1_intr(int irq, void *data)
{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- return &adapter->net_stats;
-}
+ struct atl1_adapter *adapter = netdev_priv(data);
+ u32 status;
+ u8 update_rx;
+ int max_ints = 10;
-/*
- * atl1_clean_rx_ring - Free RFD Buffers
- * @adapter: board private structure
- */
-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
-{
- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
- struct atl1_buffer *buffer_info;
- struct pci_dev *pdev = adapter->pdev;
- unsigned long size;
- unsigned int i;
+ status = adapter->cmb.cmb->int_stats;
+ if (!status)
+ return IRQ_NONE;
- /* Free all the Rx ring sk_buffs */
- for (i = 0; i < rfd_ring->count; i++) {
- buffer_info = &rfd_ring->buffer_info[i];
- if (buffer_info->dma) {
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_FROMDEVICE);
- buffer_info->dma = 0;
+ update_rx = 0;
+
+ do {
+ /* clear CMB interrupt status at once */
+ adapter->cmb.cmb->int_stats = 0;
+
+ if (status & ISR_GPHY) /* clear phy status */
+ atl1_clear_phy_int(adapter);
+
+ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+ iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+ /* check if SMB intr */
+ if (status & ISR_SMB)
+ atl1_inc_smb(adapter);
+
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "pcie phy link down %x\n", status);
+ if (netif_running(adapter->netdev)) { /* reset MAC */
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ schedule_work(&adapter->pcie_dma_to_rst_task);
+ return IRQ_HANDLED;
+ }
}
- if (buffer_info->skb) {
- dev_kfree_skb(buffer_info->skb);
- buffer_info->skb = NULL;
+
+ /* check if DMA read/write error ? */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "pcie DMA r/w error (status = 0x%x)\n",
+ status);
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ schedule_work(&adapter->pcie_dma_to_rst_task);
+ return IRQ_HANDLED;
}
- }
- size = sizeof(struct atl1_buffer) * rfd_ring->count;
- memset(rfd_ring->buffer_info, 0, size);
+ /* link event */
+ if (status & ISR_GPHY) {
+ adapter->soft_stats.tx_carrier_errors++;
+ atl1_check_for_link(adapter);
+ }
- /* Zero out the descriptor ring */
- memset(rfd_ring->desc, 0, rfd_ring->size);
+ /* transmit event */
+ if (status & ISR_CMB_TX)
+ atl1_intr_tx(adapter);
- rfd_ring->next_to_clean = 0;
- atomic_set(&rfd_ring->next_to_use, 0);
+ /* rx exception */
+ if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+ ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+ if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+ ISR_HOST_RRD_OV))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "rx exception, ISR = 0x%x\n", status);
+ atl1_intr_rx(adapter);
+ }
- rrd_ring->next_to_use = 0;
- atomic_set(&rrd_ring->next_to_clean, 0);
+ if (--max_ints < 0)
+ break;
+
+ } while ((status = adapter->cmb.cmb->int_stats));
+
+ /* re-enable Interrupt */
+ iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+ return IRQ_HANDLED;
}
/*
- * atl1_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
+ * atl1_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
*/
-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+static void atl1_watchdog(unsigned long data)
{
- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
- struct atl1_buffer *buffer_info;
- struct pci_dev *pdev = adapter->pdev;
- unsigned long size;
- unsigned int i;
+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
- /* Free all the Tx ring sk_buffs */
- for (i = 0; i < tpd_ring->count; i++) {
- buffer_info = &tpd_ring->buffer_info[i];
- if (buffer_info->dma) {
- pci_unmap_page(pdev, buffer_info->dma,
- buffer_info->length, PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
- }
- }
+ /* Reset the timer */
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
- for (i = 0; i < tpd_ring->count; i++) {
- buffer_info = &tpd_ring->buffer_info[i];
- if (buffer_info->skb) {
- dev_kfree_skb_any(buffer_info->skb);
- buffer_info->skb = NULL;
- }
- }
+/*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_phy_config(unsigned long data)
+{
+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+ struct atl1_hw *hw = &adapter->hw;
+ unsigned long flags;
- size = sizeof(struct atl1_buffer) * tpd_ring->count;
- memset(tpd_ring->buffer_info, 0, size);
+ spin_lock_irqsave(&adapter->lock, flags);
+ adapter->phy_timer_pending = false;
+ atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+ atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
- /* Zero out the descriptor ring */
- memset(tpd_ring->desc, 0, tpd_ring->size);
+/*
+ * atl1_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1_tx_timeout(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ /* Do the reset outside of interrupt context */
+ schedule_work(&adapter->tx_timeout_task);
+}
- atomic_set(&tpd_ring->next_to_use, 0);
- atomic_set(&tpd_ring->next_to_clean, 0);
+/*
+ * Orphaned vendor comment left intact here:
+ * <vendor comment>
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ * </vendor comment>
+ */
+static void atl1_tx_timeout_task(struct work_struct *work)
+{
+ struct atl1_adapter *adapter =
+ container_of(work, struct atl1_adapter, tx_timeout_task);
+ struct net_device *netdev = adapter->netdev;
+
+ netif_device_detach(netdev);
+ atl1_down(adapter);
+ atl1_up(adapter);
+ netif_device_attach(netdev);
}
/*
- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
- * @adapter: board private structure
- *
- * Free all transmit software resources
+ * atl1_link_chg_task - deal with link change event Out of interrupt context
*/
-void atl1_free_ring_resources(struct atl1_adapter *adapter)
+static void atl1_link_chg_task(struct work_struct *work)
{
- struct pci_dev *pdev = adapter->pdev;
- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
- struct atl1_ring_header *ring_header = &adapter->ring_header;
+ struct atl1_adapter *adapter =
+ container_of(work, struct atl1_adapter, link_chg_task);
+ unsigned long flags;
- atl1_clean_tx_ring(adapter);
- atl1_clean_rx_ring(adapter);
+ spin_lock_irqsave(&adapter->lock, flags);
+ atl1_check_link(adapter);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
- kfree(tpd_ring->buffer_info);
- pci_free_consistent(pdev, ring_header->size, ring_header->desc,
- ring_header->dma);
+static void atl1_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ u32 ctrl;
- tpd_ring->buffer_info = NULL;
- tpd_ring->desc = NULL;
- tpd_ring->dma = 0;
+ spin_lock_irqsave(&adapter->lock, flags);
+ /* atl1_irq_disable(adapter); */
+ adapter->vlgrp = grp;
- rfd_ring->buffer_info = NULL;
- rfd_ring->desc = NULL;
- rfd_ring->dma = 0;
+ if (grp) {
+ /* enable VLAN tag insert/strip */
+ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+ ctrl |= MAC_CTRL_RMV_VLAN;
+ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+ } else {
+ /* disable VLAN tag insert/strip */
+ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+ ctrl &= ~MAC_CTRL_RMV_VLAN;
+ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+ }
- rrd_ring->desc = NULL;
- rrd_ring->dma = 0;
+ /* atl1_irq_enable(adapter); */
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+static void atl1_restore_vlan(struct atl1_adapter *adapter)
+{
+ atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+
+int atl1_reset(struct atl1_adapter *adapter)
+{
+ int ret;
+
+ ret = atl1_reset_hw(&adapter->hw);
+ if (ret != ATL1_SUCCESS)
+ return ret;
+ return atl1_init_hw(&adapter->hw);
}
s32 atl1_up(struct atl1_adapter *adapter)
@@ -1723,6 +1966,7 @@ s32 atl1_up(struct atl1_adapter *adapter)
/* hardware has been reset, we need to reload some things */
atl1_set_multi(netdev);
+ atl1_init_ring_ptrs(adapter);
atl1_restore_vlan(adapter);
err = atl1_alloc_rx_buffers(adapter);
if (unlikely(!err)) /* no RX BUFFER allocated */
@@ -1750,11 +1994,6 @@ s32 atl1_up(struct atl1_adapter *adapter)
atl1_check_link(adapter);
return 0;
- /* FIXME: unreachable code! -- CHS */
- /* free irq disable any interrupt */
- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- free_irq(adapter->pdev->irq, netdev);
-
err_up:
pci_disable_msi(adapter->pdev);
/* free rx_buffers */
@@ -1786,172 +2025,6 @@ void atl1_down(struct atl1_adapter *adapter)
}
/*
- * atl1_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- int old_mtu = netdev->mtu;
- int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-
- if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
- return -EINVAL;
- }
-
- adapter->hw.max_frame_size = max_frame;
- adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
- adapter->rx_buffer_len = (max_frame + 7) & ~7;
- adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
-
- netdev->mtu = new_mtu;
- if ((old_mtu != new_mtu) && netif_running(netdev)) {
- atl1_down(adapter);
- atl1_up(adapter);
- }
-
- return 0;
-}
-
-/*
- * atl1_set_mac - Change the Ethernet Address of the NIC
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- */
-static int atl1_set_mac(struct net_device *netdev, void *p)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- struct sockaddr *addr = p;
-
- if (netif_running(netdev))
- return -EBUSY;
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-
- atl1_set_mac_addr(&adapter->hw);
- return 0;
-}
-
-/*
- * atl1_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_watchdog(unsigned long data)
-{
- struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-
- /* Reset the timer */
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
-
-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- u16 result;
-
- atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
-
- return result;
-}
-
-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
-
- atl1_write_phy_reg(&adapter->hw, reg_num, val);
-}
-
-/*
- * atl1_mii_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- unsigned long flags;
- int retval;
-
- if (!netif_running(netdev))
- return -EINVAL;
-
- spin_lock_irqsave(&adapter->lock, flags);
- retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
- spin_unlock_irqrestore(&adapter->lock, flags);
-
- return retval;
-}
-
-/*
- * atl1_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- */
-static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
- switch (cmd) {
- case SIOCGMIIPHY:
- case SIOCGMIIREG:
- case SIOCSMIIREG:
- return atl1_mii_ioctl(netdev, ifr, cmd);
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/*
- * atl1_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- */
-static void atl1_tx_timeout(struct net_device *netdev)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- /* Do the reset outside of interrupt context */
- schedule_work(&adapter->tx_timeout_task);
-}
-
-/*
- * atl1_phy_config - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_phy_config(unsigned long data)
-{
- struct atl1_adapter *adapter = (struct atl1_adapter *)data;
- struct atl1_hw *hw = &adapter->hw;
- unsigned long flags;
-
- spin_lock_irqsave(&adapter->lock, flags);
- adapter->phy_timer_pending = false;
- atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
- atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
- atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
- spin_unlock_irqrestore(&adapter->lock, flags);
-}
-
-int atl1_reset(struct atl1_adapter *adapter)
-{
- int ret;
-
- ret = atl1_reset_hw(&adapter->hw);
- if (ret != ATL1_SUCCESS)
- return ret;
- return atl1_init_hw(&adapter->hw);
-}
-
-/*
* atl1_open - Called when a network interface is made active
* @netdev: network interface device structure
*
@@ -2003,77 +2076,113 @@ static int atl1_close(struct net_device *netdev)
return 0;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void atl1_poll_controller(struct net_device *netdev)
-{
- disable_irq(netdev->irq);
- atl1_intr(netdev->irq, netdev);
- enable_irq(netdev->irq);
-}
-#endif
-
-/*
- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
- * will assert. We do soft reset <0x1400=1> according
- * with the SPEC. BUT, it seemes that PCIE or DMA
- * state-machine will not be reset. DMAR_TO_INT will
- * assert again and again.
- */
-static void atl1_tx_timeout_task(struct work_struct *work)
+#ifdef CONFIG_PM
+static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct atl1_adapter *adapter =
- container_of(work, struct atl1_adapter, tx_timeout_task);
- struct net_device *netdev = adapter->netdev;
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ u32 ctrl = 0;
+ u32 wufc = adapter->wol;
netif_device_detach(netdev);
- atl1_down(adapter);
- atl1_up(adapter);
- netif_device_attach(netdev);
-}
+ if (netif_running(netdev))
+ atl1_down(adapter);
-/*
- * atl1_link_chg_task - deal with link change event Out of interrupt context
- */
-static void atl1_link_chg_task(struct work_struct *work)
-{
- struct atl1_adapter *adapter =
- container_of(work, struct atl1_adapter, link_chg_task);
- unsigned long flags;
+ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+ if (ctrl & BMSR_LSTATUS)
+ wufc &= ~ATL1_WUFC_LNKC;
- spin_lock_irqsave(&adapter->lock, flags);
- atl1_check_link(adapter);
- spin_unlock_irqrestore(&adapter->lock, flags);
+ /* reduce speed to 10/100M */
+ if (wufc) {
+ atl1_phy_enter_power_saving(hw);
+ /* if resume, let driver to re- setup link */
+ hw->phy_configured = false;
+ atl1_set_mac_addr(hw);
+ atl1_set_multi(netdev);
+
+ ctrl = 0;
+ /* turn on magic packet wol */
+ if (wufc & ATL1_WUFC_MAG)
+ ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+ /* turn on Link change WOL */
+ if (wufc & ATL1_WUFC_LNKC)
+ ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+ iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+
+ /* turn on all-multi mode if wake on multicast is enabled */
+ ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+ ctrl &= ~MAC_CTRL_DBG;
+ ctrl &= ~MAC_CTRL_PROMIS_EN;
+ if (wufc & ATL1_WUFC_MC)
+ ctrl |= MAC_CTRL_MC_ALL_EN;
+ else
+ ctrl &= ~MAC_CTRL_MC_ALL_EN;
+
+ /* turn on broadcast mode if wake on-BC is enabled */
+ if (wufc & ATL1_WUFC_BC)
+ ctrl |= MAC_CTRL_BC_EN;
+ else
+ ctrl &= ~MAC_CTRL_BC_EN;
+
+ /* enable RX */
+ ctrl |= MAC_CTRL_RX_EN;
+ iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ pci_enable_wake(pdev, PCI_D3cold, 1);
+ } else {
+ iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+ }
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return 0;
}
-/*
- * atl1_pcie_patch - Patch for PCIE module
- */
-static void atl1_pcie_patch(struct atl1_adapter *adapter)
+static int atl1_resume(struct pci_dev *pdev)
{
- u32 value;
- value = 0x6500;
- iowrite32(value, adapter->hw.hw_addr + 0x12FC);
- /* pcie flow control mode change */
- value = ioread32(adapter->hw.hw_addr + 0x1008);
- value |= 0x8000;
- iowrite32(value, adapter->hw.hw_addr + 0x1008);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ u32 ret_val;
+
+ pci_set_power_state(pdev, 0);
+ pci_restore_state(pdev);
+
+ ret_val = pci_enable_device(pdev);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+ atl1_reset(adapter);
+
+ if (netif_running(netdev))
+ atl1_up(adapter);
+ netif_device_attach(netdev);
+
+ atl1_via_workaround(adapter);
+
+ return 0;
}
+#else
+#define atl1_suspend NULL
+#define atl1_resume NULL
+#endif
-/*
- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
- * on PCI Command register is disable.
- * The function enable this bit.
- * Brackett, 2006/03/15
- */
-static void atl1_via_workaround(struct atl1_adapter *adapter)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void atl1_poll_controller(struct net_device *netdev)
{
- unsigned long value;
-
- value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
- if (value & PCI_COMMAND_INTX_DISABLE)
- value &= ~PCI_COMMAND_INTX_DISABLE;
- iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+ disable_irq(netdev->irq);
+ atl1_intr(netdev->irq, netdev);
+ enable_irq(netdev->irq);
}
+#endif
/*
* atl1_probe - Device Initialization Routine
@@ -2087,7 +2196,7 @@ static void atl1_via_workaround(struct atl1_adapter *adapter)
* and a hardware reset occur.
*/
static int __devinit atl1_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
struct net_device *netdev;
struct atl1_adapter *adapter;
@@ -2141,7 +2250,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
}
/* get device revision number */
adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
- (REG_MASTER_CTRL + 2));
+ (REG_MASTER_CTRL + 2));
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
/* set default ring resource counts */
@@ -2294,7 +2403,8 @@ static void __devexit atl1_remove(struct pci_dev *pdev)
* address, we need to save the permanent one.
*/
if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
- memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN);
+ memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+ ETH_ALEN);
atl1_set_mac_addr(&adapter->hw);
}
@@ -2306,112 +2416,11 @@ static void __devexit atl1_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-#ifdef CONFIG_PM
-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct atl1_adapter *adapter = netdev_priv(netdev);
- struct atl1_hw *hw = &adapter->hw;
- u32 ctrl = 0;
- u32 wufc = adapter->wol;
-
- netif_device_detach(netdev);
- if (netif_running(netdev))
- atl1_down(adapter);
-
- atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
- atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
- if (ctrl & BMSR_LSTATUS)
- wufc &= ~ATL1_WUFC_LNKC;
-
- /* reduce speed to 10/100M */
- if (wufc) {
- atl1_phy_enter_power_saving(hw);
- /* if resume, let driver to re- setup link */
- hw->phy_configured = false;
- atl1_set_mac_addr(hw);
- atl1_set_multi(netdev);
-
- ctrl = 0;
- /* turn on magic packet wol */
- if (wufc & ATL1_WUFC_MAG)
- ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
- /* turn on Link change WOL */
- if (wufc & ATL1_WUFC_LNKC)
- ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
- iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
-
- /* turn on all-multi mode if wake on multicast is enabled */
- ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
- ctrl &= ~MAC_CTRL_DBG;
- ctrl &= ~MAC_CTRL_PROMIS_EN;
- if (wufc & ATL1_WUFC_MC)
- ctrl |= MAC_CTRL_MC_ALL_EN;
- else
- ctrl &= ~MAC_CTRL_MC_ALL_EN;
-
- /* turn on broadcast mode if wake on-BC is enabled */
- if (wufc & ATL1_WUFC_BC)
- ctrl |= MAC_CTRL_BC_EN;
- else
- ctrl &= ~MAC_CTRL_BC_EN;
-
- /* enable RX */
- ctrl |= MAC_CTRL_RX_EN;
- iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
- pci_enable_wake(pdev, PCI_D3hot, 1);
- pci_enable_wake(pdev, PCI_D3cold, 1); /* 4 == D3 cold */
- } else {
- iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
- }
-
- pci_save_state(pdev);
- pci_disable_device(pdev);
-
- pci_set_power_state(pdev, PCI_D3hot);
-
- return 0;
-}
-
-static int atl1_resume(struct pci_dev *pdev)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct atl1_adapter *adapter = netdev_priv(netdev);
- u32 ret_val;
-
- pci_set_power_state(pdev, 0);
- pci_restore_state(pdev);
-
- ret_val = pci_enable_device(pdev);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
-
- iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
- atl1_reset(adapter);
-
- if (netif_running(netdev))
- atl1_up(adapter);
- netif_device_attach(netdev);
-
- atl1_via_workaround(adapter);
-
- return 0;
-}
-#else
-#define atl1_suspend NULL
-#define atl1_resume NULL
-#endif
-
static struct pci_driver atl1_driver = {
.name = atl1_driver_name,
.id_table = atl1_pci_tbl,
.probe = atl1_probe,
.remove = __devexit_p(atl1_remove),
- /* Power Managment Hooks */
- /* probably broken right now -- CHS */
.suspend = atl1_suspend,
.resume = atl1_resume
};
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 9afa47edfc58..3c54014acece 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -2292,10 +2292,15 @@ static int eepro100_resume(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata (pdev);
struct speedo_private *sp = netdev_priv(dev);
void __iomem *ioaddr = sp->regs;
+ int rc;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- pci_enable_device(pdev);
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
pci_set_master(pdev);
if (!netif_running(dev))
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index f03f070451de..6628fa622e2c 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,13 +39,13 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0067"
+#define DRV_VERSION "EHEA_0070"
-/* EHEA capability flags */
+/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
-#define DLPAR_MEM_ADD 2
-#define DLPAR_MEM_REM 4
-#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
+#define DLPAR_MEM_ADD 2
+#define DLPAR_MEM_REM 4
+#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -113,6 +113,8 @@
/* Memory Regions */
#define EHEA_MR_ACC_CTRL 0x00800000
+#define EHEA_BUSMAP_START 0x8000000000000000ULL
+
#define EHEA_WATCH_DOG_TIMEOUT 10*HZ
/* utility functions */
@@ -186,6 +188,12 @@ struct h_epas {
set to 0 if unused */
};
+struct ehea_busmap {
+ unsigned int entries; /* total number of entries */
+ unsigned int valid_sections; /* number of valid sections */
+ u64 *vaddr;
+};
+
struct ehea_qp;
struct ehea_cq;
struct ehea_eq;
@@ -382,6 +390,8 @@ struct ehea_adapter {
struct ehea_mr mr;
u32 pd; /* protection domain */
u64 max_mc_mac; /* max number of multicast mac addresses */
+ int active_ports;
+ struct list_head list;
};
@@ -431,6 +441,9 @@ struct port_res_cfg {
int max_entries_rq3;
};
+enum ehea_flag_bits {
+ __EHEA_STOP_XFER
+};
void ehea_set_ethtool_ops(struct net_device *netdev);
int ehea_sense_port_attr(struct ehea_port *port);
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 383144db4d18..1d1571cf322e 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -79,6 +79,11 @@ MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
static int port_name_cnt = 0;
+static LIST_HEAD(adapter_list);
+u64 ehea_driver_flags = 0;
+struct workqueue_struct *ehea_driver_wq;
+struct work_struct ehea_rereg_mr_task;
+
static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
const struct of_device_id *id);
@@ -238,13 +243,17 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
| EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
- rwqe->sg_list[0].vaddr = (u64)skb->data;
+ rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
rwqe->sg_list[0].len = packet_size;
rwqe->data_segments = 1;
index++;
index &= max_index_mask;
+
+ if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
+ goto out;
}
+
q_skba->index = index;
/* Ring doorbell */
@@ -253,7 +262,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
ehea_update_rq2a(pr->qp, i);
else
ehea_update_rq3a(pr->qp, i);
-
+out:
return ret;
}
@@ -1321,7 +1330,7 @@ static void write_swqe2_TSO(struct sk_buff *skb,
sg1entry->len = skb_data_size - headersize;
tmp_addr = (u64)(skb->data + headersize);
- sg1entry->vaddr = tmp_addr;
+ sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
}
} else
@@ -1352,7 +1361,7 @@ static void write_swqe2_nonTSO(struct sk_buff *skb,
sg1entry->l_key = lkey;
sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM);
- sg1entry->vaddr = tmp_addr;
+ sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
}
} else {
@@ -1391,7 +1400,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
sg1entry->len = frag->size;
tmp_addr = (u64)(page_address(frag->page)
+ frag->page_offset);
- sg1entry->vaddr = tmp_addr;
+ sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
sg1entry_contains_frag_data = 1;
}
@@ -1406,7 +1415,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
tmp_addr = (u64)(page_address(frag->page)
+ frag->page_offset);
- sgentry->vaddr = tmp_addr;
+ sgentry->vaddr = ehea_map_vaddr(tmp_addr);
swqe->descriptors++;
}
}
@@ -1878,6 +1887,9 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
ehea_dump(swqe, 512, "swqe");
}
+ if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
+ goto out;
+
ehea_post_swqe(pr->qp, swqe);
pr->tx_packets++;
@@ -1892,7 +1904,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev->trans_start = jiffies;
spin_unlock(&pr->xmit_lock);
-
+out:
return NETDEV_TX_OK;
}
@@ -2220,6 +2232,9 @@ out_dereg_bc:
out_clean_pr:
ehea_clean_all_portres(port);
out:
+ if (ret)
+ ehea_info("Failed starting %s. ret=%i", dev->name, ret);
+
return ret;
}
@@ -2259,8 +2274,13 @@ static int ehea_down(struct net_device *dev)
msleep(1);
ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
- ret = ehea_clean_all_portres(port);
port->state = EHEA_PORT_DOWN;
+
+ ret = ehea_clean_all_portres(port);
+ if (ret)
+ ehea_info("Failed freeing resources for %s. ret=%i",
+ dev->name, ret);
+
return ret;
}
@@ -2292,15 +2312,11 @@ static void ehea_reset_port(struct work_struct *work)
netif_stop_queue(dev);
netif_poll_disable(dev);
- ret = ehea_down(dev);
- if (ret)
- ehea_error("ehea_down failed. not all resources are freed");
+ ehea_down(dev);
ret = ehea_up(dev);
- if (ret) {
- ehea_error("Reset device %s failed: ret=%d", dev->name, ret);
+ if (ret)
goto out;
- }
if (netif_msg_timer(port))
ehea_info("Device %s resetted successfully", dev->name);
@@ -2312,6 +2328,88 @@ out:
return;
}
+static void ehea_rereg_mrs(struct work_struct *work)
+{
+ int ret, i;
+ struct ehea_adapter *adapter;
+
+ ehea_info("LPAR memory enlarged - re-initializing driver");
+
+ list_for_each_entry(adapter, &adapter_list, list)
+ if (adapter->active_ports) {
+ /* Shutdown all ports */
+ for (i = 0; i < EHEA_MAX_PORTS; i++) {
+ struct ehea_port *port = adapter->port[i];
+
+ if (port) {
+ struct net_device *dev = port->netdev;
+
+ if (dev->flags & IFF_UP) {
+ ehea_info("stopping %s",
+ dev->name);
+ down(&port->port_lock);
+ netif_stop_queue(dev);
+ netif_poll_disable(dev);
+ ehea_down(dev);
+ up(&port->port_lock);
+ }
+ }
+ }
+
+ /* Unregister old memory region */
+ ret = ehea_rem_mr(&adapter->mr);
+ if (ret) {
+ ehea_error("unregister MR failed - driver"
+ " inoperable!");
+ goto out;
+ }
+ }
+
+ ehea_destroy_busmap();
+
+ ret = ehea_create_busmap();
+ if (ret)
+ goto out;
+
+ clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
+
+ list_for_each_entry(adapter, &adapter_list, list)
+ if (adapter->active_ports) {
+ /* Register new memory region */
+ ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
+ if (ret) {
+ ehea_error("register MR failed - driver"
+ " inoperable!");
+ goto out;
+ }
+
+ /* Restart all ports */
+ for (i = 0; i < EHEA_MAX_PORTS; i++) {
+ struct ehea_port *port = adapter->port[i];
+
+ if (port) {
+ struct net_device *dev = port->netdev;
+
+ if (dev->flags & IFF_UP) {
+ ehea_info("restarting %s",
+ dev->name);
+ down(&port->port_lock);
+
+ ret = ehea_up(dev);
+ if (!ret) {
+ netif_poll_enable(dev);
+ netif_wake_queue(dev);
+ }
+
+ up(&port->port_lock);
+ }
+ }
+ }
+ }
+out:
+ return;
+}
+
static void ehea_tx_watchdog(struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
@@ -2573,6 +2671,8 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
ehea_info("%s: Jumbo frames are %sabled", dev->name,
jumbo == 1 ? "en" : "dis");
+ adapter->active_ports++;
+
return port;
out_unreg_port:
@@ -2596,6 +2696,7 @@ static void ehea_shutdown_single_port(struct ehea_port *port)
ehea_unregister_port(port);
kfree(port->mc_list);
free_netdev(port->netdev);
+ port->adapter->active_ports--;
}
static int ehea_setup_ports(struct ehea_adapter *adapter)
@@ -2788,6 +2889,8 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
goto out;
}
+ list_add(&adapter->list, &adapter_list);
+
adapter->ebus_dev = dev;
adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
@@ -2891,7 +2994,10 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
ehea_destroy_eq(adapter->neq);
ehea_remove_adapter_mr(adapter);
+ list_del(&adapter->list);
+
kfree(adapter);
+
return 0;
}
@@ -2939,9 +3045,18 @@ int __init ehea_module_init(void)
printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
DRV_VERSION);
+ ehea_driver_wq = create_workqueue("ehea_driver_wq");
+
+ INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
+
ret = check_module_parm();
if (ret)
goto out;
+
+ ret = ehea_create_busmap();
+ if (ret)
+ goto out;
+
ret = ibmebus_register_driver(&ehea_driver);
if (ret) {
ehea_error("failed registering eHEA device driver on ebus");
@@ -2965,6 +3080,7 @@ static void __exit ehea_module_exit(void)
{
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
+ ehea_destroy_busmap();
}
module_init(ehea_module_init);
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h
index d17a45a7e717..89b63531ff26 100644
--- a/drivers/net/ehea/ehea_phyp.h
+++ b/drivers/net/ehea/ehea_phyp.h
@@ -60,6 +60,9 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code)
}
}
+/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
+#define EHEA_MAX_RPAGE 512
+
/* Notification Event Queue (NEQ) Entry bit masks */
#define NEQE_EVENT_CODE EHEA_BMASK_IBM(2, 7)
#define NEQE_PORTNUM EHEA_BMASK_IBM(32, 47)
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 29eaa46948b0..a36fa6c23fdf 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -31,6 +31,13 @@
#include "ehea_phyp.h"
#include "ehea_qmr.h"
+
+struct ehea_busmap ehea_bmap = { 0, 0, NULL };
+extern u64 ehea_driver_flags;
+extern struct workqueue_struct *ehea_driver_wq;
+extern struct work_struct ehea_rereg_mr_task;
+
+
static void *hw_qpageit_get_inc(struct hw_queue *queue)
{
void *retvalue = hw_qeit_get(queue);
@@ -547,18 +554,84 @@ int ehea_destroy_qp(struct ehea_qp *qp)
return 0;
}
+int ehea_create_busmap( void )
+{
+ u64 vaddr = EHEA_BUSMAP_START;
+ unsigned long abs_max_pfn = 0;
+ unsigned long sec_max_pfn;
+ int i;
+
+ /*
+ * Sections are not in ascending order -> Loop over all sections and
+ * find the highest PFN to compute the required map size.
+ */
+ ehea_bmap.valid_sections = 0;
+
+ for (i = 0; i < NR_MEM_SECTIONS; i++)
+ if (valid_section_nr(i)) {
+ sec_max_pfn = section_nr_to_pfn(i);
+ if (sec_max_pfn > abs_max_pfn)
+ abs_max_pfn = sec_max_pfn;
+ ehea_bmap.valid_sections++;
+ }
+
+ ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1;
+ ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr));
+
+ if (!ehea_bmap.vaddr)
+ return -ENOMEM;
+
+ for (i = 0 ; i < ehea_bmap.entries; i++) {
+ unsigned long pfn = section_nr_to_pfn(i);
+
+ if (pfn_valid(pfn)) {
+ ehea_bmap.vaddr[i] = vaddr;
+ vaddr += EHEA_SECTSIZE;
+ } else
+ ehea_bmap.vaddr[i] = 0;
+ }
+
+ return 0;
+}
+
+void ehea_destroy_busmap( void )
+{
+ vfree(ehea_bmap.vaddr);
+}
+
+u64 ehea_map_vaddr(void *caddr)
+{
+ u64 mapped_addr;
+ unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS;
+
+ if (likely(index < ehea_bmap.entries)) {
+ mapped_addr = ehea_bmap.vaddr[index];
+ if (likely(mapped_addr))
+ mapped_addr |= (((unsigned long)caddr)
+ & (EHEA_SECTSIZE - 1));
+ else
+ mapped_addr = -1;
+ } else
+ mapped_addr = -1;
+
+ if (unlikely(mapped_addr == -1))
+ if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
+ queue_work(ehea_driver_wq, &ehea_rereg_mr_task);
+
+ return mapped_addr;
+}
+
int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
{
- int i, k, ret;
- u64 hret, pt_abs, start, end, nr_pages;
- u32 acc_ctrl = EHEA_MR_ACC_CTRL;
+ int ret;
u64 *pt;
+ void *pg;
+ u64 hret, pt_abs, i, j, m, mr_len;
+ u32 acc_ctrl = EHEA_MR_ACC_CTRL;
- start = KERNELBASE;
- end = (u64)high_memory;
- nr_pages = (end - start) / EHEA_PAGESIZE;
+ mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE;
- pt = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ pt = kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL);
if (!pt) {
ehea_error("no mem");
ret = -ENOMEM;
@@ -566,7 +639,8 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
}
pt_abs = virt_to_abs(pt);
- hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start,
+ hret = ehea_h_alloc_resource_mr(adapter->handle,
+ EHEA_BUSMAP_START, mr_len,
acc_ctrl, adapter->pd,
&mr->handle, &mr->lkey);
if (hret != H_SUCCESS) {
@@ -575,49 +649,43 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
goto out;
}
- mr->vaddr = KERNELBASE;
- k = 0;
-
- while (nr_pages > 0) {
- if (nr_pages > 1) {
- u64 num_pages = min(nr_pages, (u64)512);
- for (i = 0; i < num_pages; i++)
- pt[i] = virt_to_abs((void*)(((u64)start) +
- ((k++) *
- EHEA_PAGESIZE)));
-
- hret = ehea_h_register_rpage_mr(adapter->handle,
- mr->handle, 0,
- 0, (u64)pt_abs,
- num_pages);
- nr_pages -= num_pages;
- } else {
- u64 abs_adr = virt_to_abs((void*)(((u64)start) +
- (k * EHEA_PAGESIZE)));
-
- hret = ehea_h_register_rpage_mr(adapter->handle,
- mr->handle, 0,
- 0, abs_adr,1);
- nr_pages--;
- }
-
- if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {
- ehea_h_free_resource(adapter->handle,
- mr->handle, FORCE_FREE);
- ehea_error("register_rpage_mr failed");
- ret = -EIO;
- goto out;
+ for (i = 0 ; i < ehea_bmap.entries; i++)
+ if (ehea_bmap.vaddr[i]) {
+ void *sectbase = __va(i << SECTION_SIZE_BITS);
+ unsigned long k = 0;
+
+ for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE);
+ j++) {
+
+ for (m = 0; m < EHEA_MAX_RPAGE; m++) {
+ pg = sectbase + ((k++) * EHEA_PAGESIZE);
+ pt[m] = virt_to_abs(pg);
+ }
+
+ hret = ehea_h_register_rpage_mr(adapter->handle,
+ mr->handle,
+ 0, 0, pt_abs,
+ EHEA_MAX_RPAGE);
+ if ((hret != H_SUCCESS)
+ && (hret != H_PAGE_REGISTERED)) {
+ ehea_h_free_resource(adapter->handle,
+ mr->handle,
+ FORCE_FREE);
+ ehea_error("register_rpage_mr failed");
+ ret = -EIO;
+ goto out;
+ }
+ }
}
- }
if (hret != H_SUCCESS) {
- ehea_h_free_resource(adapter->handle, mr->handle,
- FORCE_FREE);
- ehea_error("register_rpage failed for last page");
+ ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
+ ehea_error("registering mr failed");
ret = -EIO;
goto out;
}
+ mr->vaddr = EHEA_BUSMAP_START;
mr->adapter = adapter;
ret = 0;
out:
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index c0eb3e03a102..b71f8452a5e3 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -36,8 +36,14 @@
* page size of ehea hardware queues
*/
-#define EHEA_PAGESHIFT 12
-#define EHEA_PAGESIZE 4096UL
+#define EHEA_PAGESHIFT 12
+#define EHEA_PAGESIZE (1UL << EHEA_PAGESHIFT)
+#define EHEA_SECTSIZE (1UL << 24)
+#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> PAGE_SHIFT)
+
+#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE
+#error eHEA module can't work if kernel sectionsize < ehea sectionsize
+#endif
/* Some abbreviations used here:
*
@@ -372,4 +378,8 @@ int ehea_rem_mr(struct ehea_mr *mr);
void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
+int ehea_create_busmap( void );
+void ehea_destroy_busmap( void );
+u64 ehea_map_vaddr(void *caddr);
+
#endif /* __EHEA_QMR_H__ */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 67046e8c21eb..136827f8dc2e 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -550,6 +550,8 @@ union ring_type {
/* PHY defines */
#define PHY_OUI_MARVELL 0x5043
#define PHY_OUI_CICADA 0x03f1
+#define PHY_OUI_VITESSE 0x01c1
+#define PHY_OUI_REALTEK 0x01c1
#define PHYID1_OUI_MASK 0x03ff
#define PHYID1_OUI_SHFT 6
#define PHYID2_OUI_MASK 0xfc00
@@ -557,12 +559,36 @@ union ring_type {
#define PHYID2_MODEL_MASK 0x03f0
#define PHY_MODEL_MARVELL_E3016 0x220
#define PHY_MARVELL_E3016_INITMASK 0x0300
-#define PHY_INIT1 0x0f000
-#define PHY_INIT2 0x0e00
-#define PHY_INIT3 0x01000
-#define PHY_INIT4 0x0200
-#define PHY_INIT5 0x0004
-#define PHY_INIT6 0x02000
+#define PHY_CICADA_INIT1 0x0f000
+#define PHY_CICADA_INIT2 0x0e00
+#define PHY_CICADA_INIT3 0x01000
+#define PHY_CICADA_INIT4 0x0200
+#define PHY_CICADA_INIT5 0x0004
+#define PHY_CICADA_INIT6 0x02000
+#define PHY_VITESSE_INIT_REG1 0x1f
+#define PHY_VITESSE_INIT_REG2 0x10
+#define PHY_VITESSE_INIT_REG3 0x11
+#define PHY_VITESSE_INIT_REG4 0x12
+#define PHY_VITESSE_INIT_MSK1 0xc
+#define PHY_VITESSE_INIT_MSK2 0x0180
+#define PHY_VITESSE_INIT1 0x52b5
+#define PHY_VITESSE_INIT2 0xaf8a
+#define PHY_VITESSE_INIT3 0x8
+#define PHY_VITESSE_INIT4 0x8f8a
+#define PHY_VITESSE_INIT5 0xaf86
+#define PHY_VITESSE_INIT6 0x8f86
+#define PHY_VITESSE_INIT7 0xaf82
+#define PHY_VITESSE_INIT8 0x0100
+#define PHY_VITESSE_INIT9 0x8f82
+#define PHY_VITESSE_INIT10 0x0
+#define PHY_REALTEK_INIT_REG1 0x1f
+#define PHY_REALTEK_INIT_REG2 0x19
+#define PHY_REALTEK_INIT_REG3 0x13
+#define PHY_REALTEK_INIT1 0x0000
+#define PHY_REALTEK_INIT2 0x8e00
+#define PHY_REALTEK_INIT3 0x0001
+#define PHY_REALTEK_INIT4 0xad17
+
#define PHY_GIGABIT 0x0100
#define PHY_TIMEOUT 0x1
@@ -1096,6 +1122,28 @@ static int phy_init(struct net_device *dev)
return PHY_ERROR;
}
}
+ if (np->phy_oui == PHY_OUI_REALTEK) {
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ }
/* set advertise register */
reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
@@ -1141,14 +1189,14 @@ static int phy_init(struct net_device *dev)
/* phy vendor specific configuration */
if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
- phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
- phy_reserved |= (PHY_INIT3 | PHY_INIT4);
+ phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
+ phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
- phy_reserved |= PHY_INIT5;
+ phy_reserved |= PHY_CICADA_INIT5;
if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
@@ -1156,12 +1204,106 @@ static int phy_init(struct net_device *dev)
}
if (np->phy_oui == PHY_OUI_CICADA) {
phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
- phy_reserved |= PHY_INIT6;
+ phy_reserved |= PHY_CICADA_INIT6;
if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR;
}
}
+ if (np->phy_oui == PHY_OUI_VITESSE) {
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+ phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+ phy_reserved |= PHY_VITESSE_INIT3;
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+ phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+ phy_reserved |= PHY_VITESSE_INIT3;
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+ phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
+ phy_reserved |= PHY_VITESSE_INIT8;
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ }
+ if (np->phy_oui == PHY_OUI_REALTEK) {
+ /* reset could have cleared these out, set them back */
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+ return PHY_ERROR;
+ }
+ }
+
/* some phys clear out pause advertisment on reset, set it back */
mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 5dd34a1a7b89..ac3596f45dd8 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -31,7 +31,6 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <asm/ocp.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/phy.h>
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0e04f7ac3f2e..a4bb0264180a 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -17,13 +17,12 @@
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include <linux/mutex.h>
#include <linux/dma-mapping.h>
-#include <linux/ethtool.h>
#include <linux/platform_device.h>
+#include <linux/phy.h>
#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
#include "macb.h"
@@ -85,172 +84,202 @@ static void __init macb_get_hwaddr(struct macb *bp)
memcpy(bp->dev->dev_addr, addr, sizeof(addr));
}
-static void macb_enable_mdio(struct macb *bp)
+static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
- unsigned long flags;
- u32 reg;
-
- spin_lock_irqsave(&bp->lock, flags);
- reg = macb_readl(bp, NCR);
- reg |= MACB_BIT(MPE);
- macb_writel(bp, NCR, reg);
- macb_writel(bp, IER, MACB_BIT(MFD));
- spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static void macb_disable_mdio(struct macb *bp)
-{
- unsigned long flags;
- u32 reg;
-
- spin_lock_irqsave(&bp->lock, flags);
- reg = macb_readl(bp, NCR);
- reg &= ~MACB_BIT(MPE);
- macb_writel(bp, NCR, reg);
- macb_writel(bp, IDR, MACB_BIT(MFD));
- spin_unlock_irqrestore(&bp->lock, flags);
-}
-
-static int macb_mdio_read(struct net_device *dev, int phy_id, int location)
-{
- struct macb *bp = netdev_priv(dev);
+ struct macb *bp = bus->priv;
int value;
- mutex_lock(&bp->mdio_mutex);
-
- macb_enable_mdio(bp);
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
| MACB_BF(RW, MACB_MAN_READ)
- | MACB_BF(PHYA, phy_id)
- | MACB_BF(REGA, location)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_CODE)));
- wait_for_completion(&bp->mdio_complete);
+ /* wait for end of transfer */
+ while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
+ cpu_relax();
value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
- macb_disable_mdio(bp);
- mutex_unlock(&bp->mdio_mutex);
return value;
}
-static void macb_mdio_write(struct net_device *dev, int phy_id,
- int location, int val)
+static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+ u16 value)
{
- struct macb *bp = netdev_priv(dev);
-
- dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",
- phy_id, location, val);
-
- mutex_lock(&bp->mdio_mutex);
- macb_enable_mdio(bp);
+ struct macb *bp = bus->priv;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
| MACB_BF(RW, MACB_MAN_WRITE)
- | MACB_BF(PHYA, phy_id)
- | MACB_BF(REGA, location)
+ | MACB_BF(PHYA, mii_id)
+ | MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_CODE)
- | MACB_BF(DATA, val)));
+ | MACB_BF(DATA, value)));
- wait_for_completion(&bp->mdio_complete);
+ /* wait for end of transfer */
+ while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
+ cpu_relax();
- macb_disable_mdio(bp);
- mutex_unlock(&bp->mdio_mutex);
+ return 0;
}
-static int macb_phy_probe(struct macb *bp)
+static int macb_mdio_reset(struct mii_bus *bus)
{
- int phy_address;
- u16 phyid1, phyid2;
+ return 0;
+}
- for (phy_address = 0; phy_address < 32; phy_address++) {
- phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);
- phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2);
+static void macb_handle_link_change(struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
+ struct phy_device *phydev = bp->phy_dev;
+ unsigned long flags;
- if (phyid1 != 0xffff && phyid1 != 0x0000
- && phyid2 != 0xffff && phyid2 != 0x0000)
- break;
+ int status_change = 0;
+
+ spin_lock_irqsave(&bp->lock, flags);
+
+ if (phydev->link) {
+ if ((bp->speed != phydev->speed) ||
+ (bp->duplex != phydev->duplex)) {
+ u32 reg;
+
+ reg = macb_readl(bp, NCFGR);
+ reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+
+ if (phydev->duplex)
+ reg |= MACB_BIT(FD);
+ if (phydev->speed)
+ reg |= MACB_BIT(SPD);
+
+ macb_writel(bp, NCFGR, reg);
+
+ bp->speed = phydev->speed;
+ bp->duplex = phydev->duplex;
+ status_change = 1;
+ }
}
- if (phy_address == 32)
- return -ENODEV;
+ if (phydev->link != bp->link) {
+ if (phydev->link)
+ netif_schedule(dev);
+ else {
+ bp->speed = 0;
+ bp->duplex = -1;
+ }
+ bp->link = phydev->link;
- dev_info(&bp->pdev->dev,
- "detected PHY at address %d (ID %04x:%04x)\n",
- phy_address, phyid1, phyid2);
+ status_change = 1;
+ }
- bp->mii.phy_id = phy_address;
- return 0;
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ if (status_change) {
+ if (phydev->link)
+ printk(KERN_INFO "%s: link up (%d/%s)\n",
+ dev->name, phydev->speed,
+ DUPLEX_FULL == phydev->duplex ? "Full":"Half");
+ else
+ printk(KERN_INFO "%s: link down\n", dev->name);
+ }
}
-static void macb_set_media(struct macb *bp, int media)
+/* based on au1000_eth. c*/
+static int macb_mii_probe(struct net_device *dev)
{
- u32 reg;
+ struct macb *bp = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ struct eth_platform_data *pdata;
+ int phy_addr;
- spin_lock_irq(&bp->lock);
- reg = macb_readl(bp, NCFGR);
- reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
- if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))
- reg |= MACB_BIT(SPD);
- if (media & ADVERTISE_FULL)
- reg |= MACB_BIT(FD);
- macb_writel(bp, NCFGR, reg);
- spin_unlock_irq(&bp->lock);
+ /* find the first phy */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+ if (bp->mii_bus.phy_map[phy_addr]) {
+ phydev = bp->mii_bus.phy_map[phy_addr];
+ break;
+ }
+ }
+
+ if (!phydev) {
+ printk (KERN_ERR "%s: no PHY found\n", dev->name);
+ return -1;
+ }
+
+ pdata = bp->pdev->dev.platform_data;
+ /* TODO : add pin_irq */
+
+ /* attach the mac to the phy */
+ if (pdata && pdata->is_rmii) {
+ phydev = phy_connect(dev, phydev->dev.bus_id,
+ &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII);
+ } else {
+ phydev = phy_connect(dev, phydev->dev.bus_id,
+ &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII);
+ }
+
+ if (IS_ERR(phydev)) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(phydev);
+ }
+
+ /* mask with MAC supported features */
+ phydev->supported &= PHY_BASIC_FEATURES;
+
+ phydev->advertising = phydev->supported;
+
+ bp->link = 0;
+ bp->speed = 0;
+ bp->duplex = -1;
+ bp->phy_dev = phydev;
+
+ return 0;
}
-static void macb_check_media(struct macb *bp, int ok_to_print, int init_media)
+static int macb_mii_init(struct macb *bp)
{
- struct mii_if_info *mii = &bp->mii;
- unsigned int old_carrier, new_carrier;
- int advertise, lpa, media, duplex;
+ struct eth_platform_data *pdata;
+ int err = -ENXIO, i;
- /* if forced media, go no further */
- if (mii->force_media)
- return;
+ /* Enable managment port */
+ macb_writel(bp, NCR, MACB_BIT(MPE));
- /* check current and old link status */
- old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
- new_carrier = (unsigned int) mii_link_ok(mii);
+ bp->mii_bus.name = "MACB_mii_bus",
+ bp->mii_bus.read = &macb_mdio_read,
+ bp->mii_bus.write = &macb_mdio_write,
+ bp->mii_bus.reset = &macb_mdio_reset,
+ bp->mii_bus.id = bp->pdev->id,
+ bp->mii_bus.priv = bp,
+ bp->mii_bus.dev = &bp->dev->dev;
+ pdata = bp->pdev->dev.platform_data;
- /* if carrier state did not change, assume nothing else did */
- if (!init_media && old_carrier == new_carrier)
- return;
+ if (pdata)
+ bp->mii_bus.phy_mask = pdata->phy_mask;
- /* no carrier, nothing much to do */
- if (!new_carrier) {
- netif_carrier_off(mii->dev);
- printk(KERN_INFO "%s: link down\n", mii->dev->name);
- return;
+ bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ if (!bp->mii_bus.irq) {
+ err = -ENOMEM;
+ goto err_out;
}
- /*
- * we have carrier, see who's on the other end
- */
- netif_carrier_on(mii->dev);
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ bp->mii_bus.irq[i] = PHY_POLL;
- /* get MII advertise and LPA values */
- if (!init_media && mii->advertising) {
- advertise = mii->advertising;
- } else {
- advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
- mii->advertising = advertise;
- }
- lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+ platform_set_drvdata(bp->dev, &bp->mii_bus);
- /* figure out media and duplex from advertise and LPA values */
- media = mii_nway_result(lpa & advertise);
- duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+ if (mdiobus_register(&bp->mii_bus))
+ goto err_out_free_mdio_irq;
- if (ok_to_print)
- printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
- mii->dev->name,
- media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
- duplex ? "full" : "half", lpa);
+ if (macb_mii_probe(bp->dev) != 0) {
+ goto err_out_unregister_bus;
+ }
- mii->full_duplex = duplex;
+ return 0;
- /* Let the MAC know about the new link state */
- macb_set_media(bp, media);
+err_out_unregister_bus:
+ mdiobus_unregister(&bp->mii_bus);
+err_out_free_mdio_irq:
+ kfree(bp->mii_bus.irq);
+err_out:
+ return err;
}
static void macb_update_stats(struct macb *bp)
@@ -265,16 +294,6 @@ static void macb_update_stats(struct macb *bp)
*p += __raw_readl(reg);
}
-static void macb_periodic_task(struct work_struct *work)
-{
- struct macb *bp = container_of(work, struct macb, periodic_task.work);
-
- macb_update_stats(bp);
- macb_check_media(bp, 1, 0);
-
- schedule_delayed_work(&bp->periodic_task, HZ);
-}
-
static void macb_tx(struct macb *bp)
{
unsigned int tail;
@@ -519,9 +538,6 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
spin_lock(&bp->lock);
while (status) {
- if (status & MACB_BIT(MFD))
- complete(&bp->mdio_complete);
-
/* close possible race with dev_close */
if (unlikely(!netif_running(dev))) {
macb_writel(bp, IDR, ~0UL);
@@ -535,7 +551,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
* until we have processed the buffers
*/
macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
- dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n");
+ dev_dbg(&bp->pdev->dev,
+ "scheduling RX softirq\n");
__netif_rx_schedule(dev);
}
}
@@ -765,7 +782,7 @@ static void macb_init_hw(struct macb *bp)
macb_writel(bp, TBQP, bp->tx_ring_dma);
/* Enable TX and RX */
- macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE));
+ macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
/* Enable interrupts */
macb_writel(bp, IER, (MACB_BIT(RCOMP)
@@ -776,18 +793,126 @@ static void macb_init_hw(struct macb *bp)
| MACB_BIT(TCOMP)
| MACB_BIT(ISR_ROVR)
| MACB_BIT(HRESP)));
+
}
-static void macb_init_phy(struct net_device *dev)
+/*
+ * The hash address register is 64 bits long and takes up two
+ * locations in the memory map. The least significant bits are stored
+ * in EMAC_HSL and the most significant bits in EMAC_HSH.
+ *
+ * The unicast hash enable and the multicast hash enable bits in the
+ * network configuration register enable the reception of hash matched
+ * frames. The destination address is reduced to a 6 bit index into
+ * the 64 bit hash register using the following hash function. The
+ * hash function is an exclusive or of every sixth bit of the
+ * destination address.
+ *
+ * hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
+ * hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
+ * hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
+ * hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
+ * hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
+ * hi[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
+ *
+ * da[0] represents the least significant bit of the first byte
+ * received, that is, the multicast/unicast indicator, and da[47]
+ * represents the most significant bit of the last byte received. If
+ * the hash index, hi[n], points to a bit that is set in the hash
+ * register then the frame will be matched according to whether the
+ * frame is multicast or unicast. A multicast match will be signalled
+ * if the multicast hash enable bit is set, da[0] is 1 and the hash
+ * index points to a bit set in the hash register. A unicast match
+ * will be signalled if the unicast hash enable bit is set, da[0] is 0
+ * and the hash index points to a bit set in the hash register. To
+ * receive all multicast frames, the hash register should be set with
+ * all ones and the multicast hash enable bit should be set in the
+ * network configuration register.
+ */
+
+static inline int hash_bit_value(int bitnr, __u8 *addr)
{
+ if (addr[bitnr / 8] & (1 << (bitnr % 8)))
+ return 1;
+ return 0;
+}
+
+/*
+ * Return the hash index value for the specified address.
+ */
+static int hash_get_index(__u8 *addr)
+{
+ int i, j, bitval;
+ int hash_index = 0;
+
+ for (j = 0; j < 6; j++) {
+ for (i = 0, bitval = 0; i < 8; i++)
+ bitval ^= hash_bit_value(i*6 + j, addr);
+
+ hash_index |= (bitval << j);
+ }
+
+ return hash_index;
+}
+
+/*
+ * Add multicast addresses to the internal multicast-hash table.
+ */
+static void macb_sethashtable(struct net_device *dev)
+{
+ struct dev_mc_list *curr;
+ unsigned long mc_filter[2];
+ unsigned int i, bitnr;
+ struct macb *bp = netdev_priv(dev);
+
+ mc_filter[0] = mc_filter[1] = 0;
+
+ curr = dev->mc_list;
+ for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
+ if (!curr) break; /* unexpected end of list */
+
+ bitnr = hash_get_index(curr->dmi_addr);
+ mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
+ }
+
+ macb_writel(bp, HRB, mc_filter[0]);
+ macb_writel(bp, HRT, mc_filter[1]);
+}
+
+/*
+ * Enable/Disable promiscuous and multicast modes.
+ */
+static void macb_set_rx_mode(struct net_device *dev)
+{
+ unsigned long cfg;
struct macb *bp = netdev_priv(dev);
- /* Set some reasonable default settings */
- macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_CSMA | ADVERTISE_ALL);
- macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR,
- (BMCR_SPEED100 | BMCR_ANENABLE
- | BMCR_ANRESTART | BMCR_FULLDPLX));
+ cfg = macb_readl(bp, NCFGR);
+
+ if (dev->flags & IFF_PROMISC)
+ /* Enable promiscuous mode */
+ cfg |= MACB_BIT(CAF);
+ else if (dev->flags & (~IFF_PROMISC))
+ /* Disable promiscuous mode */
+ cfg &= ~MACB_BIT(CAF);
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Enable all multicast mode */
+ macb_writel(bp, HRB, -1);
+ macb_writel(bp, HRT, -1);
+ cfg |= MACB_BIT(NCFGR_MTI);
+ } else if (dev->mc_count > 0) {
+ /* Enable specific multicasts */
+ macb_sethashtable(dev);
+ cfg |= MACB_BIT(NCFGR_MTI);
+ } else if (dev->flags & (~IFF_ALLMULTI)) {
+ /* Disable all multicast mode */
+ macb_writel(bp, HRB, 0);
+ macb_writel(bp, HRT, 0);
+ cfg &= ~MACB_BIT(NCFGR_MTI);
+ }
+
+ macb_writel(bp, NCFGR, cfg);
}
static int macb_open(struct net_device *dev)
@@ -797,6 +922,10 @@ static int macb_open(struct net_device *dev)
dev_dbg(&bp->pdev->dev, "open\n");
+ /* if the phy is not yet register, retry later*/
+ if (!bp->phy_dev)
+ return -EAGAIN;
+
if (!is_valid_ether_addr(dev->dev_addr))
return -EADDRNOTAVAIL;
@@ -810,12 +939,11 @@ static int macb_open(struct net_device *dev)
macb_init_rings(bp);
macb_init_hw(bp);
- macb_init_phy(dev);
- macb_check_media(bp, 1, 1);
- netif_start_queue(dev);
+ /* schedule a link state check */
+ phy_start(bp->phy_dev);
- schedule_delayed_work(&bp->periodic_task, HZ);
+ netif_start_queue(dev);
return 0;
}
@@ -825,10 +953,11 @@ static int macb_close(struct net_device *dev)
struct macb *bp = netdev_priv(dev);
unsigned long flags;
- cancel_rearming_delayed_work(&bp->periodic_task);
-
netif_stop_queue(dev);
+ if (bp->phy_dev)
+ phy_stop(bp->phy_dev);
+
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
netif_carrier_off(dev);
@@ -845,6 +974,9 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
struct net_device_stats *nstat = &bp->stats;
struct macb_stats *hwstat = &bp->hw_stats;
+ /* read stats from hardware */
+ macb_update_stats(bp);
+
/* Convert HW stats into netdevice stats */
nstat->rx_errors = (hwstat->rx_fcs_errors +
hwstat->rx_align_errors +
@@ -882,18 +1014,27 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct macb *bp = netdev_priv(dev);
+ struct phy_device *phydev = bp->phy_dev;
- return mii_ethtool_gset(&bp->mii, cmd);
+ if (!phydev)
+ return -ENODEV;
+
+ return phy_ethtool_gset(phydev, cmd);
}
static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct macb *bp = netdev_priv(dev);
+ struct phy_device *phydev = bp->phy_dev;
+
+ if (!phydev)
+ return -ENODEV;
- return mii_ethtool_sset(&bp->mii, cmd);
+ return phy_ethtool_sset(phydev, cmd);
}
-static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void macb_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
struct macb *bp = netdev_priv(dev);
@@ -902,104 +1043,34 @@ static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf
strcpy(info->bus_info, bp->pdev->dev.bus_id);
}
-static int macb_nway_reset(struct net_device *dev)
-{
- struct macb *bp = netdev_priv(dev);
- return mii_nway_restart(&bp->mii);
-}
-
static struct ethtool_ops macb_ethtool_ops = {
.get_settings = macb_get_settings,
.set_settings = macb_set_settings,
.get_drvinfo = macb_get_drvinfo,
- .nway_reset = macb_nway_reset,
.get_link = ethtool_op_get_link,
};
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct macb *bp = netdev_priv(dev);
+ struct phy_device *phydev = bp->phy_dev;
if (!netif_running(dev))
return -EINVAL;
- return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
-}
-
-static ssize_t macb_mii_show(const struct device *_dev, char *buf,
- unsigned long addr)
-{
- struct net_device *dev = to_net_dev(_dev);
- struct macb *bp = netdev_priv(dev);
- ssize_t ret = -EINVAL;
-
- if (netif_running(dev)) {
- int value;
- value = macb_mdio_read(dev, bp->mii.phy_id, addr);
- ret = sprintf(buf, "0x%04x\n", (uint16_t)value);
- }
-
- return ret;
-}
-
-#define MII_ENTRY(name, addr) \
-static ssize_t show_##name(struct device *_dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return macb_mii_show(_dev, buf, addr); \
-} \
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
-
-MII_ENTRY(bmcr, MII_BMCR);
-MII_ENTRY(bmsr, MII_BMSR);
-MII_ENTRY(physid1, MII_PHYSID1);
-MII_ENTRY(physid2, MII_PHYSID2);
-MII_ENTRY(advertise, MII_ADVERTISE);
-MII_ENTRY(lpa, MII_LPA);
-MII_ENTRY(expansion, MII_EXPANSION);
-
-static struct attribute *macb_mii_attrs[] = {
- &dev_attr_bmcr.attr,
- &dev_attr_bmsr.attr,
- &dev_attr_physid1.attr,
- &dev_attr_physid2.attr,
- &dev_attr_advertise.attr,
- &dev_attr_lpa.attr,
- &dev_attr_expansion.attr,
- NULL,
-};
-
-static struct attribute_group macb_mii_group = {
- .name = "mii",
- .attrs = macb_mii_attrs,
-};
-
-static void macb_unregister_sysfs(struct net_device *net)
-{
- struct device *_dev = &net->dev;
+ if (!phydev)
+ return -ENODEV;
- sysfs_remove_group(&_dev->kobj, &macb_mii_group);
+ return phy_mii_ioctl(phydev, if_mii(rq), cmd);
}
-static int macb_register_sysfs(struct net_device *net)
-{
- struct device *_dev = &net->dev;
- int ret;
-
- ret = sysfs_create_group(&_dev->kobj, &macb_mii_group);
- if (ret)
- printk(KERN_WARNING
- "%s: sysfs mii attribute registration failed: %d\n",
- net->name, ret);
- return ret;
-}
static int __devinit macb_probe(struct platform_device *pdev)
{
struct eth_platform_data *pdata;
struct resource *regs;
struct net_device *dev;
struct macb *bp;
+ struct phy_device *phydev;
unsigned long pclk_hz;
u32 config;
int err = -ENXIO;
@@ -1073,6 +1144,7 @@ static int __devinit macb_probe(struct platform_device *pdev)
dev->stop = macb_close;
dev->hard_start_xmit = macb_start_xmit;
dev->get_stats = macb_get_stats;
+ dev->set_multicast_list = macb_set_rx_mode;
dev->do_ioctl = macb_ioctl;
dev->poll = macb_poll;
dev->weight = 64;
@@ -1080,10 +1152,6 @@ static int __devinit macb_probe(struct platform_device *pdev)
dev->base_addr = regs->start;
- INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
- mutex_init(&bp->mdio_mutex);
- init_completion(&bp->mdio_complete);
-
/* Set MII management clock divider */
pclk_hz = clk_get_rate(bp->pclk);
if (pclk_hz <= 20000000)
@@ -1096,20 +1164,9 @@ static int __devinit macb_probe(struct platform_device *pdev)
config = MACB_BF(CLK, MACB_CLK_DIV64);
macb_writel(bp, NCFGR, config);
- bp->mii.dev = dev;
- bp->mii.mdio_read = macb_mdio_read;
- bp->mii.mdio_write = macb_mdio_write;
- bp->mii.phy_id_mask = 0x1f;
- bp->mii.reg_num_mask = 0x1f;
-
macb_get_hwaddr(bp);
- err = macb_phy_probe(bp);
- if (err) {
- dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");
- goto err_out_free_irq;
- }
-
pdata = pdev->dev.platform_data;
+
if (pdata && pdata->is_rmii)
#if defined(CONFIG_ARCH_AT91)
macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
@@ -1131,9 +1188,11 @@ static int __devinit macb_probe(struct platform_device *pdev)
goto err_out_free_irq;
}
- platform_set_drvdata(pdev, dev);
+ if (macb_mii_init(bp) != 0) {
+ goto err_out_unregister_netdev;
+ }
- macb_register_sysfs(dev);
+ platform_set_drvdata(pdev, dev);
printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
"(%02x:%02x:%02x:%02x:%02x:%02x)\n",
@@ -1141,8 +1200,15 @@ static int __devinit macb_probe(struct platform_device *pdev)
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ phydev = bp->phy_dev;
+ printk(KERN_INFO "%s: attached PHY driver [%s] "
+ "(mii_bus:phy_addr=%s, irq=%d)\n",
+ dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
return 0;
+err_out_unregister_netdev:
+ unregister_netdev(dev);
err_out_free_irq:
free_irq(dev->irq, dev);
err_out_iounmap:
@@ -1153,7 +1219,9 @@ err_out_disable_clocks:
clk_put(bp->hclk);
#endif
clk_disable(bp->pclk);
+#ifndef CONFIG_ARCH_AT91
err_out_put_pclk:
+#endif
clk_put(bp->pclk);
err_out_free_dev:
free_netdev(dev);
@@ -1171,7 +1239,8 @@ static int __devexit macb_remove(struct platform_device *pdev)
if (dev) {
bp = netdev_priv(dev);
- macb_unregister_sysfs(dev);
+ mdiobus_unregister(&bp->mii_bus);
+ kfree(bp->mii_bus.irq);
unregister_netdev(dev);
free_irq(dev->irq, dev);
iounmap(bp->regs);
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index b3bb2182edd1..4e3283ebd97c 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -383,11 +383,11 @@ struct macb {
unsigned int rx_pending, tx_pending;
- struct delayed_work periodic_task;
-
- struct mutex mdio_mutex;
- struct completion mdio_complete;
- struct mii_if_info mii;
+ struct mii_bus mii_bus;
+ struct phy_device *phy_dev;
+ unsigned int link;
+ unsigned int speed;
+ unsigned int duplex;
};
#endif /* _MACB_H */
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index e1732c164a40..deca65330b0f 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1060,7 +1060,6 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
struct myri10ge_tx_buf *tx = &mgp->tx;
struct sk_buff *skb;
int idx, len;
- int limit = 0;
while (tx->pkt_done != mcp_index) {
idx = tx->done & tx->mask;
@@ -1091,11 +1090,6 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
bus), len,
PCI_DMA_TODEVICE);
}
-
- /* limit potential for livelock by only handling
- * 2 full tx rings per call */
- if (unlikely(++limit > 2 * tx->mask))
- break;
}
/* start the queue if we've stopped it */
if (netif_queue_stopped(mgp->dev)
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 3450051ae56b..6bb48ba80964 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -671,7 +671,7 @@ static ssize_t natsemi_show_##_name(struct device *dev, \
#define NATSEMI_CREATE_FILE(_dev, _name) \
device_create_file(&_dev->dev, &dev_attr_##_name)
#define NATSEMI_REMOVE_FILE(_dev, _name) \
- device_create_file(&_dev->dev, &dev_attr_##_name)
+ device_remove_file(&_dev->dev, &dev_attr_##_name)
NATSEMI_ATTR(dspcfg_workaround);
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 995c0a5d4066..cfdeaf7aa163 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -669,10 +669,15 @@ static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state)
static int ne2k_pci_resume (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
+ int rc;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
- pci_enable_device(pdev);
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
NS8390_init(dev, 1);
netif_device_attach(dev);
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 982a9010c7a9..bb6896ae3151 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -2338,7 +2338,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
{
struct skb_shared_info *info = skb_shinfo(skb);
unsigned int cur_frag, entry;
- struct TxDesc *txd;
+ struct TxDesc * uninitialized_var(txd);
entry = tp->cur_tx;
for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 58bbfdd4f901..afef6c0c59fe 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -796,12 +796,14 @@ static void free_shared_mem(struct s2io_nic *nic)
struct mac_info *mac_control;
struct config_param *config;
int lst_size, lst_per_page;
- struct net_device *dev = nic->dev;
+ struct net_device *dev;
int page_num = 0;
if (!nic)
return;
+ dev = nic->dev;
+
mac_control = &nic->mac_control;
config = &nic->config;
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
new file mode 100644
index 000000000000..8a667c13faef
--- /dev/null
+++ b/drivers/net/sunvnet.c
@@ -0,0 +1,1164 @@
+/* sunvnet.c: Sun LDOM Virtual Network Driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#include "sunvnet.h"
+
+#define DRV_MODULE_NAME "sunvnet"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "June 25, 2007"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual network driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* Ordered from largest major to lowest */
+static struct vio_version vnet_versions[] = {
+ { .major = 1, .minor = 0 },
+};
+
+static inline u32 vnet_tx_dring_avail(struct vio_dring_state *dr)
+{
+ return vio_dring_avail(dr, VNET_TX_RING_SIZE);
+}
+
+static int vnet_handle_unknown(struct vnet_port *port, void *arg)
+{
+ struct vio_msg_tag *pkt = arg;
+
+ printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+ pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+ printk(KERN_ERR PFX "Resetting connection.\n");
+
+ ldc_disconnect(port->vio.lp);
+
+ return -ECONNRESET;
+}
+
+static int vnet_send_attr(struct vio_driver_state *vio)
+{
+ struct vnet_port *port = to_vnet_port(vio);
+ struct net_device *dev = port->vp->dev;
+ struct vio_net_attr_info pkt;
+ int i;
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.tag.type = VIO_TYPE_CTRL;
+ pkt.tag.stype = VIO_SUBTYPE_INFO;
+ pkt.tag.stype_env = VIO_ATTR_INFO;
+ pkt.tag.sid = vio_send_sid(vio);
+ pkt.xfer_mode = VIO_DRING_MODE;
+ pkt.addr_type = VNET_ADDR_ETHERMAC;
+ pkt.ack_freq = 0;
+ for (i = 0; i < 6; i++)
+ pkt.addr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
+ pkt.mtu = ETH_FRAME_LEN;
+
+ viodbg(HS, "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
+ "ackfreq[%u] mtu[%llu]\n",
+ pkt.xfer_mode, pkt.addr_type,
+ (unsigned long long) pkt.addr,
+ pkt.ack_freq,
+ (unsigned long long) pkt.mtu);
+
+ return vio_ldc_send(vio, &pkt, sizeof(pkt));
+}
+
+static int handle_attr_info(struct vio_driver_state *vio,
+ struct vio_net_attr_info *pkt)
+{
+ viodbg(HS, "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] "
+ "ackfreq[%u] mtu[%llu]\n",
+ pkt->xfer_mode, pkt->addr_type,
+ (unsigned long long) pkt->addr,
+ pkt->ack_freq,
+ (unsigned long long) pkt->mtu);
+
+ pkt->tag.sid = vio_send_sid(vio);
+
+ if (pkt->xfer_mode != VIO_DRING_MODE ||
+ pkt->addr_type != VNET_ADDR_ETHERMAC ||
+ pkt->mtu != ETH_FRAME_LEN) {
+ viodbg(HS, "SEND NET ATTR NACK\n");
+
+ pkt->tag.stype = VIO_SUBTYPE_NACK;
+
+ (void) vio_ldc_send(vio, pkt, sizeof(*pkt));
+
+ return -ECONNRESET;
+ } else {
+ viodbg(HS, "SEND NET ATTR ACK\n");
+
+ pkt->tag.stype = VIO_SUBTYPE_ACK;
+
+ return vio_ldc_send(vio, pkt, sizeof(*pkt));
+ }
+
+}
+
+static int handle_attr_ack(struct vio_driver_state *vio,
+ struct vio_net_attr_info *pkt)
+{
+ viodbg(HS, "GOT NET ATTR ACK\n");
+
+ return 0;
+}
+
+static int handle_attr_nack(struct vio_driver_state *vio,
+ struct vio_net_attr_info *pkt)
+{
+ viodbg(HS, "GOT NET ATTR NACK\n");
+
+ return -ECONNRESET;
+}
+
+static int vnet_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+ struct vio_net_attr_info *pkt = arg;
+
+ switch (pkt->tag.stype) {
+ case VIO_SUBTYPE_INFO:
+ return handle_attr_info(vio, pkt);
+
+ case VIO_SUBTYPE_ACK:
+ return handle_attr_ack(vio, pkt);
+
+ case VIO_SUBTYPE_NACK:
+ return handle_attr_nack(vio, pkt);
+
+ default:
+ return -ECONNRESET;
+ }
+}
+
+static void vnet_handshake_complete(struct vio_driver_state *vio)
+{
+ struct vio_dring_state *dr;
+
+ dr = &vio->drings[VIO_DRIVER_RX_RING];
+ dr->snd_nxt = dr->rcv_nxt = 1;
+
+ dr = &vio->drings[VIO_DRIVER_TX_RING];
+ dr->snd_nxt = dr->rcv_nxt = 1;
+}
+
+/* The hypervisor interface that implements copying to/from imported
+ * memory from another domain requires that copies are done to 8-byte
+ * aligned buffers, and that the lengths of such copies are also 8-byte
+ * multiples.
+ *
+ * So we align skb->data to an 8-byte multiple and pad-out the data
+ * area so we can round the copy length up to the next multiple of
+ * 8 for the copy.
+ *
+ * The transmitter puts the actual start of the packet 6 bytes into
+ * the buffer it sends over, so that the IP headers after the ethernet
+ * header are aligned properly. These 6 bytes are not in the descriptor
+ * length, they are simply implied. This offset is represented using
+ * the VNET_PACKET_SKIP macro.
+ */
+static struct sk_buff *alloc_and_align_skb(struct net_device *dev,
+ unsigned int len)
+{
+ struct sk_buff *skb = netdev_alloc_skb(dev, len+VNET_PACKET_SKIP+8+8);
+ unsigned long addr, off;
+
+ if (unlikely(!skb))
+ return NULL;
+
+ addr = (unsigned long) skb->data;
+ off = ((addr + 7UL) & ~7UL) - addr;
+ if (off)
+ skb_reserve(skb, off);
+
+ return skb;
+}
+
+static int vnet_rx_one(struct vnet_port *port, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies)
+{
+ struct net_device *dev = port->vp->dev;
+ unsigned int copy_len;
+ struct sk_buff *skb;
+ int err;
+
+ err = -EMSGSIZE;
+ if (unlikely(len < ETH_ZLEN || len > ETH_FRAME_LEN)) {
+ dev->stats.rx_length_errors++;
+ goto out_dropped;
+ }
+
+ skb = alloc_and_align_skb(dev, len);
+ err = -ENOMEM;
+ if (unlikely(!skb)) {
+ dev->stats.rx_missed_errors++;
+ goto out_dropped;
+ }
+
+ copy_len = (len + VNET_PACKET_SKIP + 7U) & ~7U;
+ skb_put(skb, copy_len);
+ err = ldc_copy(port->vio.lp, LDC_COPY_IN,
+ skb->data, copy_len, 0,
+ cookies, ncookies);
+ if (unlikely(err < 0)) {
+ dev->stats.rx_frame_errors++;
+ goto out_free_skb;
+ }
+
+ skb_pull(skb, VNET_PACKET_SKIP);
+ skb_trim(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
+
+ netif_rx(skb);
+
+ return 0;
+
+out_free_skb:
+ kfree_skb(skb);
+
+out_dropped:
+ dev->stats.rx_dropped++;
+ return err;
+}
+
+static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
+ u32 start, u32 end, u8 vio_dring_state)
+{
+ struct vio_dring_data hdr = {
+ .tag = {
+ .type = VIO_TYPE_DATA,
+ .stype = VIO_SUBTYPE_ACK,
+ .stype_env = VIO_DRING_DATA,
+ .sid = vio_send_sid(&port->vio),
+ },
+ .dring_ident = dr->ident,
+ .start_idx = start,
+ .end_idx = end,
+ .state = vio_dring_state,
+ };
+ int err, delay;
+
+ hdr.seq = dr->snd_nxt;
+ delay = 1;
+ do {
+ err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+ if (err > 0) {
+ dr->snd_nxt++;
+ break;
+ }
+ udelay(delay);
+ if ((delay <<= 1) > 128)
+ delay = 128;
+ } while (err == -EAGAIN);
+
+ return err;
+}
+
+static u32 next_idx(u32 idx, struct vio_dring_state *dr)
+{
+ if (++idx == dr->num_entries)
+ idx = 0;
+ return idx;
+}
+
+static u32 prev_idx(u32 idx, struct vio_dring_state *dr)
+{
+ if (idx == 0)
+ idx = dr->num_entries - 1;
+ else
+ idx--;
+
+ return idx;
+}
+
+static struct vio_net_desc *get_rx_desc(struct vnet_port *port,
+ struct vio_dring_state *dr,
+ u32 index)
+{
+ struct vio_net_desc *desc = port->vio.desc_buf;
+ int err;
+
+ err = ldc_get_dring_entry(port->vio.lp, desc, dr->entry_size,
+ (index * dr->entry_size),
+ dr->cookies, dr->ncookies);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ return desc;
+}
+
+static int put_rx_desc(struct vnet_port *port,
+ struct vio_dring_state *dr,
+ struct vio_net_desc *desc,
+ u32 index)
+{
+ int err;
+
+ err = ldc_put_dring_entry(port->vio.lp, desc, dr->entry_size,
+ (index * dr->entry_size),
+ dr->cookies, dr->ncookies);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int vnet_walk_rx_one(struct vnet_port *port,
+ struct vio_dring_state *dr,
+ u32 index, int *needs_ack)
+{
+ struct vio_net_desc *desc = get_rx_desc(port, dr, index);
+ struct vio_driver_state *vio = &port->vio;
+ int err;
+
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%lx:%lx]\n",
+ desc->hdr.state, desc->hdr.ack,
+ desc->size, desc->ncookies,
+ desc->cookies[0].cookie_addr,
+ desc->cookies[0].cookie_size);
+
+ if (desc->hdr.state != VIO_DESC_READY)
+ return 1;
+ err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies);
+ if (err == -ECONNRESET)
+ return err;
+ desc->hdr.state = VIO_DESC_DONE;
+ err = put_rx_desc(port, dr, desc, index);
+ if (err < 0)
+ return err;
+ *needs_ack = desc->hdr.ack;
+ return 0;
+}
+
+static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
+ u32 start, u32 end)
+{
+ struct vio_driver_state *vio = &port->vio;
+ int ack_start = -1, ack_end = -1;
+
+ end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr);
+
+ viodbg(DATA, "vnet_walk_rx start[%08x] end[%08x]\n", start, end);
+
+ while (start != end) {
+ int ack = 0, err = vnet_walk_rx_one(port, dr, start, &ack);
+ if (err == -ECONNRESET)
+ return err;
+ if (err != 0)
+ break;
+ if (ack_start == -1)
+ ack_start = start;
+ ack_end = start;
+ start = next_idx(start, dr);
+ if (ack && start != end) {
+ err = vnet_send_ack(port, dr, ack_start, ack_end,
+ VIO_DRING_ACTIVE);
+ if (err == -ECONNRESET)
+ return err;
+ ack_start = -1;
+ }
+ }
+ if (unlikely(ack_start == -1))
+ ack_start = ack_end = prev_idx(start, dr);
+ return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED);
+}
+
+static int vnet_rx(struct vnet_port *port, void *msgbuf)
+{
+ struct vio_dring_data *pkt = msgbuf;
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING];
+ struct vio_driver_state *vio = &port->vio;
+
+ viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016lx] rcv_nxt[%016lx]\n",
+ pkt->tag.stype_env, pkt->seq, dr->rcv_nxt);
+
+ if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+ return 0;
+ if (unlikely(pkt->seq != dr->rcv_nxt)) {
+ printk(KERN_ERR PFX "RX out of sequence seq[0x%lx] "
+ "rcv_nxt[0x%lx]\n", pkt->seq, dr->rcv_nxt);
+ return 0;
+ }
+
+ dr->rcv_nxt++;
+
+ /* XXX Validate pkt->start_idx and pkt->end_idx XXX */
+
+ return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx);
+}
+
+static int idx_is_pending(struct vio_dring_state *dr, u32 end)
+{
+ u32 idx = dr->cons;
+ int found = 0;
+
+ while (idx != dr->prod) {
+ if (idx == end) {
+ found = 1;
+ break;
+ }
+ idx = next_idx(idx, dr);
+ }
+ return found;
+}
+
+static int vnet_ack(struct vnet_port *port, void *msgbuf)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data *pkt = msgbuf;
+ struct net_device *dev;
+ struct vnet *vp;
+ u32 end;
+
+ if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+ return 0;
+
+ end = pkt->end_idx;
+ if (unlikely(!idx_is_pending(dr, end)))
+ return 0;
+
+ dr->cons = next_idx(end, dr);
+
+ vp = port->vp;
+ dev = vp->dev;
+ if (unlikely(netif_queue_stopped(dev) &&
+ vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr)))
+ return 1;
+
+ return 0;
+}
+
+static int vnet_nack(struct vnet_port *port, void *msgbuf)
+{
+ /* XXX just reset or similar XXX */
+ return 0;
+}
+
+static void maybe_tx_wakeup(struct vnet *vp)
+{
+ struct net_device *dev = vp->dev;
+
+ netif_tx_lock(dev);
+ if (likely(netif_queue_stopped(dev))) {
+ struct vnet_port *port;
+ int wake = 1;
+
+ list_for_each_entry(port, &vp->port_list, list) {
+ struct vio_dring_state *dr;
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ if (vnet_tx_dring_avail(dr) <
+ VNET_TX_WAKEUP_THRESH(dr)) {
+ wake = 0;
+ break;
+ }
+ }
+ if (wake)
+ netif_wake_queue(dev);
+ }
+ netif_tx_unlock(dev);
+}
+
+static void vnet_event(void *arg, int event)
+{
+ struct vnet_port *port = arg;
+ struct vio_driver_state *vio = &port->vio;
+ unsigned long flags;
+ int tx_wakeup, err;
+
+ spin_lock_irqsave(&vio->lock, flags);
+
+ if (unlikely(event == LDC_EVENT_RESET ||
+ event == LDC_EVENT_UP)) {
+ vio_link_state_change(vio, event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+
+ return;
+ }
+
+ if (unlikely(event != LDC_EVENT_DATA_READY)) {
+ printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+ return;
+ }
+
+ tx_wakeup = err = 0;
+ while (1) {
+ union {
+ struct vio_msg_tag tag;
+ u64 raw[8];
+ } msgbuf;
+
+ err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+ if (unlikely(err < 0)) {
+ if (err == -ECONNRESET)
+ vio_conn_reset(vio);
+ break;
+ }
+ if (err == 0)
+ break;
+ viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+ msgbuf.tag.type,
+ msgbuf.tag.stype,
+ msgbuf.tag.stype_env,
+ msgbuf.tag.sid);
+ err = vio_validate_sid(vio, &msgbuf.tag);
+ if (err < 0)
+ break;
+
+ if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+ if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) {
+ err = vnet_rx(port, &msgbuf);
+ } else if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) {
+ err = vnet_ack(port, &msgbuf);
+ if (err > 0)
+ tx_wakeup |= err;
+ } else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK) {
+ err = vnet_nack(port, &msgbuf);
+ }
+ } else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+ err = vio_control_pkt_engine(vio, &msgbuf);
+ if (err)
+ break;
+ } else {
+ err = vnet_handle_unknown(port, &msgbuf);
+ }
+ if (err == -ECONNRESET)
+ break;
+ }
+ spin_unlock(&vio->lock);
+ if (unlikely(tx_wakeup && err != -ECONNRESET))
+ maybe_tx_wakeup(port->vp);
+ local_irq_restore(flags);
+}
+
+static int __vnet_tx_trigger(struct vnet_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data hdr = {
+ .tag = {
+ .type = VIO_TYPE_DATA,
+ .stype = VIO_SUBTYPE_INFO,
+ .stype_env = VIO_DRING_DATA,
+ .sid = vio_send_sid(&port->vio),
+ },
+ .dring_ident = dr->ident,
+ .start_idx = dr->prod,
+ .end_idx = (u32) -1,
+ };
+ int err, delay;
+
+ hdr.seq = dr->snd_nxt;
+ delay = 1;
+ do {
+ err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+ if (err > 0) {
+ dr->snd_nxt++;
+ break;
+ }
+ udelay(delay);
+ if ((delay <<= 1) > 128)
+ delay = 128;
+ } while (err == -EAGAIN);
+
+ return err;
+}
+
+struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+ unsigned int hash = vnet_hashfn(skb->data);
+ struct hlist_head *hp = &vp->port_hash[hash];
+ struct hlist_node *n;
+ struct vnet_port *port;
+
+ hlist_for_each_entry(port, n, hp, hash) {
+ if (!compare_ether_addr(port->raddr, skb->data))
+ return port;
+ }
+ port = NULL;
+ if (!list_empty(&vp->port_list))
+ port = list_entry(vp->port_list.next, struct vnet_port, list);
+
+ return port;
+}
+
+struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+ struct vnet_port *ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ ret = __tx_port_find(vp, skb);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ return ret;
+}
+
+static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct vnet *vp = netdev_priv(dev);
+ struct vnet_port *port = tx_port_find(vp, skb);
+ struct vio_dring_state *dr;
+ struct vio_net_desc *d;
+ unsigned long flags;
+ unsigned int len;
+ void *tx_buf;
+ int i, err;
+
+ if (unlikely(!port))
+ goto out_dropped;
+
+ spin_lock_irqsave(&port->vio.lock, flags);
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+ if (!netif_queue_stopped(dev)) {
+ netif_stop_queue(dev);
+
+ /* This is a hard error, log it. */
+ printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+ "queue awake!\n", dev->name);
+ dev->stats.tx_errors++;
+ }
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
+ d = vio_dring_cur(dr);
+
+ tx_buf = port->tx_bufs[dr->prod].buf;
+ skb_copy_from_linear_data(skb, tx_buf + VNET_PACKET_SKIP, skb->len);
+
+ len = skb->len;
+ if (len < ETH_ZLEN) {
+ len = ETH_ZLEN;
+ memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len);
+ }
+
+ d->hdr.ack = VIO_ACK_ENABLE;
+ d->size = len;
+ d->ncookies = port->tx_bufs[dr->prod].ncookies;
+ for (i = 0; i < d->ncookies; i++)
+ d->cookies[i] = port->tx_bufs[dr->prod].cookies[i];
+
+ /* This has to be a non-SMP write barrier because we are writing
+ * to memory which is shared with the peer LDOM.
+ */
+ wmb();
+
+ d->hdr.state = VIO_DESC_READY;
+
+ err = __vnet_tx_trigger(port);
+ if (unlikely(err < 0)) {
+ printk(KERN_INFO PFX "%s: TX trigger error %d\n",
+ dev->name, err);
+ d->hdr.state = VIO_DESC_FREE;
+ dev->stats.tx_carrier_errors++;
+ goto out_dropped_unlock;
+ }
+
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+ dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
+ if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+ netif_stop_queue(dev);
+ if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
+ netif_wake_queue(dev);
+ }
+
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+
+ dev_kfree_skb(skb);
+
+ dev->trans_start = jiffies;
+ return NETDEV_TX_OK;
+
+out_dropped_unlock:
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+
+out_dropped:
+ dev_kfree_skb(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+}
+
+static void vnet_tx_timeout(struct net_device *dev)
+{
+ /* XXX Implement me XXX */
+}
+
+static int vnet_open(struct net_device *dev)
+{
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int vnet_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ return 0;
+}
+
+static void vnet_set_rx_mode(struct net_device *dev)
+{
+ /* XXX Implement multicast support XXX */
+}
+
+static int vnet_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu != ETH_DATA_LEN)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static int vnet_set_mac_addr(struct net_device *dev, void *p)
+{
+ return -EINVAL;
+}
+
+static void vnet_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_MODULE_NAME);
+ strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static u32 vnet_get_msglevel(struct net_device *dev)
+{
+ struct vnet *vp = netdev_priv(dev);
+ return vp->msg_enable;
+}
+
+static void vnet_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct vnet *vp = netdev_priv(dev);
+ vp->msg_enable = value;
+}
+
+static const struct ethtool_ops vnet_ethtool_ops = {
+ .get_drvinfo = vnet_get_drvinfo,
+ .get_msglevel = vnet_get_msglevel,
+ .set_msglevel = vnet_set_msglevel,
+ .get_link = ethtool_op_get_link,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+static void vnet_port_free_tx_bufs(struct vnet_port *port)
+{
+ struct vio_dring_state *dr;
+ int i;
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ if (dr->base) {
+ ldc_free_exp_dring(port->vio.lp, dr->base,
+ (dr->entry_size * dr->num_entries),
+ dr->cookies, dr->ncookies);
+ dr->base = NULL;
+ dr->entry_size = 0;
+ dr->num_entries = 0;
+ dr->pending = 0;
+ dr->ncookies = 0;
+ }
+
+ for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+ void *buf = port->tx_bufs[i].buf;
+
+ if (!buf)
+ continue;
+
+ ldc_unmap(port->vio.lp,
+ port->tx_bufs[i].cookies,
+ port->tx_bufs[i].ncookies);
+
+ kfree(buf);
+ port->tx_bufs[i].buf = NULL;
+ }
+}
+
+static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
+{
+ struct vio_dring_state *dr;
+ unsigned long len;
+ int i, err, ncookies;
+ void *dring;
+
+ for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+ void *buf = kzalloc(ETH_FRAME_LEN + 8, GFP_KERNEL);
+ int map_len = (ETH_FRAME_LEN + 7) & ~7;
+
+ err = -ENOMEM;
+ if (!buf) {
+ printk(KERN_ERR "TX buffer allocation failure\n");
+ goto err_out;
+ }
+ err = -EFAULT;
+ if ((unsigned long)buf & (8UL - 1)) {
+ printk(KERN_ERR "TX buffer misaligned\n");
+ kfree(buf);
+ goto err_out;
+ }
+
+ err = ldc_map_single(port->vio.lp, buf, map_len,
+ port->tx_bufs[i].cookies, 2,
+ (LDC_MAP_SHADOW |
+ LDC_MAP_DIRECT |
+ LDC_MAP_RW));
+ if (err < 0) {
+ kfree(buf);
+ goto err_out;
+ }
+ port->tx_bufs[i].buf = buf;
+ port->tx_bufs[i].ncookies = err;
+ }
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+ len = (VNET_TX_RING_SIZE *
+ (sizeof(struct vio_net_desc) +
+ (sizeof(struct ldc_trans_cookie) * 2)));
+
+ ncookies = VIO_MAX_RING_COOKIES;
+ dring = ldc_alloc_exp_dring(port->vio.lp, len,
+ dr->cookies, &ncookies,
+ (LDC_MAP_SHADOW |
+ LDC_MAP_DIRECT |
+ LDC_MAP_RW));
+ if (IS_ERR(dring)) {
+ err = PTR_ERR(dring);
+ goto err_out;
+ }
+
+ dr->base = dring;
+ dr->entry_size = (sizeof(struct vio_net_desc) +
+ (sizeof(struct ldc_trans_cookie) * 2));
+ dr->num_entries = VNET_TX_RING_SIZE;
+ dr->prod = dr->cons = 0;
+ dr->pending = VNET_TX_RING_SIZE;
+ dr->ncookies = ncookies;
+
+ return 0;
+
+err_out:
+ vnet_port_free_tx_bufs(port);
+
+ return err;
+}
+
+static struct ldc_channel_config vnet_ldc_cfg = {
+ .event = vnet_event,
+ .mtu = 64,
+ .mode = LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vnet_vio_ops = {
+ .send_attr = vnet_send_attr,
+ .handle_attr = vnet_handle_attr,
+ .handshake_complete = vnet_handshake_complete,
+};
+
+const char *remote_macaddr_prop = "remote-mac-address";
+
+static int __devinit vnet_port_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ struct mdesc_handle *hp;
+ struct vnet_port *port;
+ unsigned long flags;
+ struct vnet *vp;
+ const u64 *rmac;
+ int len, i, err, switch_port;
+
+ vp = dev_get_drvdata(vdev->dev.parent);
+ if (!vp) {
+ printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
+ return -ENODEV;
+ }
+
+ hp = mdesc_grab();
+
+ rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
+ err = -ENODEV;
+ if (!rmac) {
+ printk(KERN_ERR PFX "Port lacks %s property.\n",
+ remote_macaddr_prop);
+ goto err_out_put_mdesc;
+ }
+
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!port) {
+ printk(KERN_ERR PFX "Cannot allocate vnet_port.\n");
+ goto err_out_put_mdesc;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff;
+
+ port->vp = vp;
+
+ err = vio_driver_init(&port->vio, vdev, VDEV_NETWORK,
+ vnet_versions, ARRAY_SIZE(vnet_versions),
+ &vnet_vio_ops, vp->dev->name);
+ if (err)
+ goto err_out_free_port;
+
+ err = vio_ldc_alloc(&port->vio, &vnet_ldc_cfg, port);
+ if (err)
+ goto err_out_free_port;
+
+ err = vnet_port_alloc_tx_bufs(port);
+ if (err)
+ goto err_out_free_ldc;
+
+ INIT_HLIST_NODE(&port->hash);
+ INIT_LIST_HEAD(&port->list);
+
+ switch_port = 0;
+ if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL)
+ switch_port = 1;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ if (switch_port)
+ list_add(&port->list, &vp->port_list);
+ else
+ list_add_tail(&port->list, &vp->port_list);
+ hlist_add_head(&port->hash, &vp->port_hash[vnet_hashfn(port->raddr)]);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ dev_set_drvdata(&vdev->dev, port);
+
+ printk(KERN_INFO "%s: PORT ( remote-mac ", vp->dev->name);
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", port->raddr[i], i == 5 ? ' ' : ':');
+ if (switch_port)
+ printk("switch-port ");
+ printk(")\n");
+
+ vio_port_up(&port->vio);
+
+ mdesc_release(hp);
+
+ return 0;
+
+err_out_free_ldc:
+ vio_ldc_free(&port->vio);
+
+err_out_free_port:
+ kfree(port);
+
+err_out_put_mdesc:
+ mdesc_release(hp);
+ return err;
+}
+
+static int vnet_port_remove(struct vio_dev *vdev)
+{
+ struct vnet_port *port = dev_get_drvdata(&vdev->dev);
+
+ if (port) {
+ struct vnet *vp = port->vp;
+ unsigned long flags;
+
+ del_timer_sync(&port->vio.timer);
+
+ spin_lock_irqsave(&vp->lock, flags);
+ list_del(&port->list);
+ hlist_del(&port->hash);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ vnet_port_free_tx_bufs(port);
+ vio_ldc_free(&port->vio);
+
+ dev_set_drvdata(&vdev->dev, NULL);
+
+ kfree(port);
+ }
+ return 0;
+}
+
+static struct vio_device_id vnet_port_match[] = {
+ {
+ .type = "vnet-port",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_port_driver = {
+ .id_table = vnet_port_match,
+ .probe = vnet_port_probe,
+ .remove = vnet_port_remove,
+ .driver = {
+ .name = "vnet_port",
+ .owner = THIS_MODULE,
+ }
+};
+
+const char *local_mac_prop = "local-mac-address";
+
+static int __devinit vnet_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ static int vnet_version_printed;
+ struct mdesc_handle *hp;
+ struct net_device *dev;
+ struct vnet *vp;
+ const u64 *mac;
+ int err, i, len;
+
+ if (vnet_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ hp = mdesc_grab();
+
+ mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len);
+ if (!mac) {
+ printk(KERN_ERR PFX "vnet lacks %s property.\n",
+ local_mac_prop);
+ err = -ENODEV;
+ goto err_out;
+ }
+
+ dev = alloc_etherdev(sizeof(*vp));
+ if (!dev) {
+ printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff;
+
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ SET_NETDEV_DEV(dev, &vdev->dev);
+
+ vp = netdev_priv(dev);
+
+ spin_lock_init(&vp->lock);
+ vp->dev = dev;
+ vp->vdev = vdev;
+
+ INIT_LIST_HEAD(&vp->port_list);
+ for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
+ INIT_HLIST_HEAD(&vp->port_hash[i]);
+
+ dev->open = vnet_open;
+ dev->stop = vnet_close;
+ dev->set_multicast_list = vnet_set_rx_mode;
+ dev->set_mac_address = vnet_set_mac_addr;
+ dev->tx_timeout = vnet_tx_timeout;
+ dev->ethtool_ops = &vnet_ethtool_ops;
+ dev->watchdog_timeo = VNET_TX_TIMEOUT;
+ dev->change_mtu = vnet_change_mtu;
+ dev->hard_start_xmit = vnet_start_xmit;
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register net device, "
+ "aborting.\n");
+ goto err_out_free_dev;
+ }
+
+ printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name);
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
+
+ dev_set_drvdata(&vdev->dev, vp);
+
+ mdesc_release(hp);
+
+ return 0;
+
+err_out_free_dev:
+ free_netdev(dev);
+
+err_out:
+ mdesc_release(hp);
+ return err;
+}
+
+static int vnet_remove(struct vio_dev *vdev)
+{
+
+ struct vnet *vp = dev_get_drvdata(&vdev->dev);
+
+ if (vp) {
+ /* XXX unregister port, or at least check XXX */
+ unregister_netdevice(vp->dev);
+ dev_set_drvdata(&vdev->dev, NULL);
+ }
+ return 0;
+}
+
+static struct vio_device_id vnet_match[] = {
+ {
+ .type = "network",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_driver = {
+ .id_table = vnet_match,
+ .probe = vnet_probe,
+ .remove = vnet_remove,
+ .driver = {
+ .name = "vnet",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init vnet_init(void)
+{
+ int err = vio_register_driver(&vnet_driver);
+
+ if (!err) {
+ err = vio_register_driver(&vnet_port_driver);
+ if (err)
+ vio_unregister_driver(&vnet_driver);
+ }
+
+ return err;
+}
+
+static void __exit vnet_exit(void)
+{
+ vio_unregister_driver(&vnet_port_driver);
+ vio_unregister_driver(&vnet_driver);
+}
+
+module_init(vnet_init);
+module_exit(vnet_exit);
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h
new file mode 100644
index 000000000000..1c887302d46d
--- /dev/null
+++ b/drivers/net/sunvnet.h
@@ -0,0 +1,70 @@
+#ifndef _SUNVNET_H
+#define _SUNVNET_H
+
+#define DESC_NCOOKIES(entry_size) \
+ ((entry_size) - sizeof(struct vio_net_desc))
+
+/* length of time before we decide the hardware is borked,
+ * and dev->tx_timeout() should be called to fix the problem
+ */
+#define VNET_TX_TIMEOUT (5 * HZ)
+
+#define VNET_TX_RING_SIZE 512
+#define VNET_TX_WAKEUP_THRESH(dr) ((dr)->pending / 4)
+
+/* VNET packets are sent in buffers with the first 6 bytes skipped
+ * so that after the ethernet header the IPv4/IPv6 headers are aligned
+ * properly.
+ */
+#define VNET_PACKET_SKIP 6
+
+struct vnet_tx_entry {
+ void *buf;
+ unsigned int ncookies;
+ struct ldc_trans_cookie cookies[2];
+};
+
+struct vnet;
+struct vnet_port {
+ struct vio_driver_state vio;
+
+ struct hlist_node hash;
+ u8 raddr[ETH_ALEN];
+
+ struct vnet *vp;
+
+ struct vnet_tx_entry tx_bufs[VNET_TX_RING_SIZE];
+
+ struct list_head list;
+};
+
+static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio)
+{
+ return container_of(vio, struct vnet_port, vio);
+}
+
+#define VNET_PORT_HASH_SIZE 16
+#define VNET_PORT_HASH_MASK (VNET_PORT_HASH_SIZE - 1)
+
+static inline unsigned int vnet_hashfn(u8 *mac)
+{
+ unsigned int val = mac[4] ^ mac[5];
+
+ return val & (VNET_PORT_HASH_MASK);
+}
+
+struct vnet {
+ /* Protects port_list and port_hash. */
+ spinlock_t lock;
+
+ struct net_device *dev;
+
+ u32 msg_enable;
+ struct vio_dev *vdev;
+
+ struct list_head port_list;
+
+ struct hlist_head port_hash[VNET_PORT_HASH_SIZE];
+};
+
+#endif /* _SUNVNET_H */
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 58d7e5d452fa..f83bb5cb0d3d 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3692,7 +3692,6 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
__u16 rcode, correlator;
int err = 0;
__u8 xframe = 1;
- __u16 tx_fstatus;
rmf->vl = SWAP_BYTES(rmf->vl);
if(rx_status & FCB_RX_STATUS_DA_MATCHED)
@@ -3783,7 +3782,9 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
}
break;
- case TX_FORWARD:
+ case TX_FORWARD: {
+ __u16 uninitialized_var(tx_fstatus);
+
if((rcode = smctr_rcv_tx_forward(dev, rmf))
!= POSITIVE_ACK)
{
@@ -3811,6 +3812,7 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
}
}
break;
+ }
/* Received MAC Frames Processed by CRS/REM/RPS. */
case RSP:
diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c
index bc62b012602b..943988ed01d8 100644
--- a/drivers/net/usb/cdc_subset.c
+++ b/drivers/net/usb/cdc_subset.c
@@ -305,6 +305,9 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
.driver_info = (unsigned long) &blob_info,
}, {
+ USB_DEVICE (0x1286, 0x8001), // "blob" bootloader
+ .driver_info = (unsigned long) &blob_info,
+}, {
// Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
// e.g. Gumstix, current OpenZaurus, ...
USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 4fc8681bc110..a3df09ee729f 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -61,7 +61,7 @@ config COSA
#
config LANMEDIA
tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
---help---
Driver for the following Lan Media family of serial boards:
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index ec1c556a47ca..5d8c78ee2cd9 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -2833,6 +2833,8 @@ static int clock_rate_calc(uclong rate, uclong clock, int *br_io)
int br, tc;
int br_pwr, error;
+ *br_io = 0;
+
if (rate == 0)
return (0);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 35eded7ffb2d..1cc18e787a65 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -595,8 +595,8 @@ recv_frame( struct net_device *dev )
u32 crc = CRC32_INITIAL;
- unsigned framelen, frameno, ack;
- unsigned is_first, frame_ok;
+ unsigned framelen = 0, frameno, ack;
+ unsigned is_first, frame_ok = 0;
if( check_fhdr( ioaddr, &framelen, &frameno, &ack, &is_first, &crc ) ) {
frame_ok = framelen > 4
@@ -604,8 +604,7 @@ recv_frame( struct net_device *dev )
: skip_tail( ioaddr, framelen, crc );
if( frame_ok )
interpret_ack( dev, ack );
- } else
- frame_ok = 0;
+ }
outb( inb( ioaddr + CSR0 ) ^ CT_ZER, ioaddr + CSR0 );
if( frame_ok ) {
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2d3a180dada0..ee1cc14db389 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -52,6 +52,8 @@
#include "airo.h"
+#define DRV_NAME "airo"
+
#ifdef CONFIG_PCI
static struct pci_device_id card_ids[] = {
{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
@@ -71,7 +73,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state);
static int airo_pci_resume(struct pci_dev *pdev);
static struct pci_driver airo_driver = {
- .name = "airo",
+ .name = DRV_NAME,
.id_table = card_ids,
.probe = airo_pci_probe,
.remove = __devexit_p(airo_pci_remove),
@@ -1092,7 +1094,7 @@ static int get_dec_u16( char *buffer, int *start, int limit );
static void OUT4500( struct airo_info *, u16 register, u16 value );
static unsigned short IN4500( struct airo_info *, u16 register );
static u16 setup_card(struct airo_info*, u8 *mac, int lock);
-static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );
+static int enable_MAC(struct airo_info *ai, int lock);
static void disable_MAC(struct airo_info *ai, int lock);
static void enable_interrupts(struct airo_info*);
static void disable_interrupts(struct airo_info*);
@@ -1250,7 +1252,7 @@ static int flashputbuf(struct airo_info *ai);
static int flashrestart(struct airo_info *ai,struct net_device *dev);
#define airo_print(type, name, fmt, args...) \
- { printk(type "airo(%s): " fmt "\n", name, ##args); }
+ printk(type DRV_NAME "(%s): " fmt "\n", name, ##args)
#define airo_print_info(name, fmt, args...) \
airo_print(KERN_INFO, name, fmt, ##args)
@@ -1926,28 +1928,54 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) {
return rc;
}
+static void try_auto_wep(struct airo_info *ai)
+{
+ if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
+ ai->expires = RUN_AT(3*HZ);
+ wake_up_interruptible(&ai->thr_wait);
+ }
+}
+
static int airo_open(struct net_device *dev) {
- struct airo_info *info = dev->priv;
- Resp rsp;
+ struct airo_info *ai = dev->priv;
+ int rc = 0;
- if (test_bit(FLAG_FLASHING, &info->flags))
+ if (test_bit(FLAG_FLASHING, &ai->flags))
return -EIO;
/* Make sure the card is configured.
* Wireless Extensions may postpone config changes until the card
* is open (to pipeline changes and speed-up card setup). If
* those changes are not yet commited, do it now - Jean II */
- if (test_bit (FLAG_COMMIT, &info->flags)) {
- disable_MAC(info, 1);
- writeConfigRid(info, 1);
+ if (test_bit(FLAG_COMMIT, &ai->flags)) {
+ disable_MAC(ai, 1);
+ writeConfigRid(ai, 1);
}
- if (info->wifidev != dev) {
+ if (ai->wifidev != dev) {
+ clear_bit(JOB_DIE, &ai->jobs);
+ ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
+ if (IS_ERR(ai->airo_thread_task))
+ return (int)PTR_ERR(ai->airo_thread_task);
+
+ rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (rc) {
+ airo_print_err(dev->name,
+ "register interrupt %d failed, rc %d",
+ dev->irq, rc);
+ set_bit(JOB_DIE, &ai->jobs);
+ kthread_stop(ai->airo_thread_task);
+ return rc;
+ }
+
/* Power on the MAC controller (which may have been disabled) */
- clear_bit(FLAG_RADIO_DOWN, &info->flags);
- enable_interrupts(info);
+ clear_bit(FLAG_RADIO_DOWN, &ai->flags);
+ enable_interrupts(ai);
+
+ try_auto_wep(ai);
}
- enable_MAC(info, &rsp, 1);
+ enable_MAC(ai, 1);
netif_start_queue(dev);
return 0;
@@ -2338,14 +2366,13 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
{
struct airo_info *ai = dev->priv;
struct sockaddr *addr = p;
- Resp rsp;
readConfigRid(ai, 1);
memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
set_bit (FLAG_COMMIT, &ai->flags);
disable_MAC(ai, 1);
writeConfigRid (ai, 1);
- enable_MAC(ai, &rsp, 1);
+ enable_MAC(ai, 1);
memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
if (ai->wifidev)
memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
@@ -2392,6 +2419,11 @@ static int airo_close(struct net_device *dev) {
disable_MAC(ai, 1);
#endif
disable_interrupts( ai );
+
+ free_irq(dev->irq, dev);
+
+ set_bit(JOB_DIE, &ai->jobs);
+ kthread_stop(ai->airo_thread_task);
}
return 0;
}
@@ -2403,7 +2435,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
set_bit(FLAG_RADIO_DOWN, &ai->flags);
disable_MAC(ai, 1);
disable_interrupts(ai);
- free_irq( dev->irq, dev );
takedown_proc_entry( dev, ai );
if (test_bit(FLAG_REGISTERED, &ai->flags)) {
unregister_netdev( dev );
@@ -2414,9 +2445,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
}
clear_bit(FLAG_REGISTERED, &ai->flags);
}
- set_bit(JOB_DIE, &ai->jobs);
- kthread_stop(ai->airo_thread_task);
-
/*
* Clean out tx queue
*/
@@ -2554,8 +2582,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
* 2) Map PCI memory for issueing commands.
* 3) Allocate memory (shared) to send and receive ethernet frames.
*/
-static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
- const char *name)
+static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
{
unsigned long mem_start, mem_len, aux_start, aux_len;
int rc = -1;
@@ -2569,35 +2596,35 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
aux_start = pci_resource_start(pci, 2);
aux_len = AUXMEMSIZE;
- if (!request_mem_region(mem_start, mem_len, name)) {
- airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
- (int)mem_start, (int)mem_len, name);
+ if (!request_mem_region(mem_start, mem_len, DRV_NAME)) {
+ airo_print_err("", "Couldn't get region %x[%x]",
+ (int)mem_start, (int)mem_len);
goto out;
}
- if (!request_mem_region(aux_start, aux_len, name)) {
- airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
- (int)aux_start, (int)aux_len, name);
+ if (!request_mem_region(aux_start, aux_len, DRV_NAME)) {
+ airo_print_err("", "Couldn't get region %x[%x]",
+ (int)aux_start, (int)aux_len);
goto free_region1;
}
ai->pcimem = ioremap(mem_start, mem_len);
if (!ai->pcimem) {
- airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
- (int)mem_start, (int)mem_len, name);
+ airo_print_err("", "Couldn't map region %x[%x]",
+ (int)mem_start, (int)mem_len);
goto free_region2;
}
ai->pciaux = ioremap(aux_start, aux_len);
if (!ai->pciaux) {
- airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
- (int)aux_start, (int)aux_len, name);
+ airo_print_err("", "Couldn't map region %x[%x]",
+ (int)aux_start, (int)aux_len);
goto free_memmap;
}
/* Reserve PKTSIZE for each fid and 2K for the Rids */
ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
if (!ai->shared) {
- airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
- PCI_SHARED_LEN);
+ airo_print_err("", "Couldn't alloc_consistent %d",
+ PCI_SHARED_LEN);
goto free_auxmap;
}
@@ -2742,7 +2769,7 @@ static int airo_networks_allocate(struct airo_info *ai)
kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
GFP_KERNEL);
if (!ai->networks) {
- airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
+ airo_print_warn("", "Out of memory allocating beacons");
return -ENOMEM;
}
@@ -2770,7 +2797,6 @@ static int airo_test_wpa_capable(struct airo_info *ai)
{
int status;
CapabilityRid cap_rid;
- const char *name = ai->dev->name;
status = readCapabilityRid(ai, &cap_rid, 1);
if (status != SUCCESS) return 0;
@@ -2778,12 +2804,12 @@ static int airo_test_wpa_capable(struct airo_info *ai)
/* Only firmware versions 5.30.17 or better can do WPA */
if ((cap_rid.softVer > 0x530)
|| ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
- airo_print_info(name, "WPA is supported.");
+ airo_print_info("", "WPA is supported.");
return 1;
}
/* No WPA support */
- airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17"
+ airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
" and greater support WPA. Detected %s)", cap_rid.prodVer);
return 0;
}
@@ -2797,23 +2823,19 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
int i, rc;
/* Create the network device object. */
- dev = alloc_etherdev(sizeof(*ai));
- if (!dev) {
+ dev = alloc_netdev(sizeof(*ai), "", ether_setup);
+ if (!dev) {
airo_print_err("", "Couldn't alloc_etherdev");
return NULL;
- }
- if (dev_alloc_name(dev, dev->name) < 0) {
- airo_print_err("", "Couldn't get name!");
- goto err_out_free;
}
ai = dev->priv;
ai->wifidev = NULL;
- ai->flags = 0;
+ ai->flags = 1 << FLAG_RADIO_DOWN;
ai->jobs = 0;
ai->dev = dev;
if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
- airo_print_dbg(dev->name, "Found an MPI350 card");
+ airo_print_dbg("", "Found an MPI350 card");
set_bit(FLAG_MPI, &ai->flags);
}
spin_lock_init(&ai->aux_lock);
@@ -2821,14 +2843,11 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
ai->config.len = 0;
ai->pci = pci;
init_waitqueue_head (&ai->thr_wait);
- ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
- if (IS_ERR(ai->airo_thread_task))
- goto err_out_free;
ai->tfm = NULL;
add_airo_dev(ai);
if (airo_networks_allocate (ai))
- goto err_out_thr;
+ goto err_out_free;
airo_networks_initialize (ai);
/* The Airo-specific entries in the device structure. */
@@ -2851,27 +2870,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
dev->base_addr = port;
SET_NETDEV_DEV(dev, dmdev);
+ SET_MODULE_OWNER(dev);
reset_card (dev, 1);
msleep(400);
- rc = request_irq( dev->irq, airo_interrupt, IRQF_SHARED, dev->name, dev );
- if (rc) {
- airo_print_err(dev->name, "register interrupt %d failed, rc %d",
- irq, rc);
- goto err_out_nets;
- }
if (!is_pcmcia) {
- if (!request_region( dev->base_addr, 64, dev->name )) {
+ if (!request_region(dev->base_addr, 64, DRV_NAME)) {
rc = -EBUSY;
airo_print_err(dev->name, "Couldn't request region");
- goto err_out_irq;
+ goto err_out_nets;
}
}
if (test_bit(FLAG_MPI,&ai->flags)) {
- if (mpi_map_card(ai, pci, dev->name)) {
- airo_print_err(dev->name, "Could not map memory");
+ if (mpi_map_card(ai, pci)) {
+ airo_print_err("", "Could not map memory");
goto err_out_res;
}
}
@@ -2899,6 +2913,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
}
+ strcpy(dev->name, "eth%d");
rc = register_netdev(dev);
if (rc) {
airo_print_err(dev->name, "Couldn't register_netdev");
@@ -2921,8 +2936,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
if (setup_proc_entry(dev, dev->priv) < 0)
goto err_out_wifi;
- netif_start_queue(dev);
- SET_MODULE_OWNER(dev);
return dev;
err_out_wifi:
@@ -2940,14 +2953,9 @@ err_out_map:
err_out_res:
if (!is_pcmcia)
release_region( dev->base_addr, 64 );
-err_out_irq:
- free_irq(dev->irq, dev);
err_out_nets:
airo_networks_free(ai);
-err_out_thr:
del_airo_dev(ai);
- set_bit(JOB_DIE, &ai->jobs);
- kthread_stop(ai->airo_thread_task);
err_out_free:
free_netdev(dev);
return NULL;
@@ -3078,7 +3086,8 @@ static int airo_thread(void *data) {
struct net_device *dev = data;
struct airo_info *ai = dev->priv;
int locked;
-
+
+ set_freezable();
while(1) {
/* make swsusp happy with our thread */
try_to_freeze();
@@ -3529,9 +3538,11 @@ static u16 IN4500( struct airo_info *ai, u16 reg ) {
return rc;
}
-static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
+static int enable_MAC(struct airo_info *ai, int lock)
+{
int rc;
- Cmd cmd;
+ Cmd cmd;
+ Resp rsp;
/* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
* FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
@@ -3547,7 +3558,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
if (!test_bit(FLAG_ENABLED, &ai->flags)) {
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAC_ENABLE;
- rc = issuecommand(ai, &cmd, rsp);
+ rc = issuecommand(ai, &cmd, &rsp);
if (rc == SUCCESS)
set_bit(FLAG_ENABLED, &ai->flags);
} else
@@ -3557,8 +3568,12 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
up(&ai->sem);
if (rc)
- airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
- __FUNCTION__, rc);
+ airo_print_err(ai->dev->name, "Cannot enable MAC");
+ else if ((rsp.status & 0xFF00) != 0) {
+ airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, "
+ "rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2);
+ rc = ERROR;
+ }
return rc;
}
@@ -3902,12 +3917,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if ( status != SUCCESS ) return ERROR;
}
- status = enable_MAC(ai, &rsp, lock);
- if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
- airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
- " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+ status = enable_MAC(ai, lock);
+ if (status != SUCCESS)
return ERROR;
- }
/* Grab the initial wep key, we gotta save it for auto_wep */
rc = readWepKeyRid(ai, &wkr, 1, lock);
@@ -3919,10 +3931,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
rc = readWepKeyRid(ai, &wkr, 0, lock);
} while(lastindex != wkr.kindex);
- if (auto_wep) {
- ai->expires = RUN_AT(3*HZ);
- wake_up_interruptible(&ai->thr_wait);
- }
+ try_auto_wep(ai);
return SUCCESS;
}
@@ -4004,7 +4013,7 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
}
if ( !(max_tries--) ) {
airo_print_err(ai->dev->name,
- "airo: BAP setup error too many retries\n");
+ "BAP setup error too many retries\n");
return ERROR;
}
// -- PC4500 missed it, try again
@@ -5152,7 +5161,6 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
SsidRid SSID_rid;
- Resp rsp;
int i;
int offset = 0;
@@ -5177,7 +5185,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
SSID_rid.len = sizeof(SSID_rid);
disable_MAC(ai, 1);
writeSsidRid(ai, &SSID_rid, 1);
- enable_MAC(ai, &rsp, 1);
+ enable_MAC(ai, 1);
}
static inline u8 hexVal(char c) {
@@ -5193,7 +5201,6 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
APListRid APList_rid;
- Resp rsp;
int i;
if ( !data->writelen ) return;
@@ -5218,18 +5225,17 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
}
disable_MAC(ai, 1);
writeAPListRid(ai, &APList_rid, 1);
- enable_MAC(ai, &rsp, 1);
+ enable_MAC(ai, 1);
}
/* This function wraps PC4500_writerid with a MAC disable */
static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
int len, int dummy ) {
int rc;
- Resp rsp;
disable_MAC(ai, 1);
rc = PC4500_writerid(ai, rid, rid_data, len, 1);
- enable_MAC(ai, &rsp, 1);
+ enable_MAC(ai, 1);
return rc;
}
@@ -5260,7 +5266,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
const char *key, u16 keylen, int perm, int lock ) {
static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
WepKeyRid wkr;
- Resp rsp;
memset(&wkr, 0, sizeof(wkr));
if (keylen == 0) {
@@ -5280,7 +5285,7 @@ static int set_wep_key(struct airo_info *ai, u16 index,
if (perm) disable_MAC(ai, lock);
writeWepKeyRid(ai, &wkr, perm, lock);
- if (perm) enable_MAC(ai, &rsp, lock);
+ if (perm) enable_MAC(ai, lock);
return 0;
}
@@ -5548,7 +5553,6 @@ static int proc_close( struct inode *inode, struct file *file )
changed. */
static void timer_func( struct net_device *dev ) {
struct airo_info *apriv = dev->priv;
- Resp rsp;
/* We don't have a link so try changing the authtype */
readConfigRid(apriv, 0);
@@ -5575,7 +5579,7 @@ static void timer_func( struct net_device *dev ) {
}
set_bit (FLAG_COMMIT, &apriv->flags);
writeConfigRid(apriv, 0);
- enable_MAC(apriv, &rsp, 0);
+ enable_MAC(apriv, 0);
up(&apriv->sem);
/* Schedule check to see if the change worked */
@@ -5597,8 +5601,10 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
else
dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
- if (!dev)
+ if (!dev) {
+ pci_disable_device(pdev);
return -ENODEV;
+ }
pci_set_drvdata(pdev, dev);
return 0;
@@ -5610,6 +5616,8 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev)
airo_print_info(dev->name, "Unregistering...");
stop_airo_card(dev, 1);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
}
static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -5646,7 +5654,6 @@ static int airo_pci_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct airo_info *ai = dev->priv;
- Resp rsp;
pci_power_t prev_state = pdev->current_state;
pci_set_power_state(pdev, PCI_D0);
@@ -5679,7 +5686,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
ai->APList = NULL;
}
writeConfigRid(ai, 0);
- enable_MAC(ai, &rsp, 0);
+ enable_MAC(ai, 0);
ai->power = PMSG_ON;
netif_device_attach(dev);
netif_wake_queue(dev);
@@ -5903,7 +5910,6 @@ static int airo_set_essid(struct net_device *dev,
char *extra)
{
struct airo_info *local = dev->priv;
- Resp rsp;
SsidRid SSID_rid; /* SSIDs */
/* Reload the list of current SSID */
@@ -5935,7 +5941,7 @@ static int airo_set_essid(struct net_device *dev,
/* Write it to the card */
disable_MAC(local, 1);
writeSsidRid(local, &SSID_rid, 1);
- enable_MAC(local, &rsp, 1);
+ enable_MAC(local, 1);
return 0;
}
@@ -6000,7 +6006,7 @@ static int airo_set_wap(struct net_device *dev,
memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
disable_MAC(local, 1);
writeAPListRid(local, &APList_rid, 1);
- enable_MAC(local, &rsp, 1);
+ enable_MAC(local, 1);
}
return 0;
}
@@ -7454,7 +7460,6 @@ static int airo_config_commit(struct net_device *dev,
char *extra) /* NULL */
{
struct airo_info *local = dev->priv;
- Resp rsp;
if (!test_bit (FLAG_COMMIT, &local->flags))
return 0;
@@ -7479,7 +7484,7 @@ static int airo_config_commit(struct net_device *dev,
if (down_interruptible(&local->sem))
return -ERESTARTSYS;
writeConfigRid(local, 0);
- enable_MAC(local, &rsp, 0);
+ enable_MAC(local, 0);
if (test_bit (FLAG_RESET, &local->flags))
airo_set_promisc(local);
else
@@ -7746,7 +7751,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
unsigned char *iobuf;
int len;
struct airo_info *ai = dev->priv;
- Resp rsp;
if (test_bit(FLAG_FLASHING, &ai->flags))
return -EIO;
@@ -7758,7 +7762,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
if (test_bit(FLAG_COMMIT, &ai->flags)) {
disable_MAC (ai, 1);
writeConfigRid (ai, 1);
- enable_MAC (ai, &rsp, 1);
+ enable_MAC(ai, 1);
}
break;
case AIROGSLIST: ridcode = RID_SSID; break;
@@ -7815,7 +7819,6 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
struct airo_info *ai = dev->priv;
int ridcode;
int enabled;
- Resp rsp;
static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
unsigned char *iobuf;
@@ -7849,7 +7852,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
* same with MAC off
*/
case AIROPMACON:
- if (enable_MAC(ai, &rsp, 1) != 0)
+ if (enable_MAC(ai, 1) != 0)
return -EIO;
return 0;
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index d51daf87450f..072ede71e575 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1768,7 +1768,8 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
if (priv->stop_rf_kill) {
priv->stop_rf_kill = 0;
- queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ round_jiffies(HZ));
}
deferred = 1;
@@ -2098,7 +2099,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
/* Make sure the RF Kill check timer is running */
priv->stop_rf_kill = 0;
cancel_delayed_work(&priv->rf_kill);
- queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ));
}
static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
@@ -4233,7 +4234,8 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
/* Make sure the RF_KILL check timer is running */
priv->stop_rf_kill = 0;
cancel_delayed_work(&priv->rf_kill);
- queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ round_jiffies(HZ));
} else
schedule_reset(priv);
}
@@ -5969,7 +5971,8 @@ static void ipw2100_rf_kill(struct work_struct *work)
if (rf_kill_active(priv)) {
IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
if (!priv->stop_rf_kill)
- queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
+ queue_delayed_work(priv->workqueue, &priv->rf_kill,
+ round_jiffies(HZ));
goto exit_unlock;
}
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 7cb2052a55a5..aa32a97380ec 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1751,7 +1751,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
/* Make sure the RF_KILL check timer is running */
cancel_delayed_work(&priv->rf_kill);
queue_delayed_work(priv->workqueue, &priv->rf_kill,
- 2 * HZ);
+ round_jiffies(2 * HZ));
} else
queue_work(priv->workqueue, &priv->up);
}
@@ -4690,7 +4690,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
else if (priv->config & CFG_BACKGROUND_SCAN
&& priv->status & STATUS_ASSOCIATED)
queue_delayed_work(priv->workqueue,
- &priv->request_scan, HZ);
+ &priv->request_scan,
+ round_jiffies(HZ));
/* Send an empty event to user space.
* We don't send the received data on the event because
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 13f6528abb00..4a8f5dc70239 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -240,7 +240,7 @@ static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
if (*enable)
penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
else
- penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
+ penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
}
lbs_deb_leave(LBS_DEB_CMD);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 4a59306a3f05..9f366242c392 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -613,6 +613,7 @@ static int wlan_service_main_thread(void *data)
init_waitqueue_entry(&wait, current);
+ set_freezable();
for (;;) {
lbs_deb_thread( "main-thread 111: intcounter=%d "
"currenttxskb=%p dnld_sent=%d\n",
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 88d9d2d787d5..769c86fb9509 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -439,7 +439,6 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
ret = 0;
done:
- skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}
diff --git a/drivers/net/wireless/libertas/version.h b/drivers/net/wireless/libertas/version.h
deleted file mode 100644
index 8b137891791f..000000000000
--- a/drivers/net/wireless/libertas/version.h
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index f42b796b5e47..2fcc3bf21081 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1719,9 +1719,6 @@ static int wlan_set_encodeext(struct net_device *dev,
pkey->type = KEY_TYPE_ID_TKIP;
} else if (alg == IW_ENCODE_ALG_CCMP) {
pkey->type = KEY_TYPE_ID_AES;
- } else {
- ret = -EINVAL;
- goto out;
}
/* If WPA isn't enabled yet, do that now */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 283be4a70524..585f5996d292 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -1853,7 +1853,6 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
islpci_private *priv = netdev_priv(ndev);
struct islpci_acl *acl = &priv->acl;
struct mac_entry *entry;
- struct list_head *ptr;
struct sockaddr *addr = (struct sockaddr *) extra;
if (addr->sa_family != ARPHRD_ETHER)
@@ -1861,11 +1860,9 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
if (down_interruptible(&acl->sem))
return -ERESTARTSYS;
- for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
- entry = list_entry(ptr, struct mac_entry, _list);
-
+ list_for_each_entry(entry, &acl->mac_list, _list) {
if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
- list_del(ptr);
+ list_del(&entry->_list);
acl->size--;
kfree(entry);
up(&acl->sem);
@@ -1883,7 +1880,6 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
islpci_private *priv = netdev_priv(ndev);
struct islpci_acl *acl = &priv->acl;
struct mac_entry *entry;
- struct list_head *ptr;
struct sockaddr *dst = (struct sockaddr *) extra;
dwrq->length = 0;
@@ -1891,9 +1887,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
if (down_interruptible(&acl->sem))
return -ERESTARTSYS;
- for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
- entry = list_entry(ptr, struct mac_entry, _list);
-
+ list_for_each_entry(entry, &acl->mac_list, _list) {
memcpy(dst->sa_data, entry->addr, ETH_ALEN);
dst->sa_family = ARPHRD_ETHER;
dwrq->length++;
@@ -1960,7 +1954,6 @@ prism54_get_policy(struct net_device *ndev, struct iw_request_info *info,
static int
prism54_mac_accept(struct islpci_acl *acl, char *mac)
{
- struct list_head *ptr;
struct mac_entry *entry;
int res = 0;
@@ -1972,8 +1965,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
return 1;
}
- for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
- entry = list_entry(ptr, struct mac_entry, _list);
+ list_for_each_entry(entry, &acl->mac_list, _list) {
if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
res = 1;
break;
@@ -2216,11 +2208,9 @@ prism54_wpa_bss_ie_init(islpci_private *priv)
void
prism54_wpa_bss_ie_clean(islpci_private *priv)
{
- struct list_head *ptr, *n;
+ struct islpci_bss_wpa_ie *bss, *n;
- list_for_each_safe(ptr, n, &priv->bss_wpa_list) {
- struct islpci_bss_wpa_ie *bss;
- bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+ list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) {
kfree(bss);
}
}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index e25a09f1b068..efc41207780e 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -67,7 +67,7 @@ static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
msleep(2);
}
-static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg82, reg84;
@@ -106,7 +106,7 @@ void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
struct rtl8187_priv *priv = dev->priv;
if (priv->asic_rev)
- rtl8225_write_8051(dev, addr, data);
+ rtl8225_write_8051(dev, addr, cpu_to_le16(data));
else
rtl8225_write_bitbang(dev, addr, data);
}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 5b624bfc01a6..c39f1984b84d 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -49,8 +49,9 @@ void zd_chip_clear(struct zd_chip *chip)
ZD_MEMCLEAR(chip, sizeof(*chip));
}
-static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
+static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
{
+ u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr;
return scnprintf(buffer, size, "%02x-%02x-%02x",
addr[0], addr[1], addr[2]);
}
@@ -61,10 +62,10 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
int i = 0;
i = scnprintf(buffer, size, "zd1211%s chip ",
- chip->is_zd1211b ? "b" : "");
+ zd_chip_is_zd1211b(chip) ? "b" : "");
i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
i += scnprintf(buffer+i, size-i, " ");
- i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
+ i += scnprint_mac_oui(chip, buffer+i, size-i);
i += scnprintf(buffer+i, size-i, " ");
i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
@@ -366,64 +367,9 @@ error:
return r;
}
-static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr,
- const zd_addr_t *addr)
-{
- int r;
- u32 parts[2];
-
- r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2);
- if (r) {
- dev_dbg_f(zd_chip_dev(chip),
- "error: couldn't read e2p macs. Error number %d\n", r);
- return r;
- }
-
- mac_addr[0] = parts[0];
- mac_addr[1] = parts[0] >> 8;
- mac_addr[2] = parts[0] >> 16;
- mac_addr[3] = parts[0] >> 24;
- mac_addr[4] = parts[1];
- mac_addr[5] = parts[1] >> 8;
-
- return 0;
-}
-
-static int read_e2p_mac_addr(struct zd_chip *chip)
-{
- static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 };
-
- ZD_ASSERT(mutex_is_locked(&chip->mutex));
- return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr);
-}
-
/* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and
* CR_MAC_ADDR_P2 must be overwritten
*/
-void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
- mutex_lock(&chip->mutex);
- memcpy(mac_addr, chip->e2p_mac, ETH_ALEN);
- mutex_unlock(&chip->mutex);
-}
-
-static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
- static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 };
- return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr);
-}
-
-int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
-{
- int r;
-
- dev_dbg_f(zd_chip_dev(chip), "\n");
- mutex_lock(&chip->mutex);
- r = read_mac_addr(chip, mac_addr);
- mutex_unlock(&chip->mutex);
- return r;
-}
-
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
{
int r;
@@ -444,12 +390,6 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
mutex_lock(&chip->mutex);
r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
-#ifdef DEBUG
- {
- u8 tmp[ETH_ALEN];
- read_mac_addr(chip, tmp);
- }
-#endif /* DEBUG */
mutex_unlock(&chip->mutex);
return r;
}
@@ -809,7 +749,7 @@ out:
static int hw_reset_phy(struct zd_chip *chip)
{
- return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) :
+ return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) :
zd1211_hw_reset_phy(chip);
}
@@ -874,7 +814,7 @@ static int hw_init_hmac(struct zd_chip *chip)
if (r)
return r;
- return chip->is_zd1211b ?
+ return zd_chip_is_zd1211b(chip) ?
zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
}
@@ -1136,8 +1076,15 @@ static int read_fw_regs_offset(struct zd_chip *chip)
return 0;
}
+/* Read mac address using pre-firmware interface */
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr)
+{
+ dev_dbg_f(zd_chip_dev(chip), "\n");
+ return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr,
+ ETH_ALEN);
+}
-int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
+int zd_chip_init_hw(struct zd_chip *chip)
{
int r;
u8 rf_type;
@@ -1145,7 +1092,6 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
dev_dbg_f(zd_chip_dev(chip), "\n");
mutex_lock(&chip->mutex);
- chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0;
#ifdef DEBUG
r = test_init(chip);
@@ -1201,10 +1147,6 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
goto out;
#endif /* DEBUG */
- r = read_e2p_mac_addr(chip);
- if (r)
- goto out;
-
r = read_cal_int_tables(chip);
if (r)
goto out;
@@ -1259,7 +1201,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
r = update_pwr_int(chip, channel);
if (r)
return r;
- if (chip->is_zd1211b) {
+ if (zd_chip_is_zd1211b(chip)) {
static const struct zd_ioreq16 ioreqs[] = {
{ CR69, 0x28 },
{},
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 79d0288c193a..f4698576ab71 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -704,7 +704,6 @@ struct zd_chip {
struct mutex mutex;
/* Base address of FW_REG_ registers */
zd_addr_t fw_regs_base;
- u8 e2p_mac[ETH_ALEN];
/* EepSetPoint in the vendor driver */
u8 pwr_cal_values[E2P_CHANNEL_COUNT];
/* integration values in the vendor driver */
@@ -715,7 +714,7 @@ struct zd_chip {
unsigned int pa_type:4,
patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
new_phy_layout:1, al2230s_bit:1,
- is_zd1211b:1, supports_tx_led:1;
+ supports_tx_led:1;
};
static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -734,9 +733,15 @@ void zd_chip_init(struct zd_chip *chip,
struct net_device *netdev,
struct usb_interface *intf);
void zd_chip_clear(struct zd_chip *chip);
-int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
+int zd_chip_init_hw(struct zd_chip *chip);
int zd_chip_reset(struct zd_chip *chip);
+static inline int zd_chip_is_zd1211b(struct zd_chip *chip)
+{
+ return chip->usb.is_zd1211b;
+}
+
static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
const zd_addr_t *addresses,
unsigned int count)
@@ -825,8 +830,6 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
}
u8 zd_chip_get_channel(struct zd_chip *chip);
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
-void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
-int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
int zd_chip_switch_radio_on(struct zd_chip *chip);
int zd_chip_switch_radio_off(struct zd_chip *chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 6753d240c168..f6c487aa8246 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -86,38 +86,46 @@ out:
return r;
}
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
+int zd_mac_preinit_hw(struct zd_mac *mac)
{
int r;
- struct zd_chip *chip = &mac->chip;
u8 addr[ETH_ALEN];
+
+ r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
+ if (r)
+ return r;
+
+ memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
+ return 0;
+}
+
+int zd_mac_init_hw(struct zd_mac *mac)
+{
+ int r;
+ struct zd_chip *chip = &mac->chip;
u8 default_regdomain;
r = zd_chip_enable_int(chip);
if (r)
goto out;
- r = zd_chip_init_hw(chip, device_type);
+ r = zd_chip_init_hw(chip);
if (r)
goto disable_int;
- zd_get_e2p_mac_addr(chip, addr);
- r = zd_write_mac_addr(chip, addr);
- if (r)
- goto disable_int;
ZD_ASSERT(!irqs_disabled());
- spin_lock_irq(&mac->lock);
- memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
- spin_unlock_irq(&mac->lock);
r = zd_read_regdomain(chip, &default_regdomain);
if (r)
goto disable_int;
if (!zd_regdomain_supported(default_regdomain)) {
- dev_dbg_f(zd_mac_dev(mac),
- "Regulatory Domain %#04x is not supported.\n",
- default_regdomain);
- r = -EINVAL;
- goto disable_int;
+ /* The vendor driver overrides the regulatory domain and
+ * allowed channel registers and unconditionally restricts
+ * available channels to 1-11 everywhere. Match their
+ * questionable behaviour only for regdomains which we don't
+ * recognise. */
+ dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
+ "%#04x. Defaulting to FCC.\n", default_regdomain);
+ default_regdomain = ZD_REGDOMAIN_FCC;
}
spin_lock_irq(&mac->lock);
mac->regdomain = mac->default_regdomain = default_regdomain;
@@ -164,14 +172,25 @@ int zd_mac_open(struct net_device *netdev)
{
struct zd_mac *mac = zd_netdev_mac(netdev);
struct zd_chip *chip = &mac->chip;
+ struct zd_usb *usb = &chip->usb;
int r;
+ if (!usb->initialized) {
+ r = zd_usb_init_hw(usb);
+ if (r)
+ goto out;
+ }
+
tasklet_enable(&mac->rx_tasklet);
r = zd_chip_enable_int(chip);
if (r < 0)
goto out;
+ r = zd_write_mac_addr(chip, netdev->dev_addr);
+ if (r)
+ goto disable_int;
+
r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
if (r < 0)
goto disable_int;
@@ -251,9 +270,11 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p)
dev_dbg_f(zd_mac_dev(mac),
"Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data));
- r = zd_write_mac_addr(chip, addr->sa_data);
- if (r)
- return r;
+ if (netdev->flags & IFF_UP) {
+ r = zd_write_mac_addr(chip, addr->sa_data);
+ if (r)
+ return r;
+ }
spin_lock_irqsave(&mac->lock, flags);
memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -855,7 +876,7 @@ static int fill_ctrlset(struct zd_mac *mac,
/* ZD1211B: Computing the length difference this way, gives us
* flexibility to compute the packet length.
*/
- cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ?
+ cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
packet_length - frag_len : packet_length);
/*
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index faf4c7828d4e..9f9344eb50f9 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -189,7 +189,8 @@ int zd_mac_init(struct zd_mac *mac,
struct usb_interface *intf);
void zd_mac_clear(struct zd_mac *mac);
-int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
+int zd_mac_preinit_hw(struct zd_mac *mac);
+int zd_mac_init_hw(struct zd_mac *mac);
int zd_mac_open(struct net_device *netdev);
int zd_mac_stop(struct net_device *netdev);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 7407409b60b1..abe5d38f7f4d 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -34,7 +34,7 @@ static const char * const rfs[] = {
[AL2210_RF] = "AL2210_RF",
[MAXIM_NEW_RF] = "MAXIM_NEW_RF",
[UW2453_RF] = "UW2453_RF",
- [UNKNOWN_A_RF] = "UNKNOWN_A_RF",
+ [AL2230S_RF] = "AL2230S_RF",
[RALINK_RF] = "RALINK_RF",
[INTERSIL_RF] = "INTERSIL_RF",
[RF2959_RF] = "RF2959_RF",
@@ -77,6 +77,7 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
r = zd_rf_init_rf2959(rf);
break;
case AL2230_RF:
+ case AL2230S_RF:
r = zd_rf_init_al2230(rf);
break;
case AL7230B_RF:
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index c6dfd8227f6e..30502f26b71c 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -26,7 +26,7 @@
#define AL2210_RF 0x7
#define MAXIM_NEW_RF 0x8
#define UW2453_RF 0x9
-#define UNKNOWN_A_RF 0xa
+#define AL2230S_RF 0xa
#define RALINK_RF 0xb
#define INTERSIL_RF 0xc
#define RF2959_RF 0xd
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index e7a4ecf7b6e2..006774de3202 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -21,6 +21,8 @@
#include "zd_usb.h"
#include "zd_chip.h"
+#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
+
static const u32 zd1211_al2230_table[][3] = {
RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
@@ -176,7 +178,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
if (r)
return r;
- if (chip->al2230s_bit) {
+ if (IS_AL2230S(chip)) {
r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
ARRAY_SIZE(ioreqs_init_al2230s));
if (r)
@@ -188,7 +190,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
return r;
/* improve band edge for AL2230S */
- if (chip->al2230s_bit)
+ if (IS_AL2230S(chip))
r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
else
r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
@@ -314,7 +316,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
if (r)
return r;
- if (chip->al2230s_bit) {
+ if (IS_AL2230S(chip)) {
r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
ARRAY_SIZE(ioreqs_init_al2230s));
if (r)
@@ -328,7 +330,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
if (r)
return r;
- if (chip->al2230s_bit)
+ if (IS_AL2230S(chip))
r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
else
r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
@@ -422,7 +424,7 @@ int zd_rf_init_al2230(struct zd_rf *rf)
struct zd_chip *chip = zd_rf_to_chip(rf);
rf->switch_radio_off = al2230_switch_radio_off;
- if (chip->is_zd1211b) {
+ if (zd_chip_is_zd1211b(chip)) {
rf->init_hw = zd1211b_al2230_init_hw;
rf->set_channel = zd1211b_al2230_set_channel;
rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index f4e8b6ada854..73d0bb26f810 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -473,7 +473,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
- if (chip->is_zd1211b) {
+ if (zd_chip_is_zd1211b(chip)) {
rf->init_hw = zd1211b_al7230b_init_hw;
rf->switch_radio_on = zd1211b_al7230b_switch_radio_on;
rf->set_channel = zd1211b_al7230b_set_channel;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
index 2d736bdf707c..cc70d40684ea 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
@@ -265,7 +265,7 @@ int zd_rf_init_rf2959(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
- if (chip->is_zd1211b) {
+ if (zd_chip_is_zd1211b(chip)) {
dev_err(zd_chip_dev(chip),
"RF2959 is currently not supported for ZD1211B"
" devices\n");
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
index 414e40d571ab..857dcf3eae61 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -486,7 +486,7 @@ static int uw2453_switch_radio_on(struct zd_rf *rf)
if (r)
return r;
- if (chip->is_zd1211b)
+ if (zd_chip_is_zd1211b(chip))
ioreqs[1].value = 0x7f;
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index ca24299a26c6..28d41a29d7b1 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -71,6 +71,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
/* "Driverless" devices that need ejecting */
{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
@@ -195,26 +196,27 @@ static u16 get_word(const void *data, u16 offset)
return le16_to_cpu(p[offset]);
}
-static char *get_fw_name(char *buffer, size_t size, u8 device_type,
+static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
const char* postfix)
{
scnprintf(buffer, size, "%s%s",
- device_type == DEVICE_ZD1211B ?
+ usb->is_zd1211b ?
FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
postfix);
return buffer;
}
-static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
+static int handle_version_mismatch(struct zd_usb *usb,
const struct firmware *ub_fw)
{
+ struct usb_device *udev = zd_usb_to_usbdev(usb);
const struct firmware *ur_fw = NULL;
int offset;
int r = 0;
char fw_name[128];
r = request_fw_file(&ur_fw,
- get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"),
+ get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
&udev->dev);
if (r)
goto error;
@@ -237,11 +239,12 @@ error:
return r;
}
-static int upload_firmware(struct usb_device *udev, u8 device_type)
+static int upload_firmware(struct zd_usb *usb)
{
int r;
u16 fw_bcdDevice;
u16 bcdDevice;
+ struct usb_device *udev = zd_usb_to_usbdev(usb);
const struct firmware *ub_fw = NULL;
const struct firmware *uph_fw = NULL;
char fw_name[128];
@@ -249,7 +252,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
bcdDevice = get_bcdDevice(udev);
r = request_fw_file(&ub_fw,
- get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"),
+ get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
&udev->dev);
if (r)
goto error;
@@ -264,7 +267,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
dev_warn(&udev->dev, "device has old bootcode, please "
"report success or failure\n");
- r = handle_version_mismatch(udev, device_type, ub_fw);
+ r = handle_version_mismatch(usb, ub_fw);
if (r)
goto error;
} else {
@@ -275,7 +278,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
r = request_fw_file(&uph_fw,
- get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"),
+ get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
&udev->dev);
if (r)
goto error;
@@ -294,6 +297,30 @@ error:
return r;
}
+/* Read data from device address space using "firmware interface" which does
+ * not require firmware to be loaded. */
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
+{
+ int r;
+ struct usb_device *udev = zd_usb_to_usbdev(usb);
+
+ r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
+ data, len, 5000);
+ if (r < 0) {
+ dev_err(&udev->dev,
+ "read over firmware interface failed: %d\n", r);
+ return r;
+ } else if (r != len) {
+ dev_err(&udev->dev,
+ "incomplete read over firmware interface: %d/%d\n",
+ r, len);
+ return -EIO;
+ }
+
+ return 0;
+}
+
#define urb_dev(urb) (&(urb)->dev->dev)
static inline void handle_regs_int(struct urb *urb)
@@ -920,9 +947,42 @@ static int eject_installer(struct usb_interface *intf)
return 0;
}
+int zd_usb_init_hw(struct zd_usb *usb)
+{
+ int r;
+ struct zd_mac *mac = zd_usb_to_mac(usb);
+
+ dev_dbg_f(zd_usb_dev(usb), "\n");
+
+ r = upload_firmware(usb);
+ if (r) {
+ dev_err(zd_usb_dev(usb),
+ "couldn't load firmware. Error number %d\n", r);
+ return r;
+ }
+
+ r = usb_reset_configuration(zd_usb_to_usbdev(usb));
+ if (r) {
+ dev_dbg_f(zd_usb_dev(usb),
+ "couldn't reset configuration. Error number %d\n", r);
+ return r;
+ }
+
+ r = zd_mac_init_hw(mac);
+ if (r) {
+ dev_dbg_f(zd_usb_dev(usb),
+ "couldn't initialize mac. Error number %d\n", r);
+ return r;
+ }
+
+ usb->initialized = 1;
+ return 0;
+}
+
static int probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int r;
+ struct zd_usb *usb;
struct usb_device *udev = interface_to_usbdev(intf);
struct net_device *netdev = NULL;
@@ -950,26 +1010,10 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
}
- r = upload_firmware(udev, id->driver_info);
- if (r) {
- dev_err(&intf->dev,
- "couldn't load firmware. Error number %d\n", r);
- goto error;
- }
+ usb = &zd_netdev_mac(netdev)->chip.usb;
+ usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
- r = usb_reset_configuration(udev);
- if (r) {
- dev_dbg_f(&intf->dev,
- "couldn't reset configuration. Error number %d\n", r);
- goto error;
- }
-
- /* At this point the interrupt endpoint is not generally enabled. We
- * save the USB bandwidth until the network device is opened. But
- * notify that the initialization of the MAC will require the
- * interrupts to be temporary enabled.
- */
- r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info);
+ r = zd_mac_preinit_hw(zd_netdev_mac(netdev));
if (r) {
dev_dbg_f(&intf->dev,
"couldn't initialize mac. Error number %d\n", r);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 506ea6a74393..961a7a12ad68 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -188,6 +188,7 @@ struct zd_usb {
struct zd_usb_rx rx;
struct zd_usb_tx tx;
struct usb_interface *intf;
+ u8 is_zd1211b:1, initialized:1;
};
#define zd_usb_dev(usb) (&usb->intf->dev)
@@ -236,6 +237,8 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len);
+
extern struct workqueue_struct *zd_workqueue;
#endif /* _ZD_USB_H */
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index a68b3b3761a2..a728a7cd2fc8 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/dma-mapping.h>
#include <linux/ioport.h>
#include <asm/io.h>
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f46c69e4ed82..09c93ff932b1 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -5,11 +5,9 @@
# Parport configuration.
#
-menu "Parallel port support"
- depends on HAS_IOMEM
-
-config PARPORT
+menuconfig PARPORT
tristate "Parallel port support"
+ depends on HAS_IOMEM
---help---
If you want to use devices connected to your machine's parallel port
(the connector at the computer with 25 holes), e.g. printer, ZIP
@@ -33,9 +31,11 @@ config PARPORT
If unsure, say Y.
+if PARPORT
+
config PARPORT_PC
tristate "PC-style hardware"
- depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
+ depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
@@ -85,7 +85,7 @@ config PARPORT_PC_PCMCIA
config PARPORT_IP32
tristate "SGI IP32 builtin port (EXPERIMENTAL)"
- depends on SGI_IP32 && PARPORT && EXPERIMENTAL
+ depends on SGI_IP32 && EXPERIMENTAL
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port on
@@ -94,7 +94,7 @@ config PARPORT_IP32
config PARPORT_AMIGA
tristate "Amiga builtin port"
- depends on AMIGA && PARPORT
+ depends on AMIGA
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
@@ -103,7 +103,7 @@ config PARPORT_AMIGA
config PARPORT_MFC3
tristate "Multiface III parallel port"
- depends on ZORRO && PARPORT
+ depends on ZORRO
select PARPORT_NOT_PC
help
Say Y here if you need parallel port support for the MFC3 card.
@@ -112,7 +112,7 @@ config PARPORT_MFC3
config PARPORT_ATARI
tristate "Atari hardware"
- depends on ATARI && PARPORT
+ depends on ATARI
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
@@ -122,12 +122,11 @@ config PARPORT_ATARI
config PARPORT_GSC
tristate
default GSC
- depends on PARPORT
select PARPORT_NOT_PC
config PARPORT_SUNBPP
tristate "Sparc hardware (EXPERIMENTAL)"
- depends on SBUS && PARPORT && EXPERIMENTAL
+ depends on SBUS && EXPERIMENTAL
select PARPORT_NOT_PC
help
This driver provides support for the bidirectional parallel port
@@ -136,7 +135,6 @@ config PARPORT_SUNBPP
config PARPORT_AX88796
tristate "AX88796 Parallel Port"
- depends on PARPORT
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
@@ -148,7 +146,6 @@ config PARPORT_AX88796
config PARPORT_1284
bool "IEEE 1284 transfer modes"
- depends on PARPORT
help
If you have a printer that supports status readback or device ID, or
want to use a device that uses enhanced parallel port transfer modes
@@ -159,5 +156,4 @@ config PARPORT_1284
config PARPORT_NOT_PC
bool
-endmenu
-
+endif # PARPORT
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 7bfbad57879d..5d58ad55d85c 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2424,7 +2424,6 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
u32 ite8872set;
u32 ite8872_lpt, ite8872_lpthi;
u8 ite8872_irq, type;
- char *fake_name = "parport probe";
int irq;
int i;
@@ -2432,11 +2431,11 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
// make sure which one chip
for(i = 0; i < 5; i++) {
- base_res = request_region(inta_addr[i], 0x8, fake_name);
+ base_res = request_region(inta_addr[i], 32, "it887x");
if (base_res) {
int test;
pci_write_config_dword (pdev, 0x60,
- 0xe7000000 | inta_addr[i]);
+ 0xe5000000 | inta_addr[i]);
pci_write_config_dword (pdev, 0x78,
0x00000000 | inta_addr[i]);
test = inb (inta_addr[i]);
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index bb3c101c2c5a..deb6b5e35feb 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -159,8 +159,8 @@ static void dlpar_pci_add_bus(struct device_node *dn)
/* Claim new bus resources */
pcibios_claim_one_bus(dev->bus);
- /* ioremap() for child bus, which may or may not succeed */
- remap_bus_range(dev->subordinate);
+ /* Map IO space for child bus, which may or may not succeed */
+ pcibios_map_io_space(dev->subordinate);
/* Add new devices to global lists. Register in proc, sysfs. */
pci_bus_add_devices(phb->bus);
@@ -390,7 +390,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
} else
pcibios_remove_pci_devices(bus);
- if (unmap_bus_range(bus)) {
+ if (pcibios_unmap_io_space(bus)) {
printk(KERN_ERR "%s: failed to unmap bus range\n",
__FUNCTION__);
return -ERANGE;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 10dbdec80416..1b7b2812bf2d 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -20,7 +20,7 @@
#include <linux/stat.h>
#include <linux/topology.h>
#include <linux/mm.h>
-
+#include <linux/capability.h>
#include "pci.h"
static int sysfs_initialized; /* = 0 */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a7bce75c6732..34b8dae0d90f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -22,6 +22,18 @@ EXPORT_SYMBOL(pci_root_buses);
LIST_HEAD(pci_devices);
+/*
+ * Some device drivers need know if pci is initiated.
+ * Basically, we think pci is not initiated when there
+ * is no device in list of pci_devices.
+ */
+int no_pci_devices(void)
+{
+ return list_empty(&pci_devices);
+}
+
+EXPORT_SYMBOL(no_pci_devices);
+
#ifdef HAVE_PCI_LEGACY
/**
* pci_create_legacy_files - create legacy I/O port and memory files
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index cfa0dfe61b1a..90adc62d07ff 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-
+#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include "pci.h"
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 9f7090fa8771..c6e79d01ce3d 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -202,7 +202,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor,
* can cause some machines to crash. So here we detect and flag that
* situation and bail out early.
*/
- if (unlikely(list_empty(&pci_devices)))
+ if (unlikely(no_pci_devices()))
return NULL;
down_read(&pci_bus_sem);
n = from ? from->global_list.next : pci_devices.next;
@@ -277,7 +277,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
* can cause some machines to crash. So here we detect and flag that
* situation and bail out early.
*/
- if (unlikely(list_empty(&pci_devices)))
+ if (unlikely(no_pci_devices()))
return NULL;
down_read(&pci_bus_sem);
n = from ? from->global_list.next : pci_devices.next;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 35f88649d3b7..c0c77f82d051 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -180,14 +180,15 @@ config TCIC
PCMCIA cards are plugged into. If unsure, say N.
config PCMCIA_M8XX
- tristate "MPC8xx PCMCIA support"
- depends on PCMCIA && PPC && 8xx
- select PCCARD_IODYN
- help
- Say Y here to include support for PowerPC 8xx series PCMCIA
- controller.
-
- This driver is also available as a module called m8xx_pcmcia.
+ tristate "MPC8xx PCMCIA support"
+ depends on PCMCIA && PPC && 8xx
+ select PCCARD_IODYN
+ select PCCARD_NONSTATIC
+ help
+ Say Y here to include support for PowerPC 8xx series PCMCIA
+ controller.
+
+ This driver is also available as a module called m8xx_pcmcia.
config HD64465_PCMCIA
tristate "HD64465 host bridge support"
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 50cad3a59a6c..7c93a108f9b8 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -651,6 +651,7 @@ static int pccardd(void *__skt)
add_wait_queue(&skt->thread_wait, &wait);
complete(&skt->thread_done);
+ set_freezable();
for (;;) {
unsigned long flags;
unsigned int events;
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 9721ed7bf502..3c45142c40b2 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -10,7 +10,7 @@
* Further fixes, v2.6 kernel port
* <marcelo.tosatti@cyclades.com>
*
- * Some fixes, additions (C) 2005 Montavista Software, Inc.
+ * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
* <vbordug@ru.mvista.com>
*
* "The ExCA standard specifies that socket controllers should provide
@@ -40,10 +40,6 @@
#include <linux/fcntl.h>
#include <linux/string.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/system.h>
-
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
@@ -51,11 +47,18 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/time.h>
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/irq.h>
+#include <asm/fs_pd.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -110,7 +113,7 @@ MODULE_LICENSE("Dual MPL/GPL");
#define CONFIG_PCMCIA_SLOT_B
#endif
-#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
+#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
@@ -143,30 +146,20 @@ MODULE_LICENSE("Dual MPL/GPL");
/* ------------------------------------------------------------------------- */
-#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
-#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
-#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
-
-#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */
-
+#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
+#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
+#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
/* ------------------------------------------------------------------------- */
-/* 2.4.x and newer has this always in HZ */
-#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
-
-static int pcmcia_schlvl = PCMCIA_SCHLVL;
+static int pcmcia_schlvl;
static DEFINE_SPINLOCK(events_lock);
-
#define PCMCIA_SOCKET_KEY_5V 1
#define PCMCIA_SOCKET_KEY_LV 2
/* look up table for pgcrx registers */
-static u32 *m8xx_pgcrx[2] = {
- &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,
- &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb
-};
+static u32 *m8xx_pgcrx[2];
/*
* This structure is used to address each window in the PCMCIA controller.
@@ -176,8 +169,8 @@ static u32 *m8xx_pgcrx[2] = {
*/
struct pcmcia_win {
- u32 br;
- u32 or;
+ u32 br;
+ u32 or;
};
/*
@@ -221,22 +214,27 @@ struct pcmcia_win {
/* we keep one lookup table per socket to check flags */
-#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
+#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
struct event_table {
u32 regbit;
u32 eventbit;
};
+static const char driver_name[] = "m8xx-pcmcia";
+
struct socket_info {
- void (*handler)(void *info, u32 events);
- void *info;
+ void (*handler) (void *info, u32 events);
+ void *info;
u32 slot;
+ pcmconf8xx_t *pcmcia;
+ u32 bus_freq;
+ int hwirq;
socket_state_t state;
struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
- struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
+ struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
struct event_table events[PCMCIA_EVENTS_MAX];
struct pcmcia_socket socket;
};
@@ -250,8 +248,7 @@ static struct socket_info socket[PCMCIA_SOCKETS_NO];
#define M8XX_SIZES_NO 32
-static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
-{
+static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
0x00000001, 0x00000002, 0x00000008, 0x00000004,
0x00000080, 0x00000040, 0x00000010, 0x00000020,
0x00008000, 0x00004000, 0x00001000, 0x00002000,
@@ -267,7 +264,7 @@ static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
static irqreturn_t m8xx_interrupt(int irq, void *dev);
-#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
+#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
/* ------------------------------------------------------------------------- */
/* board specific stuff: */
@@ -291,8 +288,9 @@ static int voltage_set(int slot, int vcc, int vpp)
{
u32 reg = 0;
- switch(vcc) {
- case 0: break;
+ switch (vcc) {
+ case 0:
+ break;
case 33:
reg |= BCSR1_PCVCTL4;
break;
@@ -303,11 +301,12 @@ static int voltage_set(int slot, int vcc, int vpp)
return 1;
}
- switch(vpp) {
- case 0: break;
+ switch (vpp) {
+ case 0:
+ break;
case 33:
case 50:
- if(vcc == vpp)
+ if (vcc == vpp)
reg |= BCSR1_PCVCTL6;
else
return 1;
@@ -318,25 +317,29 @@ static int voltage_set(int slot, int vcc, int vpp)
return 1;
}
- if(!((vcc == 50) || (vcc == 0)))
+ if (!((vcc == 50) || (vcc == 0)))
return 1;
/* first, turn off all power */
- out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7));
+ out_be32(((u32 *) RPX_CSR_ADDR),
+ in_be32(((u32 *) RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 |
+ BCSR1_PCVCTL5 |
+ BCSR1_PCVCTL6 |
+ BCSR1_PCVCTL7));
/* enable new powersettings */
- out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) | reg);
+ out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) | reg);
return 0;
}
#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_) /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
+#define hardware_enable(_slot_) /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
-#endif /* CONFIG_RPXCLASSIC */
+#endif /* CONFIG_RPXCLASSIC */
/* FADS Boards from Motorola */
@@ -348,43 +351,45 @@ static int voltage_set(int slot, int vcc, int vpp)
{
u32 reg = 0;
- switch(vcc) {
- case 0:
- break;
- case 33:
- reg |= BCSR1_PCCVCC0;
- break;
- case 50:
- reg |= BCSR1_PCCVCC1;
- break;
- default:
- return 1;
+ switch (vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= BCSR1_PCCVCC0;
+ break;
+ case 50:
+ reg |= BCSR1_PCCVCC1;
+ break;
+ default:
+ return 1;
}
- switch(vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if(vcc == vpp)
- reg |= BCSR1_PCCVPP1;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= BCSR1_PCCVPP0;
- else
- return 1;
- default:
+ switch (vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if (vcc == vpp)
+ reg |= BCSR1_PCCVPP1;
+ else
return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= BCSR1_PCCVPP0;
+ else
+ return 1;
+ default:
+ return 1;
}
/* first, turn off all power */
- out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+ out_be32((u32 *) BCSR1,
+ in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK |
+ BCSR1_PCCVPP_MASK));
/* enable new powersettings */
- out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | reg);
+ out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
return 0;
}
@@ -393,12 +398,12 @@ static int voltage_set(int slot, int vcc, int vpp)
static void hardware_enable(int slot)
{
- out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~BCSR1_PCCEN);
+ out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN);
}
static void hardware_disable(int slot)
{
- out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | BCSR1_PCCEN);
+ out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
}
#endif
@@ -408,78 +413,21 @@ static void hardware_disable(int slot)
#if defined(CONFIG_MPC885ADS)
#define PCMCIA_BOARD_MSG "MPC885ADS"
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-static int voltage_set(int slot, int vcc, int vpp)
+static inline void hardware_enable(int slot)
{
- u32 reg = 0;
- unsigned *bcsr_io;
-
- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
- switch(vcc) {
- case 0:
- break;
- case 33:
- reg |= BCSR1_PCCVCC0;
- break;
- case 50:
- reg |= BCSR1_PCCVCC1;
- break;
- default:
- goto out_unmap;
- }
-
- switch(vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if(vcc == vpp)
- reg |= BCSR1_PCCVPP1;
- else
- goto out_unmap;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= BCSR1_PCCVPP0;
- else
- goto out_unmap;
- default:
- goto out_unmap;
- }
-
- /* first, turn off all power */
- out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
-
- /* enable new powersettings */
- out_be32(bcsr_io, in_be32(bcsr_io) | reg);
-
- iounmap(bcsr_io);
- return 0;
-
-out_unmap:
- iounmap(bcsr_io);
- return 1;
+ m8xx_pcmcia_ops.hw_ctrl(slot, 1);
}
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-
-static void hardware_enable(int slot)
+static inline void hardware_disable(int slot)
{
- unsigned *bcsr_io;
-
- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
- out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
- iounmap(bcsr_io);
+ m8xx_pcmcia_ops.hw_ctrl(slot, 0);
}
-static void hardware_disable(int slot)
+static inline int voltage_set(int slot, int vcc, int vpp)
{
- unsigned *bcsr_io;
-
- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
- out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN);
- iounmap(bcsr_io);
+ return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
}
#endif
@@ -495,52 +443,53 @@ static int voltage_set(int slot, int vcc, int vpp)
{
u8 reg = 0;
- switch(vcc) {
- case 0:
- break;
- case 33:
- reg |= CSR2_VCC_33;
- break;
- case 50:
- reg |= CSR2_VCC_50;
- break;
- default:
- return 1;
+ switch (vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= CSR2_VCC_33;
+ break;
+ case 50:
+ reg |= CSR2_VCC_50;
+ break;
+ default:
+ return 1;
}
- switch(vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if(vcc == vpp)
- reg |= CSR2_VPP_VCC;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= CSR2_VPP_12;
- else
- return 1;
- default:
+ switch (vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if (vcc == vpp)
+ reg |= CSR2_VPP_VCC;
+ else
return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= CSR2_VPP_12;
+ else
+ return 1;
+ default:
+ return 1;
}
/* first, turn off all power */
- out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
+ out_8((u8 *) MBX_CSR2_ADDR,
+ in_8((u8 *) MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
/* enable new powersettings */
- out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) | reg);
+ out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) | reg);
return 0;
}
#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_) /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
+#define hardware_enable(_slot_) /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
-#endif /* CONFIG_MBX */
+#endif /* CONFIG_MBX */
#if defined(CONFIG_PRxK)
#include <asm/cpld.h>
@@ -554,43 +503,46 @@ static int voltage_set(int slot, int vcc, int vpp)
u8 regread;
cpld_regs *ccpld = get_cpld();
- switch(vcc) {
- case 0:
- break;
- case 33:
- reg |= PCMCIA_VCC_33;
- break;
- case 50:
- reg |= PCMCIA_VCC_50;
- break;
- default:
- return 1;
+ switch (vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= PCMCIA_VCC_33;
+ break;
+ case 50:
+ reg |= PCMCIA_VCC_50;
+ break;
+ default:
+ return 1;
}
- switch(vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if(vcc == vpp)
- reg |= PCMCIA_VPP_VCC;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= PCMCIA_VPP_12;
- else
- return 1;
- default:
+ switch (vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if (vcc == vpp)
+ reg |= PCMCIA_VPP_VCC;
+ else
return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= PCMCIA_VPP_12;
+ else
+ return 1;
+ default:
+ return 1;
}
reg = reg >> (slot << 2);
regread = in_8(&ccpld->fpga_pc_ctl);
- if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
+ if (reg !=
+ (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
/* enable new powersettings */
- regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
+ regread =
+ regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
+ (slot << 2));
out_8(&ccpld->fpga_pc_ctl, reg | regread);
msleep(100);
}
@@ -599,52 +551,10 @@ static int voltage_set(int slot, int vcc, int vpp)
}
#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
-#define hardware_enable(_slot_) /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
-
-#endif /* CONFIG_PRxK */
-
-static void m8xx_shutdown(void)
-{
- u32 m, i;
- struct pcmcia_win *w;
+#define hardware_enable(_slot_) /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
- for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
- w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
-
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i));
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i));
-
- /* turn off interrupt and disable CxOE */
- out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
-
- /* turn off memory windows */
- for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
- out_be32(&w->or, 0); /* set to not valid */
- w++;
- }
-
- /* turn off voltage */
- voltage_set(i, 0, 0);
-
- /* disable external hardware */
- hardware_disable(i);
- }
-
- free_irq(pcmcia_schlvl, NULL);
-}
-
-static struct device_driver m8xx_driver = {
- .name = "m8xx-pcmcia",
- .bus = &platform_bus_type,
- .suspend = pcmcia_socket_dev_suspend,
- .resume = pcmcia_socket_dev_resume,
-};
-
-static struct platform_device m8xx_device = {
- .name = "m8xx-pcmcia",
- .id = 0,
-};
+#endif /* CONFIG_PRxK */
static u32 pending_events[PCMCIA_SOCKETS_NO];
static DEFINE_SPINLOCK(pending_event_lock);
@@ -654,24 +564,25 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
struct socket_info *s;
struct event_table *e;
unsigned int i, events, pscr, pipr, per;
+ pcmconf8xx_t *pcmcia = socket[0].pcmcia;
dprintk("Interrupt!\n");
/* get interrupt sources */
- pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr);
- pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
- per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per);
+ pscr = in_be32(&pcmcia->pcmc_pscr);
+ pipr = in_be32(&pcmcia->pcmc_pipr);
+ per = in_be32(&pcmcia->pcmc_per);
- for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
s = &socket[i];
e = &s->events[0];
events = 0;
- while(e->regbit) {
- if(pscr & e->regbit)
+ while (e->regbit) {
+ if (pscr & e->regbit)
events |= e->eventbit;
- e++;
+ e++;
}
/*
@@ -679,13 +590,11 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
* not too nice done,
* we depend on that CD2 is the bit to the left of CD1...
*/
- if(events & SS_DETECT)
- if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
- (pipr & M8XX_PCMCIA_CD1(i)))
- {
+ if (events & SS_DETECT)
+ if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
+ (pipr & M8XX_PCMCIA_CD1(i))) {
events &= ~SS_DETECT;
}
-
#ifdef PCMCIA_GLITCHY_CD
/*
* I've experienced CD problems with my ADS board.
@@ -693,24 +602,23 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
* real change of Card detection.
*/
- if((events & SS_DETECT) &&
- ((pipr &
- (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
- (s->state.Vcc | s->state.Vpp)) {
+ if ((events & SS_DETECT) &&
+ ((pipr &
+ (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
+ (s->state.Vcc | s->state.Vpp)) {
events &= ~SS_DETECT;
/*printk( "CD glitch workaround - CD = 0x%08x!\n",
- (pipr & (M8XX_PCMCIA_CD2(i)
- | M8XX_PCMCIA_CD1(i))));*/
+ (pipr & (M8XX_PCMCIA_CD2(i)
+ | M8XX_PCMCIA_CD1(i)))); */
}
#endif
/* call the handler */
dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
- "pipr = 0x%08x\n",
- i, events, pscr, pipr);
+ "pipr = 0x%08x\n", i, events, pscr, pipr);
- if(events) {
+ if (events) {
spin_lock(&pending_event_lock);
pending_events[i] |= events;
spin_unlock(&pending_event_lock);
@@ -724,7 +632,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
per &= ~M8XX_PCMCIA_RDY_L(0);
per &= ~M8XX_PCMCIA_RDY_L(1);
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per);
+ out_be32(&pcmcia->pcmc_per, per);
if (events)
pcmcia_parse_events(&socket[i].socket, events);
@@ -732,7 +640,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
}
/* clear the interrupt sources */
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr);
+ out_be32(&pcmcia->pcmc_pscr, pscr);
dprintk("Interrupt done.\n");
@@ -743,21 +651,21 @@ static u32 m8xx_get_graycode(u32 size)
{
u32 k;
- for(k = 0; k < M8XX_SIZES_NO; k++)
- if(m8xx_size_to_gray[k] == size)
+ for (k = 0; k < M8XX_SIZES_NO; k++)
+ if (m8xx_size_to_gray[k] == size)
break;
- if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
+ if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
k = -1;
return k;
}
-static u32 m8xx_get_speed(u32 ns, u32 is_io)
+static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
{
u32 reg, clocks, psst, psl, psht;
- if(!ns) {
+ if (!ns) {
/*
* We get called with IO maps setup to 0ns
@@ -765,10 +673,10 @@ static u32 m8xx_get_speed(u32 ns, u32 is_io)
* They should be 255ns.
*/
- if(is_io)
+ if (is_io)
ns = 255;
else
- ns = 100; /* fast memory if 0 */
+ ns = 100; /* fast memory if 0 */
}
/*
@@ -779,23 +687,23 @@ static u32 m8xx_get_speed(u32 ns, u32 is_io)
/* how we want to adjust the timing - in percent */
-#define ADJ 180 /* 80 % longer accesstime - to be sure */
+#define ADJ 180 /* 80 % longer accesstime - to be sure */
- clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
- clocks = (clocks * ADJ) / (100*1000);
- if(clocks >= PCMCIA_BMT_LIMIT) {
- printk( "Max access time limit reached\n");
- clocks = PCMCIA_BMT_LIMIT-1;
+ clocks = ((bus_freq / 1000) * ns) / 1000;
+ clocks = (clocks * ADJ) / (100 * 1000);
+ if (clocks >= PCMCIA_BMT_LIMIT) {
+ printk("Max access time limit reached\n");
+ clocks = PCMCIA_BMT_LIMIT - 1;
}
- psst = clocks / 7; /* setup time */
- psht = clocks / 7; /* hold time */
- psl = (clocks * 5) / 7; /* strobe length */
+ psst = clocks / 7; /* setup time */
+ psht = clocks / 7; /* hold time */
+ psl = (clocks * 5) / 7; /* strobe length */
psst += clocks - (psst + psht + psl);
- reg = psst << 12;
- reg |= psl << 7;
+ reg = psst << 12;
+ reg |= psl << 7;
reg |= psht << 16;
return reg;
@@ -806,11 +714,12 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
int lsock = container_of(sock, struct socket_info, socket)->slot;
struct socket_info *s = &socket[lsock];
unsigned int pipr, reg;
+ pcmconf8xx_t *pcmcia = s->pcmcia;
- pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
+ pipr = in_be32(&pcmcia->pcmc_pipr);
- *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
- | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
+ *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
+ | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
*value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
if (s->state.flags & SS_IOCARD)
@@ -894,16 +803,16 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
/* read out VS1 and VS2 */
reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
- >> M8XX_PCMCIA_VS_SHIFT(lsock);
+ >> M8XX_PCMCIA_VS_SHIFT(lsock);
- if(socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
- switch(reg) {
+ if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
+ switch (reg) {
case 1:
*value |= SS_3VCARD;
- break; /* GND, NC - 3.3V only */
+ break; /* GND, NC - 3.3V only */
case 2:
*value |= SS_XVCARD;
- break; /* NC. GND - x.xV only */
+ break; /* NC. GND - x.xV only */
};
}
@@ -911,27 +820,29 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0;
}
-static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
{
int lsock = container_of(sock, struct socket_info, socket)->slot;
struct socket_info *s = &socket[lsock];
struct event_table *e;
unsigned int reg;
unsigned long flags;
+ pcmconf8xx_t *pcmcia = socket[0].pcmcia;
- dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+ dprintk("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+ "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
+ state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
/* First, set voltage - bail out if invalid */
- if(voltage_set(lsock, state->Vcc, state->Vpp))
+ if (voltage_set(lsock, state->Vcc, state->Vpp))
return -EINVAL;
/* Take care of reset... */
- if(state->flags & SS_RESET)
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
+ if (state->flags & SS_RESET)
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
else
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
+ out_be32(M8XX_PGCRX(lsock),
+ in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
/* ... and output enable. */
@@ -943,10 +854,11 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
no pullups are present -> the cards act wierd.
So right now the buffers are enabled if the power is on. */
- if(state->Vcc || state->Vpp)
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
+ if (state->Vcc || state->Vpp)
+ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
else
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
+ out_be32(M8XX_PGCRX(lsock),
+ in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
/*
* We'd better turn off interrupts before
@@ -963,17 +875,17 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
e = &s->events[0];
reg = 0;
- if(state->csc_mask & SS_DETECT) {
+ if (state->csc_mask & SS_DETECT) {
e->eventbit = SS_DETECT;
reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
| M8XX_PCMCIA_CD1(lsock));
e++;
}
- if(state->flags & SS_IOCARD) {
+ if (state->flags & SS_IOCARD) {
/*
* I/O card
*/
- if(state->csc_mask & SS_STSCHG) {
+ if (state->csc_mask & SS_STSCHG) {
e->eventbit = SS_STSCHG;
reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
e++;
@@ -981,8 +893,10 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
/*
* If io_irq is non-zero we should enable irq.
*/
- if(state->io_irq) {
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24);
+ if (state->io_irq) {
+ out_be32(M8XX_PGCRX(lsock),
+ in_be32(M8XX_PGCRX(lsock)) |
+ mk_int_int_mask(s->hwirq) << 24);
/*
* Strange thing here:
* The manual does not tell us which interrupt
@@ -993,33 +907,32 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
* have to be cleared in PSCR in the interrupt handler.
*/
reg |= M8XX_PCMCIA_RDY_L(lsock);
- }
- else
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
- }
- else {
+ } else
+ out_be32(M8XX_PGCRX(lsock),
+ in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
+ } else {
/*
* Memory card
*/
- if(state->csc_mask & SS_BATDEAD) {
+ if (state->csc_mask & SS_BATDEAD) {
e->eventbit = SS_BATDEAD;
reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
e++;
}
- if(state->csc_mask & SS_BATWARN) {
+ if (state->csc_mask & SS_BATWARN) {
e->eventbit = SS_BATWARN;
reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
e++;
}
/* What should I trigger on - low/high,raise,fall? */
- if(state->csc_mask & SS_READY) {
+ if (state->csc_mask & SS_READY) {
e->eventbit = SS_READY;
- reg |= e->regbit = 0; //??
+ reg |= e->regbit = 0; //??
e++;
}
}
- e->regbit = 0; /* terminate list */
+ e->regbit = 0; /* terminate list */
/*
* Clear the status changed .
@@ -1027,7 +940,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
* Writing ones will clear the bits.
*/
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg);
+ out_be32(&pcmcia->pcmc_pscr, reg);
/*
* Write the mask.
@@ -1036,15 +949,10 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
* Ones will enable the interrupt.
*/
- /*
- reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per
- & M8XX_PCMCIA_MASK(lsock);
- */
-
- reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
- (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg);
+ reg |=
+ in_be32(&pcmcia->
+ pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+ out_be32(&pcmcia->pcmc_per, reg);
spin_unlock_irqrestore(&events_lock, flags);
@@ -1062,66 +970,68 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
struct socket_info *s = &socket[lsock];
struct pcmcia_win *w;
unsigned int reg, winnr;
+ pcmconf8xx_t *pcmcia = s->pcmcia;
#define M8XX_SIZE (io->stop - io->start + 1)
#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
- dprintk( "SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
- io->speed, io->start, io->stop);
+ dprintk("SetIOMap(%d, %d, %#2.2x, %d ns, "
+ "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
+ io->speed, io->start, io->stop);
if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
|| (io->stop > 0xffff) || (io->stop < io->start))
return -EINVAL;
- if((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
+ if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
return -EINVAL;
- if(io->flags & MAP_ACTIVE) {
+ if (io->flags & MAP_ACTIVE) {
- dprintk( "io->flags & MAP_ACTIVE\n");
+ dprintk("io->flags & MAP_ACTIVE\n");
winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
- + (lsock * PCMCIA_IO_WIN_NO) + io->map;
+ + (lsock * PCMCIA_IO_WIN_NO) + io->map;
/* setup registers */
- w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+ w = (void *)&pcmcia->pcmc_pbr0;
w += winnr;
- out_be32(&w->or, 0); /* turn off window first */
+ out_be32(&w->or, 0); /* turn off window first */
out_be32(&w->br, M8XX_BASE);
reg <<= 27;
- reg |= M8XX_PCMCIA_POR_IO |(lsock << 2);
+ reg |= M8XX_PCMCIA_POR_IO | (lsock << 2);
- reg |= m8xx_get_speed(io->speed, 1);
+ reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
- if(io->flags & MAP_WRPROT)
+ if (io->flags & MAP_WRPROT)
reg |= M8XX_PCMCIA_POR_WRPROT;
- if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
+ /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
+ if (io->flags & MAP_16BIT)
reg |= M8XX_PCMCIA_POR_16BIT;
- if(io->flags & MAP_ACTIVE)
+ if (io->flags & MAP_ACTIVE)
reg |= M8XX_PCMCIA_POR_VALID;
out_be32(&w->or, reg);
dprintk("Socket %u: Mapped io window %u at %#8.8x, "
- "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
+ "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
} else {
/* shutdown IO window */
winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
- + (lsock * PCMCIA_IO_WIN_NO) + io->map;
+ + (lsock * PCMCIA_IO_WIN_NO) + io->map;
/* setup registers */
- w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+ w = (void *)&pcmcia->pcmc_pbr0;
w += winnr;
- out_be32(&w->or, 0); /* turn off window */
- out_be32(&w->br, 0); /* turn off base address */
+ out_be32(&w->or, 0); /* turn off window */
+ out_be32(&w->br, 0); /* turn off base address */
dprintk("Socket %u: Unmapped io window %u at %#8.8x, "
"OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
@@ -1129,35 +1039,35 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
/* copy the struct and modify the copy */
s->io_win[io->map] = *io;
- s->io_win[io->map].flags &= (MAP_WRPROT
- | MAP_16BIT
- | MAP_ACTIVE);
+ s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
dprintk("SetIOMap exit\n");
return 0;
}
-static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+static int m8xx_set_mem_map(struct pcmcia_socket *sock,
+ struct pccard_mem_map *mem)
{
int lsock = container_of(sock, struct socket_info, socket)->slot;
struct socket_info *s = &socket[lsock];
struct pcmcia_win *w;
struct pccard_mem_map *old;
unsigned int reg, winnr;
+ pcmconf8xx_t *pcmcia = s->pcmcia;
- dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
- mem->speed, mem->static_start, mem->card_start);
+ dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
+ "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+ mem->speed, mem->static_start, mem->card_start);
if ((mem->map >= PCMCIA_MEM_WIN_NO)
-// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
+// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
|| (mem->card_start >= 0x04000000)
- || (mem->static_start & 0xfff) /* 4KByte resolution */
- || (mem->card_start & 0xfff))
+ || (mem->static_start & 0xfff) /* 4KByte resolution */
+ ||(mem->card_start & 0xfff))
return -EINVAL;
- if((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
- printk( "Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
+ if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
+ printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
return -EINVAL;
}
reg <<= 27;
@@ -1166,50 +1076,47 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m
/* Setup the window in the pcmcia controller */
- w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+ w = (void *)&pcmcia->pcmc_pbr0;
w += winnr;
reg |= lsock << 2;
- reg |= m8xx_get_speed(mem->speed, 0);
+ reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
- if(mem->flags & MAP_ATTRIB)
- reg |= M8XX_PCMCIA_POR_ATTRMEM;
+ if (mem->flags & MAP_ATTRIB)
+ reg |= M8XX_PCMCIA_POR_ATTRMEM;
- if(mem->flags & MAP_WRPROT)
+ if (mem->flags & MAP_WRPROT)
reg |= M8XX_PCMCIA_POR_WRPROT;
- if(mem->flags & MAP_16BIT)
+ if (mem->flags & MAP_16BIT)
reg |= M8XX_PCMCIA_POR_16BIT;
- if(mem->flags & MAP_ACTIVE)
+ if (mem->flags & MAP_ACTIVE)
reg |= M8XX_PCMCIA_POR_VALID;
out_be32(&w->or, reg);
dprintk("Socket %u: Mapped memory window %u at %#8.8x, "
- "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
+ "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
- if(mem->flags & MAP_ACTIVE) {
+ if (mem->flags & MAP_ACTIVE) {
/* get the new base address */
mem->static_start = PCMCIA_MEM_WIN_BASE +
- (PCMCIA_MEM_WIN_SIZE * winnr)
- + mem->card_start;
+ (PCMCIA_MEM_WIN_SIZE * winnr)
+ + mem->card_start;
}
dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
- mem->speed, mem->static_start, mem->card_start);
+ "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+ mem->speed, mem->static_start, mem->card_start);
/* copy the struct and modify the copy */
old = &s->mem_win[mem->map];
*old = *mem;
- old->flags &= (MAP_ATTRIB
- | MAP_WRPROT
- | MAP_16BIT
- | MAP_ACTIVE);
+ old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
return 0;
}
@@ -1220,7 +1127,7 @@ static int m8xx_sock_init(struct pcmcia_socket *sock)
pccard_io_map io = { 0, 0, 0, 0, 1 };
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
- dprintk( "sock_init(%d)\n", s);
+ dprintk("sock_init(%d)\n", s);
m8xx_set_socket(sock, &dead_socket);
for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
@@ -1236,111 +1143,195 @@ static int m8xx_sock_init(struct pcmcia_socket *sock)
}
-static int m8xx_suspend(struct pcmcia_socket *sock)
+static int m8xx_sock_suspend(struct pcmcia_socket *sock)
{
return m8xx_set_socket(sock, &dead_socket);
}
static struct pccard_operations m8xx_services = {
- .init = m8xx_sock_init,
- .suspend = m8xx_suspend,
+ .init = m8xx_sock_init,
+ .suspend = m8xx_sock_suspend,
.get_status = m8xx_get_status,
.set_socket = m8xx_set_socket,
.set_io_map = m8xx_set_io_map,
.set_mem_map = m8xx_set_mem_map,
};
-static int __init m8xx_init(void)
+static int __init m8xx_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
struct pcmcia_win *w;
- unsigned int i,m;
+ unsigned int i, m, hwirq;
+ pcmconf8xx_t *pcmcia;
+ int status;
+ struct device_node *np = ofdev->node;
pcmcia_info("%s\n", version);
- if (driver_register(&m8xx_driver))
- return -1;
+ pcmcia = of_iomap(np, 0);
+ if (pcmcia == NULL)
+ return -EINVAL;
+
+ pcmcia_schlvl = irq_of_parse_and_map(np, 0);
+ hwirq = irq_map[pcmcia_schlvl].hwirq;
+ if (pcmcia_schlvl < 0)
+ return -EINVAL;
+
+ m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
+ m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
- " with IRQ %u.\n", pcmcia_schlvl);
+ " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq);
/* Configure Status change interrupt */
- if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0,
- "m8xx_pcmcia", NULL)) {
+ if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
+ driver_name, socket)) {
pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
pcmcia_schlvl);
return -1;
}
- w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
-
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr,
- M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+ w = (void *)&pcmcia->pcmc_pbr0;
- out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per,
- in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
- ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)));
+ out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+ clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-/* connect interrupt and disable CxOE */
+ /* connect interrupt and disable CxOE */
- out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
- out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
+ out_be32(M8XX_PGCRX(0),
+ M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
+ out_be32(M8XX_PGCRX(1),
+ M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
-/* intialize the fixed memory windows */
+ /* intialize the fixed memory windows */
- for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
- for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+ for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
- (PCMCIA_MEM_WIN_SIZE
- * (m + i * PCMCIA_MEM_WIN_NO)));
+ (PCMCIA_MEM_WIN_SIZE
+ * (m + i * PCMCIA_MEM_WIN_NO)));
- out_be32(&w->or, 0); /* set to not valid */
+ out_be32(&w->or, 0); /* set to not valid */
w++;
}
}
-/* turn off voltage */
+ /* turn off voltage */
voltage_set(0, 0, 0);
voltage_set(1, 0, 0);
-/* Enable external hardware */
+ /* Enable external hardware */
hardware_enable(0);
hardware_enable(1);
- platform_device_register(&m8xx_device);
-
- for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
socket[i].slot = i;
socket[i].socket.owner = THIS_MODULE;
- socket[i].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
+ socket[i].socket.features =
+ SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
socket[i].socket.irq_mask = 0x000;
socket[i].socket.map_size = 0x1000;
socket[i].socket.io_offset = 0;
- socket[i].socket.pci_irq = i ? 7 : 9;
+ socket[i].socket.pci_irq = pcmcia_schlvl;
socket[i].socket.ops = &m8xx_services;
- socket[i].socket.resource_ops = &pccard_iodyn_ops;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.cb_dev = NULL;
- socket[i].socket.dev.parent = &m8xx_device.dev;
+ socket[i].socket.dev.parent = &ofdev->dev;
+ socket[i].pcmcia = pcmcia;
+ socket[i].bus_freq = ppc_proc_freq;
+ socket[i].hwirq = hwirq;
+
}
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
- pcmcia_register_socket(&socket[i].socket);
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+ status = pcmcia_register_socket(&socket[i].socket);
+ if (status < 0)
+ pcmcia_error("Socket register failed\n");
+ }
return 0;
}
-static void __exit m8xx_exit(void)
+static int m8xx_remove(struct of_device *ofdev)
{
- int i;
+ u32 m, i;
+ struct pcmcia_win *w;
+ pcmconf8xx_t *pcmcia = socket[0].pcmcia;
+
+ for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+ w = (void *)&pcmcia->pcmc_pbr0;
+ out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
+ out_be32(&pcmcia->pcmc_per,
+ in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
+
+ /* turn off interrupt and disable CxOE */
+ out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
+
+ /* turn off memory windows */
+ for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+ out_be32(&w->or, 0); /* set to not valid */
+ w++;
+ }
+
+ /* turn off voltage */
+ voltage_set(i, 0, 0);
+
+ /* disable external hardware */
+ hardware_disable(i);
+ }
for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
pcmcia_unregister_socket(&socket[i].socket);
- m8xx_shutdown();
+ free_irq(pcmcia_schlvl, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return pcmcia_socket_dev_suspend(&pdev->dev, state);
+}
+
+static int m8xx_resume(struct platform_device *pdev)
+{
+ return pcmcia_socket_dev_resume(&pdev->dev);
+}
+#else
+#define m8xx_suspend NULL
+#define m8xx_resume NULL
+#endif
- platform_device_unregister(&m8xx_device);
- driver_unregister(&m8xx_driver);
+static struct of_device_id m8xx_pcmcia_match[] = {
+ {
+ .type = "pcmcia",
+ .compatible = "fsl,pq-pcmcia",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
+
+static struct of_platform_driver m8xx_pcmcia_driver = {
+ .name = (char *)driver_name,
+ .match_table = m8xx_pcmcia_match,
+ .probe = m8xx_probe,
+ .remove = m8xx_remove,
+ .suspend = m8xx_suspend,
+ .resume = m8xx_resume,
+};
+
+static int __init m8xx_init(void)
+{
+ return of_register_platform_driver(&m8xx_pcmcia_driver);
+}
+
+static void __exit m8xx_exit(void)
+{
+ of_unregister_platform_driver(&m8xx_pcmcia_driver);
}
module_init(m8xx_init);
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 1959cef8e9de..821933f9aa57 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -2,11 +2,9 @@
# Plug and Play configuration
#
-menu "Plug and Play support"
- depends on HAS_IOMEM
-
-config PNP
+menuconfig PNP
bool "Plug and Play support"
+ depends on HAS_IOMEM
depends on ISA || ACPI
---help---
Plug and Play (PnP) is a standard for peripherals which allows those
@@ -22,15 +20,15 @@ config PNP
If unsure, say Y.
+if PNP
+
config PNP_DEBUG
bool "PnP Debug Messages"
- depends on PNP
help
Say Y if you want the Plug and Play Layer to print debug messages.
This is useful if you are developing a PnP driver or troubleshooting.
comment "Protocols"
- depends on PNP
source "drivers/pnp/isapnp/Kconfig"
@@ -38,5 +36,4 @@ source "drivers/pnp/pnpbios/Kconfig"
source "drivers/pnp/pnpacpi/Kconfig"
-endmenu
-
+endif # PNP
diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig
index 578651eeb4b0..f1ef36673ad4 100644
--- a/drivers/pnp/isapnp/Kconfig
+++ b/drivers/pnp/isapnp/Kconfig
@@ -3,7 +3,7 @@
#
config ISAPNP
bool "ISA Plug and Play support"
- depends on PNP && ISA
+ depends on ISA
help
Say Y here if you would like support for ISA Plug and Play devices.
Some information is in <file:Documentation/isapnp.txt>.
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index a0b158704ca1..914d00c423ad 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -370,8 +370,6 @@ static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
#if 0
printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
#endif
- if (type == 0) /* wrong type */
- return -1;
if (*type == 0xff && *size == 0xffff) /* probably invalid data */
return -1;
return 0;
diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig
index fab848cae89d..b986d9fa3b9a 100644
--- a/drivers/pnp/pnpbios/Kconfig
+++ b/drivers/pnp/pnpbios/Kconfig
@@ -3,7 +3,7 @@
#
config PNPBIOS
bool "Plug and Play BIOS support (EXPERIMENTAL)"
- depends on PNP && ISA && X86 && EXPERIMENTAL
+ depends on ISA && X86 && EXPERIMENTAL
default n
---help---
Linux uses the PNPBIOS as defined in "Plug and Play BIOS
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 3a201b77b963..03baf1c64a2e 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -160,6 +160,7 @@ static int pnp_dock_thread(void * unused)
{
static struct pnp_docking_station_info now;
int docked = -1, d = 0;
+ set_freezable();
while (!unloading)
{
int status;
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index e251d1c1171c..746031de2195 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1,3 +1,6 @@
obj-$(CONFIG_PS3_VUART) += vuart.o
-obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
+ps3av_mod-objs += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
+obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 1393e64335f9..85e21614f868 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -1,32 +1,30 @@
/*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ * PS3 AV backend support.
*
- * AV backend support for PS3
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
*
- * 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * 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.
+ * 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/delay.h>
#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/kernel.h>
#include <linux/ioctl.h>
#include <asm/firmware.h>
-#include <asm/lv1call.h>
#include <asm/ps3av.h>
#include <asm/ps3.h>
@@ -39,13 +37,12 @@ static int timeout = 5000; /* in msec ( 5 sec ) */
module_param(timeout, int, 0644);
static struct ps3av {
- int available;
struct mutex mutex;
struct work_struct work;
struct completion done;
struct workqueue_struct *wq;
int open_count;
- struct ps3_vuart_port_device *dev;
+ struct ps3_system_bus_device *dev;
int region;
struct ps3av_pkt_av_get_hw_conf av_hw_conf;
@@ -55,11 +52,13 @@ static struct ps3av {
u32 audio_port;
int ps3av_mode;
int ps3av_mode_old;
-} ps3av;
-
-static struct ps3_vuart_port_device ps3av_dev = {
- .match_id = PS3_MATCH_ID_AV_SETTINGS
-};
+ union {
+ struct ps3av_reply_hdr reply_hdr;
+ u8 raw[PS3AV_BUF_SIZE];
+ } recv_buf;
+ void (*flip_ctl)(int on, void *data);
+ void *flip_data;
+} *ps3av;
/* color space */
#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
@@ -169,7 +168,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
if (table)
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"recv event packet cid:%08x port:0x%x size:%d\n",
hdr->cid, ps3av_event_get_port_id(hdr->cid),
hdr->size);
@@ -182,6 +181,41 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
return 0;
}
+
+#define POLLING_INTERVAL 25 /* in msec */
+
+static int ps3av_vuart_write(struct ps3_system_bus_device *dev,
+ const void *buf, unsigned long size)
+{
+ int error;
+ dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+ error = ps3_vuart_write(dev, buf, size);
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+ return error ? error : size;
+}
+
+static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
+ unsigned long size, int timeout)
+{
+ int error;
+ int loopcnt = 0;
+
+ dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+ timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+ while (loopcnt++ <= timeout) {
+ error = ps3_vuart_read(dev, buf, size);
+ if (!error)
+ return size;
+ if (error != -EAGAIN) {
+ printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+ __func__, error);
+ return error;
+ }
+ msleep(POLLING_INTERVAL);
+ }
+ return -EWOULDBLOCK;
+}
+
static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
struct ps3av_reply_hdr *recv_buf, int write_len,
int read_len)
@@ -190,13 +224,13 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
u32 cmd;
int event;
- if (!ps3av.available)
+ if (!ps3av)
return -ENODEV;
/* send pkt */
- res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+ res = ps3av_vuart_write(ps3av->dev, send_buf, write_len);
if (res < 0) {
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"%s: ps3av_vuart_write() failed (result=%d)\n",
__func__, res);
return res;
@@ -206,20 +240,20 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
cmd = send_buf->cid;
do {
/* read header */
- res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+ res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE,
timeout);
if (res != PS3AV_HDR_SIZE) {
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"%s: ps3av_vuart_read() failed (result=%d)\n",
__func__, res);
return res;
}
/* read body */
- res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+ res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid,
recv_buf->size, timeout);
if (res < 0) {
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"%s: ps3av_vuart_read() failed (result=%d)\n",
__func__, res);
return res;
@@ -230,7 +264,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
} while (event);
if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
- dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+ dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n",
__func__, recv_buf->cid);
return -EINVAL;
}
@@ -245,7 +279,7 @@ static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
int return_len;
if (recv_buf->version != PS3AV_VERSION) {
- dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+ dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n",
recv_buf->version);
return -EFAULT;
}
@@ -267,16 +301,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
struct ps3av_send_hdr *buf)
{
int res = 0;
- static union {
- struct ps3av_reply_hdr reply_hdr;
- u8 raw[PS3AV_BUF_SIZE];
- } recv_buf;
-
u32 *table;
- BUG_ON(!ps3av.available);
+ BUG_ON(!ps3av);
- mutex_lock(&ps3av.mutex);
+ mutex_lock(&ps3av->mutex);
table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
BUG_ON(!table);
@@ -288,7 +317,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
ps3av_set_hdr(cid, send_len, buf);
/* send packet via vuart */
- res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+ res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len,
usr_buf_size);
if (res < 0) {
printk(KERN_ERR
@@ -298,7 +327,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
}
/* process reply packet */
- res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+ res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr,
usr_buf_size);
if (res < 0) {
printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
@@ -306,11 +335,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
goto err;
}
- mutex_unlock(&ps3av.mutex);
+ mutex_unlock(&ps3av->mutex);
return 0;
err:
- mutex_unlock(&ps3av.mutex);
+ mutex_unlock(&ps3av->mutex);
printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
return res;
}
@@ -319,11 +348,11 @@ static int ps3av_set_av_video_mute(u32 mute)
{
int i, num_of_av_port, res;
- num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
- ps3av.av_hw_conf.num_of_avmulti;
+ num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+ ps3av->av_hw_conf.num_of_avmulti;
/* video mute on */
for (i = 0; i < num_of_av_port; i++) {
- res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+ res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute);
if (res < 0)
return -1;
}
@@ -335,13 +364,13 @@ static int ps3av_set_video_disable_sig(void)
{
int i, num_of_hdmi_port, num_of_av_port, res;
- num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
- num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
- ps3av.av_hw_conf.num_of_avmulti;
+ num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi;
+ num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+ ps3av->av_hw_conf.num_of_avmulti;
/* tv mute */
for (i = 0; i < num_of_hdmi_port; i++) {
- res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+ res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
PS3AV_CMD_MUTE_ON);
if (res < 0)
return -1;
@@ -350,11 +379,11 @@ static int ps3av_set_video_disable_sig(void)
/* video mute on */
for (i = 0; i < num_of_av_port; i++) {
- res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+ res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]);
if (res < 0)
return -1;
if (i < num_of_hdmi_port) {
- res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+ res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
PS3AV_CMD_MUTE_OFF);
if (res < 0)
return -1;
@@ -369,17 +398,17 @@ static int ps3av_set_audio_mute(u32 mute)
{
int i, num_of_av_port, num_of_opt_port, res;
- num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
- ps3av.av_hw_conf.num_of_avmulti;
- num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+ num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+ ps3av->av_hw_conf.num_of_avmulti;
+ num_of_opt_port = ps3av->av_hw_conf.num_of_spdif;
for (i = 0; i < num_of_av_port; i++) {
- res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+ res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute);
if (res < 0)
return -1;
}
for (i = 0; i < num_of_opt_port; i++) {
- res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+ res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute);
if (res < 0)
return -1;
}
@@ -394,40 +423,40 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
struct ps3av_pkt_audio_mode audio_mode;
u32 len = 0;
- num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
- ps3av.av_hw_conf.num_of_avmulti +
- ps3av.av_hw_conf.num_of_spdif;
+ num_of_audio = ps3av->av_hw_conf.num_of_hdmi +
+ ps3av->av_hw_conf.num_of_avmulti +
+ ps3av->av_hw_conf.num_of_spdif;
avb_param.num_of_video_pkt = 0;
avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */
avb_param.num_of_av_video_pkt = 0;
- avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+ avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi;
- vid = video_mode_table[ps3av.ps3av_mode].vid;
+ vid = video_mode_table[ps3av->ps3av_mode].vid;
/* audio mute */
ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
/* audio inactive */
- res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+ res = ps3av_cmd_audio_active(0, ps3av->audio_port);
if (res < 0)
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"ps3av_cmd_audio_active OFF failed\n");
/* audio_pkt */
for (i = 0; i < num_of_audio; i++) {
- ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
- word_bits, format, source);
- if (i < ps3av.av_hw_conf.num_of_hdmi) {
+ ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch,
+ fs, word_bits, format, source);
+ if (i < ps3av->av_hw_conf.num_of_hdmi) {
/* hdmi only */
len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
- ps3av.av_port[i],
+ ps3av->av_port[i],
&audio_mode, vid);
}
/* audio_mode pkt should be sent separately */
res = ps3av_cmd_audio_mode(&audio_mode);
if (res < 0)
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"ps3av_cmd_audio_mode failed, port:%x\n", i);
}
@@ -435,15 +464,16 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
len += offsetof(struct ps3av_pkt_avb_param, buf);
res = ps3av_cmd_avb_param(&avb_param, len);
if (res < 0)
- dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+ dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
/* audio mute */
ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
/* audio active */
- res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+ res = ps3av_cmd_audio_active(1, ps3av->audio_port);
if (res < 0)
- dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+ dev_dbg(&ps3av->dev->core,
+ "ps3av_cmd_audio_active ON failed\n");
return 0;
}
@@ -456,7 +486,7 @@ static int ps3av_set_videomode(void)
ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
/* wake up ps3avd to do the actual video mode setting */
- queue_work(ps3av.wq, &ps3av.work);
+ queue_work(ps3av->wq, &ps3av->work);
return 0;
}
@@ -473,8 +503,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */
avb_param.num_of_audio_pkt = 0;
- avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
- ps3av.av_hw_conf.num_of_avmulti;
+ avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
+ ps3av->av_hw_conf.num_of_avmulti;
avb_param.num_of_av_audio_pkt = 0;
/* video signal off */
@@ -484,21 +514,21 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
if (id & PS3AV_MODE_HDCP_OFF) {
res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
- dev_dbg(&ps3av_dev.core, "Not supported\n");
+ dev_dbg(&ps3av->dev->core, "Not supported\n");
else if (res)
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"ps3av_cmd_av_hdmi_mode failed\n");
} else if (old_id & PS3AV_MODE_HDCP_OFF) {
res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
- dev_dbg(&ps3av_dev.core,
+ dev_dbg(&ps3av->dev->core,
"ps3av_cmd_av_hdmi_mode failed\n");
}
/* video_pkt */
for (i = 0; i < avb_param.num_of_video_pkt; i++)
len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
- ps3av.head[i], video_mode->vid,
+ ps3av->head[i], video_mode->vid,
video_mode->fmt, id);
/* av_video_pkt */
for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
@@ -507,12 +537,12 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
else
av_video_cs = video_mode->cs;
#ifndef PS3AV_HDMI_YUV
- if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
- ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+ if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+ ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
av_video_cs = RGB8; /* use RGB for HDMI */
#endif
len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
- ps3av.av_port[i],
+ ps3av->av_port[i],
video_mode->vid, av_video_cs,
video_mode->aspect, id);
}
@@ -524,7 +554,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
"%s: Command failed. Please try your request again. \n",
__func__);
else if (res)
- dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+ dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
msleep(1500);
/* av video mute */
@@ -533,8 +563,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
static void ps3avd(struct work_struct *work)
{
- ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
- complete(&ps3av.done);
+ ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old);
+ complete(&ps3av->done);
}
static int ps3av_vid2table_id(int vid)
@@ -601,7 +631,7 @@ static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
return vid;
}
- if (ps3av.region & PS3AV_REGION_60)
+ if (ps3av->region & PS3AV_REGION_60)
vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
else
vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
@@ -643,16 +673,16 @@ static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
vid = PS3AV_DEFAULT_DVI_VID;
} else if (vid == -1) {
/* no HDMI interface or HDMI is off */
- if (ps3av.region & PS3AV_REGION_60)
+ if (ps3av->region & PS3AV_REGION_60)
vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
else
vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
- if (ps3av.region & PS3AV_REGION_RGB)
+ if (ps3av->region & PS3AV_REGION_RGB)
rgb = PS3AV_MODE_RGB;
} else if (boot) {
/* HDMI: using DEFAULT HDMI_VID while booting up */
info = &monitor_info.info;
- if (ps3av.region & PS3AV_REGION_60) {
+ if (ps3av->region & PS3AV_REGION_60) {
if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
@@ -715,14 +745,14 @@ int ps3av_set_video_mode(u32 id, int boot)
size = ARRAY_SIZE(video_mode_table);
if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
- dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
+ dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id);
return -EINVAL;
}
/* auto mode */
option = id & ~PS3AV_MODE_MASK;
if ((id & PS3AV_MODE_MASK) == 0) {
- id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+ id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
if (id < 1) {
printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
return -EINVAL;
@@ -731,11 +761,11 @@ int ps3av_set_video_mode(u32 id, int boot)
}
/* set videomode */
- wait_for_completion(&ps3av.done);
- ps3av.ps3av_mode_old = ps3av.ps3av_mode;
- ps3av.ps3av_mode = id;
+ wait_for_completion(&ps3av->done);
+ ps3av->ps3av_mode_old = ps3av->ps3av_mode;
+ ps3av->ps3av_mode = id;
if (ps3av_set_videomode())
- ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+ ps3av->ps3av_mode = ps3av->ps3av_mode_old;
return 0;
}
@@ -744,7 +774,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
int ps3av_get_auto_mode(int boot)
{
- return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+ return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
}
EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
@@ -772,7 +802,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_mode);
int ps3av_get_mode(void)
{
- return ps3av.ps3av_mode;
+ return ps3av ? ps3av->ps3av_mode : 0;
}
EXPORT_SYMBOL_GPL(ps3av_get_mode);
@@ -842,82 +872,65 @@ int ps3av_audio_mute(int mute)
EXPORT_SYMBOL_GPL(ps3av_audio_mute);
-int ps3av_dev_open(void)
+void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+ void *flip_data)
{
- int status = 0;
-
- mutex_lock(&ps3av.mutex);
- if (!ps3av.open_count++) {
- status = lv1_gpu_open(0);
- if (status) {
- printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
- __func__, status);
- ps3av.open_count--;
- }
- }
- mutex_unlock(&ps3av.mutex);
-
- return status;
+ mutex_lock(&ps3av->mutex);
+ ps3av->flip_ctl = flip_ctl;
+ ps3av->flip_data = flip_data;
+ mutex_unlock(&ps3av->mutex);
}
+EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
-EXPORT_SYMBOL_GPL(ps3av_dev_open);
-
-int ps3av_dev_close(void)
+void ps3av_flip_ctl(int on)
{
- int status = 0;
-
- mutex_lock(&ps3av.mutex);
- if (ps3av.open_count <= 0) {
- printk(KERN_ERR "%s: GPU already closed\n", __func__);
- status = -1;
- } else if (!--ps3av.open_count) {
- status = lv1_gpu_close();
- if (status)
- printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
- __func__, status);
- }
- mutex_unlock(&ps3av.mutex);
-
- return status;
+ mutex_lock(&ps3av->mutex);
+ if (ps3av->flip_ctl)
+ ps3av->flip_ctl(on, ps3av->flip_data);
+ mutex_unlock(&ps3av->mutex);
}
-EXPORT_SYMBOL_GPL(ps3av_dev_close);
-
-static int ps3av_probe(struct ps3_vuart_port_device *dev)
+static int ps3av_probe(struct ps3_system_bus_device *dev)
{
int res;
u32 id;
- dev_dbg(&ps3av_dev.core, "init ...\n");
- dev_dbg(&ps3av_dev.core, " timeout=%d\n", timeout);
+ dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+ dev_dbg(&dev->core, " timeout=%d\n", timeout);
- memset(&ps3av, 0, sizeof(ps3av));
-
- mutex_init(&ps3av.mutex);
- ps3av.ps3av_mode = 0;
- ps3av.dev = dev;
+ if (ps3av) {
+ dev_err(&dev->core, "Only one ps3av device is supported\n");
+ return -EBUSY;
+ }
- INIT_WORK(&ps3av.work, ps3avd);
- init_completion(&ps3av.done);
- complete(&ps3av.done);
- ps3av.wq = create_singlethread_workqueue("ps3avd");
- if (!ps3av.wq)
+ ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL);
+ if (!ps3av)
return -ENOMEM;
- ps3av.available = 1;
+ mutex_init(&ps3av->mutex);
+ ps3av->ps3av_mode = 0;
+ ps3av->dev = dev;
+
+ INIT_WORK(&ps3av->work, ps3avd);
+ init_completion(&ps3av->done);
+ complete(&ps3av->done);
+ ps3av->wq = create_singlethread_workqueue("ps3avd");
+ if (!ps3av->wq)
+ goto fail;
+
switch (ps3_os_area_get_av_multi_out()) {
case PS3_PARAM_AV_MULTI_OUT_NTSC:
- ps3av.region = PS3AV_REGION_60;
+ ps3av->region = PS3AV_REGION_60;
break;
case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
case PS3_PARAM_AV_MULTI_OUT_SECAM:
- ps3av.region = PS3AV_REGION_50;
+ ps3av->region = PS3AV_REGION_50;
break;
case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
- ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+ ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
break;
default:
- ps3av.region = PS3AV_REGION_60;
+ ps3av->region = PS3AV_REGION_60;
break;
}
@@ -927,39 +940,47 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev)
printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
res);
- ps3av_get_hw_conf(&ps3av);
- id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
- mutex_lock(&ps3av.mutex);
- ps3av.ps3av_mode = id;
- mutex_unlock(&ps3av.mutex);
+ ps3av_get_hw_conf(ps3av);
+ id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
+ mutex_lock(&ps3av->mutex);
+ ps3av->ps3av_mode = id;
+ mutex_unlock(&ps3av->mutex);
- dev_dbg(&ps3av_dev.core, "init...done\n");
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
return 0;
+
+fail:
+ kfree(ps3av);
+ ps3av = NULL;
+ return -ENOMEM;
}
-static int ps3av_remove(struct ps3_vuart_port_device *dev)
+static int ps3av_remove(struct ps3_system_bus_device *dev)
{
- if (ps3av.available) {
+ dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+ if (ps3av) {
ps3av_cmd_fin();
- if (ps3av.wq)
- destroy_workqueue(ps3av.wq);
- ps3av.available = 0;
+ if (ps3av->wq)
+ destroy_workqueue(ps3av->wq);
+ kfree(ps3av);
+ ps3av = NULL;
}
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
return 0;
}
-static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+static void ps3av_shutdown(struct ps3_system_bus_device *dev)
{
+ dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
ps3av_remove(dev);
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
}
static struct ps3_vuart_port_driver ps3av_driver = {
- .match_id = PS3_MATCH_ID_AV_SETTINGS,
- .core = {
- .name = "ps3_av",
- },
+ .core.match_id = PS3_MATCH_ID_AV_SETTINGS,
+ .core.core.name = "ps3_av",
.probe = ps3av_probe,
.remove = ps3av_remove,
.shutdown = ps3av_shutdown,
@@ -972,6 +993,8 @@ static int ps3av_module_init(void)
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
return -ENODEV;
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
error = ps3_vuart_port_driver_register(&ps3av_driver);
if (error) {
printk(KERN_ERR
@@ -980,20 +1003,21 @@ static int ps3av_module_init(void)
return error;
}
- error = ps3_vuart_port_device_register(&ps3av_dev);
- if (error)
- printk(KERN_ERR
- "%s: ps3_vuart_port_device_register failed %d\n",
- __func__, error);
-
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
return error;
}
static void __exit ps3av_module_exit(void)
{
- device_unregister(&ps3av_dev.core);
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
ps3_vuart_port_driver_unregister(&ps3av_driver);
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
subsys_initcall(ps3av_module_init);
module_exit(ps3av_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 AV Settings Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index 0145ea173c42..f72f5ddf18e4 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -143,6 +143,14 @@ static u32 ps3av_vid_video2av(int vid)
return PS3AV_CMD_AV_VID_480P;
}
+static int ps3av_hdmi_range(void)
+{
+ if (ps3_compare_firmware_version(1, 8, 0) < 0)
+ return 0;
+ else
+ return 1; /* supported */
+}
+
int ps3av_cmd_init(void)
{
int res;
@@ -350,6 +358,10 @@ u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out,
/* should be same as video_mode.video_cs_out */
av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+ if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range())
+ av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON;
+ else /* default off */
+ av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF;
av_video_cs->aspect = aspect;
if (id & PS3AV_MODE_DITHER) {
av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
@@ -392,6 +404,10 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
video_mode->pitch = video_mode->width * 4; /* line_length */
video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+ if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range())
+ video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT;
+ else /* default enable */
+ video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT;
video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
@@ -852,7 +868,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
{
int res;
- ps3fb_flip_ctl(0); /* flip off */
+ ps3av_flip_ctl(0); /* flip off */
/* avb packet */
res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -866,7 +882,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
res);
out:
- ps3fb_flip_ctl(1); /* flip on */
+ ps3av_flip_ctl(1); /* flip on */
return res;
}
@@ -987,34 +1003,3 @@ void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *
| PS3AV_CMD_AV_LAYOUT_176 \
| PS3AV_CMD_AV_LAYOUT_192)
-/************************* vuart ***************************/
-
-#define POLLING_INTERVAL 25 /* in msec */
-
-int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
- unsigned long size)
-{
- int error = ps3_vuart_write(dev, buf, size);
- return error ? error : size;
-}
-
-int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
- unsigned long size, int timeout)
-{
- int error;
- int loopcnt = 0;
-
- timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
- while (loopcnt++ <= timeout) {
- error = ps3_vuart_read(dev, buf, size);
- if (!error)
- return size;
- if (error != -EAGAIN) {
- printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
- __func__, error);
- return error;
- }
- msleep(POLLING_INTERVAL);
- }
- return -EWOULDBLOCK;
-}
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
new file mode 100644
index 000000000000..3a9824e3b251
--- /dev/null
+++ b/drivers/ps3/ps3stor_lib.c
@@ -0,0 +1,302 @@
+/*
+ * PS3 Storage Library
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+
+static int ps3stor_probe_access(struct ps3_storage_device *dev)
+{
+ int res, error;
+ unsigned int i;
+ unsigned long n;
+
+ if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) {
+ /* special case: CD-ROM is assumed always accessible */
+ dev->accessible_regions = 1;
+ return 0;
+ }
+
+ error = -EPERM;
+ for (i = 0; i < dev->num_regions; i++) {
+ dev_dbg(&dev->sbd.core,
+ "%s:%u: checking accessibility of region %u\n",
+ __func__, __LINE__, i);
+
+ dev->region_idx = i;
+ res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
+ 0);
+ if (res) {
+ dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
+ "region %u is not accessible\n", __func__,
+ __LINE__, i);
+ continue;
+ }
+
+ dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n",
+ __func__, __LINE__, i);
+ set_bit(i, &dev->accessible_regions);
+
+ /* We can access at least one region */
+ error = 0;
+ }
+ if (error)
+ return error;
+
+ n = hweight_long(dev->accessible_regions);
+ if (n > 1)
+ dev_info(&dev->sbd.core,
+ "%s:%u: %lu accessible regions found. Only the first "
+ "one will be used",
+ __func__, __LINE__, n);
+ dev->region_idx = __ffs(dev->accessible_regions);
+ dev_info(&dev->sbd.core,
+ "First accessible region has index %u start %lu size %lu\n",
+ dev->region_idx, dev->regions[dev->region_idx].start,
+ dev->regions[dev->region_idx].size);
+
+ return 0;
+}
+
+
+/**
+ * ps3stor_setup - Setup a storage device before use
+ * @dev: Pointer to a struct ps3_storage_device
+ * @handler: Pointer to an interrupt handler
+ *
+ * Returns 0 for success, or an error code
+ */
+int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
+{
+ int error, res, alignment;
+ enum ps3_dma_page_size page_size;
+
+ error = ps3_open_hv_device(&dev->sbd);
+ if (error) {
+ dev_err(&dev->sbd.core,
+ "%s:%u: ps3_open_hv_device failed %d\n", __func__,
+ __LINE__, error);
+ goto fail;
+ }
+
+ error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY,
+ &dev->irq);
+ if (error) {
+ dev_err(&dev->sbd.core,
+ "%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
+ __func__, __LINE__, error);
+ goto fail_close_device;
+ }
+
+ error = request_irq(dev->irq, handler, IRQF_DISABLED,
+ dev->sbd.core.driver->name, dev);
+ if (error) {
+ dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
+ __func__, __LINE__, error);
+ goto fail_sb_event_receive_port_destroy;
+ }
+
+ alignment = min(__ffs(dev->bounce_size),
+ __ffs((unsigned long)dev->bounce_buf));
+ if (alignment < 12) {
+ dev_err(&dev->sbd.core,
+ "%s:%u: bounce buffer not aligned (%lx at 0x%p)\n",
+ __func__, __LINE__, dev->bounce_size, dev->bounce_buf);
+ error = -EINVAL;
+ goto fail_free_irq;
+ } else if (alignment < 16)
+ page_size = PS3_DMA_4K;
+ else
+ page_size = PS3_DMA_64K;
+ dev->sbd.d_region = &dev->dma_region;
+ ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size,
+ PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size);
+ res = ps3_dma_region_create(&dev->dma_region);
+ if (res) {
+ dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n",
+ __func__, __LINE__);
+ error = -ENOMEM;
+ goto fail_free_irq;
+ }
+
+ dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf));
+ dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf,
+ dev->bounce_size, DMA_BIDIRECTIONAL);
+ if (!dev->bounce_dma) {
+ dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n",
+ __func__, __LINE__);
+ error = -ENODEV;
+ goto fail_free_dma;
+ }
+
+ error = ps3stor_probe_access(dev);
+ if (error) {
+ dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n",
+ __func__, __LINE__);
+ goto fail_unmap_dma;
+ }
+ return 0;
+
+fail_unmap_dma:
+ dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+ DMA_BIDIRECTIONAL);
+fail_free_dma:
+ ps3_dma_region_free(&dev->dma_region);
+fail_free_irq:
+ free_irq(dev->irq, dev);
+fail_sb_event_receive_port_destroy:
+ ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+fail_close_device:
+ ps3_close_hv_device(&dev->sbd);
+fail:
+ return error;
+}
+EXPORT_SYMBOL_GPL(ps3stor_setup);
+
+
+/**
+ * ps3stor_teardown - Tear down a storage device after use
+ * @dev: Pointer to a struct ps3_storage_device
+ */
+void ps3stor_teardown(struct ps3_storage_device *dev)
+{
+ int error;
+
+ dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+ DMA_BIDIRECTIONAL);
+ ps3_dma_region_free(&dev->dma_region);
+
+ free_irq(dev->irq, dev);
+
+ error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+ if (error)
+ dev_err(&dev->sbd.core,
+ "%s:%u: destroy event receive port failed %d\n",
+ __func__, __LINE__, error);
+
+ error = ps3_close_hv_device(&dev->sbd);
+ if (error)
+ dev_err(&dev->sbd.core,
+ "%s:%u: ps3_close_hv_device failed %d\n", __func__,
+ __LINE__, error);
+}
+EXPORT_SYMBOL_GPL(ps3stor_teardown);
+
+
+/**
+ * ps3stor_read_write_sectors - read/write from/to a storage device
+ * @dev: Pointer to a struct ps3_storage_device
+ * @lpar: HV logical partition address
+ * @start_sector: First sector to read/write
+ * @sectors: Number of sectors to read/write
+ * @write: Flag indicating write (non-zero) or read (zero)
+ *
+ * Returns 0 for success, -1 in case of failure to submit the command, or
+ * an LV1 status value in case of other errors
+ */
+u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+ u64 start_sector, u64 sectors, int write)
+{
+ unsigned int region_id = dev->regions[dev->region_idx].id;
+ const char *op = write ? "write" : "read";
+ int res;
+
+ dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+ __func__, __LINE__, op, sectors, start_sector);
+
+ init_completion(&dev->done);
+ res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
+ start_sector, sectors, 0, lpar,
+ &dev->tag)
+ : lv1_storage_read(dev->sbd.dev_id, region_id,
+ start_sector, sectors, 0, lpar,
+ &dev->tag);
+ if (res) {
+ dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
+ __LINE__, op, res);
+ return -1;
+ }
+
+ wait_for_completion(&dev->done);
+ if (dev->lv1_status) {
+ dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+ __LINE__, op, dev->lv1_status);
+ return dev->lv1_status;
+ }
+
+ dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__,
+ op);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors);
+
+
+/**
+ * ps3stor_send_command - send a device command to a storage device
+ * @dev: Pointer to a struct ps3_storage_device
+ * @cmd: Command number
+ * @arg1: First command argument
+ * @arg2: Second command argument
+ * @arg3: Third command argument
+ * @arg4: Fourth command argument
+ *
+ * Returns 0 for success, -1 in case of failure to submit the command, or
+ * an LV1 status value in case of other errors
+ */
+u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
+ u64 arg2, u64 arg3, u64 arg4)
+{
+ int res;
+
+ dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
+ __LINE__, cmd);
+
+ init_completion(&dev->done);
+
+ res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1,
+ arg2, arg3, arg4, &dev->tag);
+ if (res) {
+ dev_err(&dev->sbd.core,
+ "%s:%u: send_device_command 0x%lx failed %d\n",
+ __func__, __LINE__, cmd, res);
+ return -1;
+ }
+
+ wait_for_completion(&dev->done);
+ if (dev->lv1_status) {
+ dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
+ __func__, __LINE__, cmd, dev->lv1_status);
+ return dev->lv1_status;
+ }
+
+ dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
+ __LINE__, cmd);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_send_command);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 Storage Bus Library");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
new file mode 100644
index 000000000000..31648f7d9ae1
--- /dev/null
+++ b/drivers/ps3/sys-manager-core.c
@@ -0,0 +1,68 @@
+/*
+ * PS3 System Manager core.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <asm/ps3.h>
+
+/**
+ * Staticly linked routines that allow late binding of a loaded sys-manager
+ * module.
+ */
+
+static struct ps3_sys_manager_ops ps3_sys_manager_ops;
+
+/**
+ * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module.
+ * @ops: struct ps3_sys_manager_ops.
+ *
+ * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to
+ * register call back ops for power control. Copies data to the static
+ * variable ps3_sys_manager_ops.
+ */
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops)
+{
+ BUG_ON(!ops);
+ BUG_ON(!ops->dev);
+ ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops;
+}
+EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops);
+
+void ps3_sys_manager_power_off(void)
+{
+ if (ps3_sys_manager_ops.power_off)
+ ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+ local_irq_disable();
+ while (1)
+ (void)0;
+}
+
+void ps3_sys_manager_restart(void)
+{
+ if (ps3_sys_manager_ops.restart)
+ ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+ local_irq_disable();
+ while (1)
+ (void)0;
+}
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
index 3aa2b0dcc369..8461b08ab9fb 100644
--- a/drivers/ps3/sys-manager.c
+++ b/drivers/ps3/sys-manager.c
@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("PS3 System Manager");
/**
* ps3_sys_manager - PS3 system manager driver.
*
- * The system manager provides an asyncronous system event notification
+ * The system manager provides an asynchronous system event notification
* mechanism for reporting events like thermal alert and button presses to
* guests. It also provides support to control system shutdown and startup.
*
@@ -52,6 +52,7 @@ MODULE_DESCRIPTION("PS3 System Manager");
* @size: Header size in bytes, curently 16.
* @payload_size: Message payload size in bytes.
* @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ * @request_tag: Unique number to identify reply.
*/
struct ps3_sys_manager_header {
@@ -61,29 +62,49 @@ struct ps3_sys_manager_header {
u16 reserved_1;
u32 payload_size;
u16 service_id;
- u16 reserved_2[3];
+ u16 reserved_2;
+ u32 request_tag;
};
+#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
+static void __maybe_unused _dump_sm_header(
+ const struct ps3_sys_manager_header *h, const char *func, int line)
+{
+ pr_debug("%s:%d: version: %xh\n", func, line, h->version);
+ pr_debug("%s:%d: size: %xh\n", func, line, h->size);
+ pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
+ pr_debug("%s:%d: service_id: %xh\n", func, line, h->service_id);
+ pr_debug("%s:%d: request_tag: %xh\n", func, line, h->request_tag);
+}
+
/**
- * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
+ * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
*
- * Currently all messages received from the system manager are the same length
- * (16 bytes header + 16 bytes payload = 32 bytes). This knowlege is used to
- * simplify the logic.
+ * Currently all messages received from the system manager are either
+ * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
+ * + 16 bytes payload = 32 bytes). This knowlege is used to simplify
+ * the logic.
*/
enum {
- PS3_SM_RX_MSG_LEN = 32,
+ PS3_SM_RX_MSG_LEN_MIN = 24,
+ PS3_SM_RX_MSG_LEN_MAX = 32,
};
/**
* enum ps3_sys_manager_service_id - Message header service_id.
- * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager.
+ *
+ * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
+ * a PS3_SM_SERVICE_ID_REQUEST message. It also seems to be returned when
+ * a REQUEST message is sent at the wrong time.
*/
enum ps3_sys_manager_service_id {
@@ -93,6 +114,7 @@ enum ps3_sys_manager_service_id {
PS3_SM_SERVICE_ID_COMMAND = 3,
PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+ PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
PS3_SM_SERVICE_ID_SET_ATTR = 8,
};
@@ -185,11 +207,21 @@ enum ps3_sys_manager_cmd {
};
/**
+ * ps3_sm_force_power_off - Poweroff helper.
+ *
+ * A global variable used to force a poweroff when the power button has
+ * been pressed irrespective of how init handles the ctrl_alt_del signal.
+ *
+ */
+
+static unsigned int ps3_sm_force_power_off;
+
+/**
* ps3_sys_manager_write - Helper to write a two part message to the vuart.
*
*/
-static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
const struct ps3_sys_manager_header *header, const void *payload)
{
int result;
@@ -213,15 +245,10 @@ static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
*
*/
-static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
enum ps3_sys_manager_attr attr)
{
- static const struct ps3_sys_manager_header header = {
- .version = 1,
- .size = 16,
- .payload_size = 16,
- .service_id = PS3_SM_SERVICE_ID_SET_ATTR,
- };
+ struct ps3_sys_manager_header header;
struct {
u8 version;
u8 reserved_1[3];
@@ -232,6 +259,12 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
+ memset(&header, 0, sizeof(header));
+ header.version = 1;
+ header.size = 16;
+ header.payload_size = 16;
+ header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
+
memset(&payload, 0, sizeof(payload));
payload.version = 1;
payload.attribute = attr;
@@ -245,16 +278,11 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
* Tell the system manager what to do after this lpar is destroyed.
*/
-static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
enum ps3_sys_manager_next_op op,
enum ps3_sys_manager_wake_source wake_source)
{
- static const struct ps3_sys_manager_header header = {
- .version = 1,
- .size = 16,
- .payload_size = 16,
- .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
- };
+ struct ps3_sys_manager_header header;
struct {
u8 version;
u8 type;
@@ -268,6 +296,12 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
+ memset(&header, 0, sizeof(header));
+ header.version = 1;
+ header.size = 16;
+ header.payload_size = 16;
+ header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
+
memset(&payload, 0, sizeof(payload));
payload.version = 3;
payload.type = op;
@@ -286,32 +320,35 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
* the command is then communicated back to the system manager with a response
* message.
*
- * Currently, the only supported request it the 'shutdown self' request.
+ * Currently, the only supported request is the 'shutdown self' request.
*/
-static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_send_request_shutdown(
+ struct ps3_system_bus_device *dev)
{
- static const struct ps3_sys_manager_header header = {
- .version = 1,
- .size = 16,
- .payload_size = 16,
- .service_id = PS3_SM_SERVICE_ID_REQUEST,
- };
+ struct ps3_sys_manager_header header;
struct {
u8 version;
u8 type;
u8 gos_id;
u8 reserved_1[13];
- } static const payload = {
- .version = 1,
- .type = 1, /* shutdown */
- .gos_id = 0, /* self */
- };
+ } payload;
BUILD_BUG_ON(sizeof(payload) != 16);
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+ memset(&header, 0, sizeof(header));
+ header.version = 1;
+ header.size = 16;
+ header.payload_size = 16;
+ header.service_id = PS3_SM_SERVICE_ID_REQUEST;
+
+ memset(&payload, 0, sizeof(payload));
+ payload.version = 1;
+ payload.type = 1; /* shutdown */
+ payload.gos_id = 0; /* self */
+
return ps3_sys_manager_write(dev, &header, &payload);
}
@@ -323,15 +360,10 @@ static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *d
* failure of a command sent by the system manager.
*/
-static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
u64 status)
{
- static const struct ps3_sys_manager_header header = {
- .version = 1,
- .size = 16,
- .payload_size = 16,
- .service_id = PS3_SM_SERVICE_ID_RESPONSE,
- };
+ struct ps3_sys_manager_header header;
struct {
u8 version;
u8 reserved_1[3];
@@ -344,6 +376,12 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
(status ? "nak" : "ack"));
+ memset(&header, 0, sizeof(header));
+ header.version = 1;
+ header.size = 16;
+ header.payload_size = 16;
+ header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
+
memset(&payload, 0, sizeof(payload));
payload.version = 1;
payload.status = status;
@@ -356,7 +394,7 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
*
*/
-static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
{
int result;
struct {
@@ -370,7 +408,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
BUILD_BUG_ON(sizeof(event) != 16);
result = ps3_vuart_read(dev, &event, sizeof(event));
- BUG_ON(result);
+ BUG_ON(result && "need to retry here");
if (event.version != 1) {
dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
@@ -382,11 +420,34 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
case PS3_SM_EVENT_POWER_PRESSED:
dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
__func__, __LINE__);
+ ps3_sm_force_power_off = 1;
+ /*
+ * A memory barrier is use here to sync memory since
+ * ps3_sys_manager_final_restart() could be called on
+ * another cpu.
+ */
+ wmb();
+ kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
break;
case PS3_SM_EVENT_POWER_RELEASED:
dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
__func__, __LINE__, event.value);
- kill_cad_pid(SIGINT, 1);
+ break;
+ case PS3_SM_EVENT_RESET_PRESSED:
+ dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
+ __func__, __LINE__);
+ ps3_sm_force_power_off = 0;
+ /*
+ * A memory barrier is use here to sync memory since
+ * ps3_sys_manager_final_restart() could be called on
+ * another cpu.
+ */
+ wmb();
+ kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
+ break;
+ case PS3_SM_EVENT_RESET_RELEASED:
+ dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
+ __func__, __LINE__, event.value);
break;
case PS3_SM_EVENT_THERMAL_ALERT:
dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
@@ -411,7 +472,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
* The system manager sends this in reply to a 'request' message from the guest.
*/
-static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
{
int result;
struct {
@@ -425,6 +486,7 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+ BUG_ON(result && "need to retry here");
if(result)
return result;
@@ -448,9 +510,10 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
/**
* ps3_sys_manager_handle_msg - First stage msg handler.
*
+ * Can be called directly to manually poll vuart and pump message handler.
*/
-static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
{
int result;
struct ps3_sys_manager_header header;
@@ -464,12 +527,17 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
if (header.version != 1) {
dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
__func__, __LINE__, header.version);
+ dump_sm_header(&header);
goto fail_header;
}
BUILD_BUG_ON(sizeof(header) != 16);
- BUG_ON(header.size != 16);
- BUG_ON(header.payload_size != 16);
+
+ if (header.size != 16 || (header.payload_size != 8
+ && header.payload_size != 16)) {
+ dump_sm_header(&header);
+ BUG();
+ }
switch (header.service_id) {
case PS3_SM_SERVICE_ID_EXTERN_EVENT:
@@ -478,6 +546,11 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
case PS3_SM_SERVICE_ID_COMMAND:
dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
return ps3_sys_manager_handle_cmd(dev);
+ case PS3_SM_SERVICE_ID_REQUEST_ERROR:
+ dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
+ __LINE__);
+ dump_sm_header(&header);
+ break;
default:
dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
__func__, __LINE__, header.service_id);
@@ -494,45 +567,25 @@ fail_id:
}
/**
- * ps3_sys_manager_work - Asyncronous read handler.
- *
- * Signaled when a complete message arrives at the vuart port.
- */
-
-static void ps3_sys_manager_work(struct work_struct *work)
-{
- struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
-
- ps3_sys_manager_handle_msg(dev);
- ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
-}
-
-struct {
- struct ps3_vuart_port_device *dev;
-} static drv_priv;
-
-/**
- * ps3_sys_manager_restart - The final platform machine_restart routine.
+ * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
*
- * This routine never returns. The routine disables asyncronous vuart reads
+ * This routine never returns. The routine disables asynchronous vuart reads
* then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
* the shutdown command sent from the system manager. Soon after the
* acknowledgement is sent the lpar is destroyed by the HV. This routine
- * should only be called from ps3_restart().
+ * should only be called from ps3_power_off() through
+ * ps3_sys_manager_ops.power_off.
*/
-void ps3_sys_manager_restart(void)
+static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
{
- struct ps3_vuart_port_device *dev = drv_priv.dev;
-
- BUG_ON(!drv_priv.dev);
+ BUG_ON(!dev);
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
ps3_vuart_cancel_async(dev);
- ps3_sys_manager_send_attr(dev, 0);
- ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+ ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
PS3_SM_WAKE_DEFAULT);
ps3_sys_manager_send_request_shutdown(dev);
@@ -543,26 +596,33 @@ void ps3_sys_manager_restart(void)
}
/**
- * ps3_sys_manager_power_off - The final platform machine_power_off routine.
+ * ps3_sys_manager_final_restart - The final platform machine_restart routine.
*
- * This routine never returns. The routine disables asyncronous vuart reads
+ * This routine never returns. The routine disables asynchronous vuart reads
* then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
* the shutdown command sent from the system manager. Soon after the
* acknowledgement is sent the lpar is destroyed by the HV. This routine
- * should only be called from ps3_power_off().
+ * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
*/
-void ps3_sys_manager_power_off(void)
+static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
{
- struct ps3_vuart_port_device *dev = drv_priv.dev;
-
- BUG_ON(!drv_priv.dev);
+ BUG_ON(!dev);
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+ /* Check if we got here via a power button event. */
+
+ if (ps3_sm_force_power_off) {
+ dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
+ __func__, __LINE__);
+ ps3_sys_manager_final_power_off(dev);
+ }
+
ps3_vuart_cancel_async(dev);
- ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+ ps3_sys_manager_send_attr(dev, 0);
+ ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
PS3_SM_WAKE_DEFAULT);
ps3_sys_manager_send_request_shutdown(dev);
@@ -572,31 +632,60 @@ void ps3_sys_manager_power_off(void)
ps3_sys_manager_handle_msg(dev);
}
-static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+/**
+ * ps3_sys_manager_work - Asynchronous read handler.
+ *
+ * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
+{
+ ps3_sys_manager_handle_msg(dev);
+ ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
+}
+
+static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
{
int result;
+ struct ps3_sys_manager_ops ops;
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
- BUG_ON(drv_priv.dev);
- drv_priv.dev = dev;
+ ops.power_off = ps3_sys_manager_final_power_off;
+ ops.restart = ps3_sys_manager_final_restart;
+ ops.dev = dev;
+
+ /* ps3_sys_manager_register_ops copies ops. */
+
+ ps3_sys_manager_register_ops(&ops);
result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
BUG_ON(result);
- result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
- PS3_SM_RX_MSG_LEN);
+ result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
BUG_ON(result);
return result;
}
+static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
+{
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+ return 0;
+}
+
+static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
+{
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+}
+
static struct ps3_vuart_port_driver ps3_sys_manager = {
- .match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
- .core = {
- .name = "ps3_sys_manager",
- },
+ .core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+ .core.core.name = "ps3_sys_manager",
.probe = ps3_sys_manager_probe,
+ .remove = ps3_sys_manager_remove,
+ .shutdown = ps3_sys_manager_shutdown,
+ .work = ps3_sys_manager_work,
};
static int __init ps3_sys_manager_init(void)
@@ -608,3 +697,6 @@ static int __init ps3_sys_manager_init(void)
}
module_init(ps3_sys_manager_init);
+/* Module remove not supported. */
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index ec2d36a1bc67..bea25a1391ee 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -71,6 +71,34 @@ enum vuart_interrupt_mask {
};
/**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+ u64 interrupt_mask;
+
+ struct {
+ spinlock_t lock;
+ struct list_head head;
+ } tx_list;
+ struct {
+ struct ps3_vuart_work work;
+ unsigned long bytes_held;
+ spinlock_t lock;
+ struct list_head head;
+ } rx_list;
+ struct ps3_vuart_stats stats;
+};
+
+static struct ps3_vuart_port_priv *to_port_priv(
+ struct ps3_system_bus_device *dev)
+{
+ BUG_ON(!dev);
+ BUG_ON(!dev->driver_priv);
+ return (struct ps3_vuart_port_priv *)dev->driver_priv;
+}
+
+/**
* struct ports_bmp - bitmap indicating ports needing service.
*
* A 256 bit read only bitmap indicating ports needing service. Do not write
@@ -83,31 +111,14 @@ struct ports_bmp {
} __attribute__ ((aligned (32)));
#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_ports_bmp(
+static void __maybe_unused _dump_ports_bmp(
const struct ports_bmp* bmp, const char* func, int line)
{
pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
}
-static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
- unsigned int *port_number)
-{
- switch(match_id) {
- case PS3_MATCH_ID_AV_SETTINGS:
- *port_number = 0;
- return 0;
- case PS3_MATCH_ID_SYSTEM_MANAGER:
- *port_number = 2;
- return 0;
- default:
- WARN_ON(1);
- *port_number = UINT_MAX;
- return -EINVAL;
- };
-}
-
#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+static void __maybe_unused _dump_port_params(unsigned int port_number,
const char* func, int line)
{
#if defined(DEBUG)
@@ -144,14 +155,14 @@ struct vuart_triggers {
unsigned long tx;
};
-int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
struct vuart_triggers *trig)
{
int result;
unsigned long size;
unsigned long val;
- result = lv1_get_virtual_uart_param(dev->priv->port_number,
+ result = lv1_get_virtual_uart_param(dev->port_number,
PARAM_TX_TRIGGER, &trig->tx);
if (result) {
@@ -160,7 +171,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
return result;
}
- result = lv1_get_virtual_uart_param(dev->priv->port_number,
+ result = lv1_get_virtual_uart_param(dev->port_number,
PARAM_RX_BUF_SIZE, &size);
if (result) {
@@ -169,7 +180,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
return result;
}
- result = lv1_get_virtual_uart_param(dev->priv->port_number,
+ result = lv1_get_virtual_uart_param(dev->port_number,
PARAM_RX_TRIGGER, &val);
if (result) {
@@ -186,13 +197,13 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
return result;
}
-int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
unsigned int rx)
{
int result;
unsigned long size;
- result = lv1_set_virtual_uart_param(dev->priv->port_number,
+ result = lv1_set_virtual_uart_param(dev->port_number,
PARAM_TX_TRIGGER, tx);
if (result) {
@@ -201,7 +212,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
return result;
}
- result = lv1_get_virtual_uart_param(dev->priv->port_number,
+ result = lv1_get_virtual_uart_param(dev->port_number,
PARAM_RX_BUF_SIZE, &size);
if (result) {
@@ -210,7 +221,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
return result;
}
- result = lv1_set_virtual_uart_param(dev->priv->port_number,
+ result = lv1_set_virtual_uart_param(dev->port_number,
PARAM_RX_TRIGGER, size - rx);
if (result) {
@@ -225,10 +236,12 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
return result;
}
-static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
u64 *bytes_waiting)
{
- int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+ int result;
+
+ result = lv1_get_virtual_uart_param(dev->port_number,
PARAM_RX_BYTES, bytes_waiting);
if (result)
@@ -240,17 +253,24 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
return result;
}
-static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+/**
+ * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
+ */
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
unsigned long mask)
{
int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
- dev->priv->interrupt_mask = mask;
+ priv->interrupt_mask = mask;
- result = lv1_set_virtual_uart_param(dev->priv->port_number,
- PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
+ result = lv1_set_virtual_uart_param(dev->port_number,
+ PARAM_INTERRUPT_MASK, priv->interrupt_mask);
if (result)
dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
return result;
}
-static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
unsigned long *status)
{
+ int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
u64 tmp;
- int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+
+ result = lv1_get_virtual_uart_param(dev->port_number,
PARAM_INTERRUPT_STATUS, &tmp);
if (result)
dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
__func__, __LINE__, ps3_result(result));
- *status = tmp & dev->priv->interrupt_mask;
+ *status = tmp & priv->interrupt_mask;
dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
- __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
+ __func__, __LINE__, priv->interrupt_mask, tmp, *status);
return result;
}
-int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
{
- return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
- : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+ return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
| INTERRUPT_MASK_TX);
}
-int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
{
- return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
- : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+ return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
| INTERRUPT_MASK_RX);
}
-int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
{
- return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
- : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+ return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
| INTERRUPT_MASK_DISCONNECT);
}
-int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
{
- return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
- ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+ return (priv->interrupt_mask & INTERRUPT_MASK_TX)
+ ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
& ~INTERRUPT_MASK_TX) : 0;
}
-int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
{
- return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
- ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+ return (priv->interrupt_mask & INTERRUPT_MASK_RX)
+ ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
& ~INTERRUPT_MASK_RX) : 0;
}
-int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
{
- return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
- ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+ return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+ ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
& ~INTERRUPT_MASK_DISCONNECT) : 0;
}
/**
* ps3_vuart_raw_write - Low level write helper.
+ * @dev: The struct ps3_system_bus_device instance.
*
* Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
*/
-static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
const void* buf, unsigned int bytes, unsigned long *bytes_written)
{
int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
- result = lv1_write_virtual_uart(dev->priv->port_number,
+ result = lv1_write_virtual_uart(dev->port_number,
ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
if (result) {
@@ -340,28 +377,30 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
return result;
}
- dev->priv->stats.bytes_written += *bytes_written;
+ priv->stats.bytes_written += *bytes_written;
dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
- *bytes_written, bytes, dev->priv->stats.bytes_written);
+ *bytes_written, bytes, priv->stats.bytes_written);
return result;
}
/**
* ps3_vuart_raw_read - Low level read helper.
+ * @dev: The struct ps3_system_bus_device instance.
*
* Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
*/
-static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
unsigned int bytes, unsigned long *bytes_read)
{
int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
- result = lv1_read_virtual_uart(dev->priv->port_number,
+ result = lv1_read_virtual_uart(dev->port_number,
ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
if (result) {
@@ -370,25 +409,27 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
return result;
}
- dev->priv->stats.bytes_read += *bytes_read;
+ priv->stats.bytes_read += *bytes_read;
dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
- *bytes_read, bytes, dev->priv->stats.bytes_read);
+ *bytes_read, bytes, priv->stats.bytes_read);
return result;
}
/**
* ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @dev: The struct ps3_system_bus_device instance.
* @bytes: Max byte count to discard, zero = all pending.
*
* Used to clear pending rx interrupt source. Will not block.
*/
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
unsigned int bytes)
{
int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
u64 bytes_waiting;
void* tmp;
@@ -418,8 +459,9 @@ void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
/* Don't include these bytes in the stats. */
- dev->priv->stats.bytes_read -= bytes_waiting;
+ priv->stats.bytes_read -= bytes_waiting;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
/**
* struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@ struct list_buffer {
/**
* ps3_vuart_write - the entry point for writing data to a port
+ * @dev: The struct ps3_system_bus_device instance.
*
* If the port is idle on entry as much of the incoming data is written to
* the port as the port will accept. Otherwise a list buffer is created
@@ -442,25 +485,26 @@ struct list_buffer {
* then enqueued for transmision via the transmit interrupt.
*/
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
unsigned int bytes)
{
static unsigned long dbg_number;
int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
unsigned long flags;
struct list_buffer *lb;
dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
bytes, bytes);
- spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+ spin_lock_irqsave(&priv->tx_list.lock, flags);
- if (list_empty(&dev->priv->tx_list.head)) {
+ if (list_empty(&priv->tx_list.head)) {
unsigned long bytes_written;
result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
- spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+ spin_unlock_irqrestore(&priv->tx_list.lock, flags);
if (result) {
dev_dbg(&dev->core,
@@ -478,7 +522,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
bytes -= bytes_written;
buf += bytes_written;
} else
- spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+ spin_unlock_irqrestore(&priv->tx_list.lock, flags);
lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
@@ -491,29 +535,86 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
lb->tail = lb->data + bytes;
lb->dbg_number = ++dbg_number;
- spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
- list_add_tail(&lb->link, &dev->priv->tx_list.head);
+ spin_lock_irqsave(&priv->tx_list.lock, flags);
+ list_add_tail(&lb->link, &priv->tx_list.head);
ps3_vuart_enable_interrupt_tx(dev);
- spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+ spin_unlock_irqrestore(&priv->tx_list.lock, flags);
dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
__func__, __LINE__, lb->dbg_number, bytes);
return 0;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_write);
+
+/**
+ * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bytes_queued: Number of bytes queued to the buffer list.
+ *
+ * Must be called with priv->rx_list.lock held.
+ */
+
+static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
+ u64 *bytes_queued)
+{
+ static unsigned long dbg_number;
+ int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+ struct list_buffer *lb;
+ u64 bytes;
+
+ *bytes_queued = 0;
+
+ result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+ BUG_ON(result);
+
+ if (result)
+ return -EIO;
+
+ if (!bytes)
+ return 0;
+
+ /* Add some extra space for recently arrived data. */
+
+ bytes += 128;
+
+ lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+ if (!lb)
+ return -ENOMEM;
+
+ ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+ lb->head = lb->data;
+ lb->tail = lb->data + bytes;
+ lb->dbg_number = ++dbg_number;
+
+ list_add_tail(&lb->link, &priv->rx_list.head);
+ priv->rx_list.bytes_held += bytes;
+
+ dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
+ __func__, __LINE__, lb->dbg_number, bytes);
+
+ *bytes_queued = bytes;
+
+ return 0;
+}
/**
- * ps3_vuart_read - the entry point for reading data from a port
+ * ps3_vuart_read - The entry point for reading data from a port.
*
- * If enough bytes to satisfy the request are held in the buffer list those
- * bytes are dequeued and copied to the caller's buffer. Emptied list buffers
- * are retiered. If the request cannot be statified by bytes held in the list
- * buffers -EAGAIN is returned.
+ * Queue data waiting at the port, and if enough bytes to satisfy the request
+ * are held in the buffer list those bytes are dequeued and copied to the
+ * caller's buffer. Emptied list buffers are retiered. If the request cannot
+ * be statified by bytes held in the list buffers -EAGAIN is returned.
*/
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
unsigned int bytes)
{
+ int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
unsigned long flags;
struct list_buffer *lb, *n;
unsigned long bytes_read;
@@ -521,30 +622,37 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
bytes, bytes);
- spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+ spin_lock_irqsave(&priv->rx_list.lock, flags);
- if (dev->priv->rx_list.bytes_held < bytes) {
- spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
- dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
- __func__, __LINE__,
- bytes - dev->priv->rx_list.bytes_held);
- return -EAGAIN;
+ /* Queue rx bytes here for polled reads. */
+
+ while (priv->rx_list.bytes_held < bytes) {
+ u64 tmp;
+
+ result = ps3_vuart_queue_rx_bytes(dev, &tmp);
+ if (result || !tmp) {
+ dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+ __func__, __LINE__,
+ bytes - priv->rx_list.bytes_held);
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+ return -EAGAIN;
+ }
}
- list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
+ list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
memcpy(buf, lb->head, bytes_read);
buf += bytes_read;
bytes -= bytes_read;
- dev->priv->rx_list.bytes_held -= bytes_read;
+ priv->rx_list.bytes_held -= bytes_read;
if (bytes_read < lb->tail - lb->head) {
lb->head += bytes_read;
dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
"bytes\n", __func__, __LINE__, lb->dbg_number,
bytes_read);
- spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
return 0;
}
@@ -556,16 +664,32 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
kfree(lb);
}
- spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_read);
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
- unsigned int bytes)
+/**
+ * ps3_vuart_work - Asynchronous read handler.
+ */
+
+static void ps3_vuart_work(struct work_struct *work)
+{
+ struct ps3_system_bus_device *dev =
+ ps3_vuart_work_to_system_bus_dev(work);
+ struct ps3_vuart_port_driver *drv =
+ ps3_system_bus_dev_to_vuart_drv(dev);
+
+ BUG_ON(!drv);
+ drv->work(dev);
+}
+
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
{
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
unsigned long flags;
- if(dev->priv->work.trigger) {
+ if (priv->rx_list.work.trigger) {
dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
__func__, __LINE__);
return -EAGAIN;
@@ -573,30 +697,32 @@ int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
BUG_ON(!bytes);
- PREPARE_WORK(&dev->priv->work.work, func);
+ PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
- spin_lock_irqsave(&dev->priv->work.lock, flags);
- if(dev->priv->rx_list.bytes_held >= bytes) {
+ spin_lock_irqsave(&priv->rx_list.lock, flags);
+ if (priv->rx_list.bytes_held >= bytes) {
dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
__func__, __LINE__, bytes);
- schedule_work(&dev->priv->work.work);
- spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+ schedule_work(&priv->rx_list.work.work);
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
return 0;
}
- dev->priv->work.trigger = bytes;
- spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+ priv->rx_list.work.trigger = bytes;
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
__LINE__, bytes, bytes);
return 0;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
{
- dev->priv->work.trigger = 0;
+ to_port_priv(dev)->rx_list.work.trigger = 0;
}
+EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
/**
* ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@ void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
* adjusts the final list buffer state for a partial write.
*/
-static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
{
int result = 0;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
unsigned long flags;
struct list_buffer *lb, *n;
unsigned long bytes_total = 0;
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
- spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+ spin_lock_irqsave(&priv->tx_list.lock, flags);
- list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
+ list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
unsigned long bytes_written;
@@ -651,7 +778,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
ps3_vuart_disable_interrupt_tx(dev);
port_full:
- spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+ spin_unlock_irqrestore(&priv->tx_list.lock, flags);
dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
__func__, __LINE__, bytes_total);
return result;
@@ -665,60 +792,37 @@ port_full:
* buffer list. Buffer list data is dequeued via ps3_vuart_read.
*/
-static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
{
- static unsigned long dbg_number;
- int result = 0;
+ int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
unsigned long flags;
- struct list_buffer *lb;
- unsigned long bytes;
+ u64 bytes;
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
- result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
-
- if (result)
- return -EIO;
-
- BUG_ON(!bytes);
-
- /* Add some extra space for recently arrived data. */
-
- bytes += 128;
-
- lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+ spin_lock_irqsave(&priv->rx_list.lock, flags);
+ result = ps3_vuart_queue_rx_bytes(dev, &bytes);
- if (!lb)
- return -ENOMEM;
-
- ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
-
- lb->head = lb->data;
- lb->tail = lb->data + bytes;
- lb->dbg_number = ++dbg_number;
-
- spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
- list_add_tail(&lb->link, &dev->priv->rx_list.head);
- dev->priv->rx_list.bytes_held += bytes;
- spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-
- dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
- __func__, __LINE__, lb->dbg_number, bytes);
+ if (result) {
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+ return result;
+ }
- spin_lock_irqsave(&dev->priv->work.lock, flags);
- if(dev->priv->work.trigger
- && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
+ if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
+ >= priv->rx_list.work.trigger) {
dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
- __func__, __LINE__, dev->priv->work.trigger);
- dev->priv->work.trigger = 0;
- schedule_work(&dev->priv->work.work);
+ __func__, __LINE__, priv->rx_list.work.trigger);
+ priv->rx_list.work.trigger = 0;
+ schedule_work(&priv->rx_list.work.work);
}
- spin_unlock_irqrestore(&dev->priv->work.lock, flags);
- return 0;
+
+ spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+ return result;
}
static int ps3_vuart_handle_interrupt_disconnect(
- struct ps3_vuart_port_device *dev)
+ struct ps3_system_bus_device *dev)
{
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
BUG_ON("no support");
@@ -733,9 +837,10 @@ static int ps3_vuart_handle_interrupt_disconnect(
* stage handler after one iteration.
*/
-static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
{
int result;
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
unsigned long status;
result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
status);
if (status & INTERRUPT_MASK_DISCONNECT) {
- dev->priv->stats.disconnect_interrupts++;
+ priv->stats.disconnect_interrupts++;
result = ps3_vuart_handle_interrupt_disconnect(dev);
if (result)
ps3_vuart_disable_interrupt_disconnect(dev);
}
if (status & INTERRUPT_MASK_TX) {
- dev->priv->stats.tx_interrupts++;
+ priv->stats.tx_interrupts++;
result = ps3_vuart_handle_interrupt_tx(dev);
if (result)
ps3_vuart_disable_interrupt_tx(dev);
}
if (status & INTERRUPT_MASK_RX) {
- dev->priv->stats.rx_interrupts++;
+ priv->stats.rx_interrupts++;
result = ps3_vuart_handle_interrupt_rx(dev);
if (result)
ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
}
struct vuart_bus_priv {
- const struct ports_bmp bmp;
+ struct ports_bmp *bmp;
unsigned int virq;
struct semaphore probe_mutex;
int use_count;
- struct ps3_vuart_port_device *devices[PORT_COUNT];
+ struct ps3_system_bus_device *devices[PORT_COUNT];
} static vuart_bus_priv;
/**
@@ -788,17 +893,16 @@ struct vuart_bus_priv {
static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
{
- struct vuart_bus_priv *bus_priv;
+ struct vuart_bus_priv *bus_priv = _private;
- BUG_ON(!_private);
- bus_priv = (struct vuart_bus_priv *)_private;
+ BUG_ON(!bus_priv);
while (1) {
unsigned int port;
- dump_ports_bmp(&bus_priv->bmp);
+ dump_ports_bmp(bus_priv->bmp);
- port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
+ port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
if (port == BITS_PER_LONG)
break;
@@ -812,100 +916,144 @@ static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
return IRQ_HANDLED;
}
-static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+static int ps3_vuart_bus_interrupt_get(void)
{
int result;
- struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
- struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
- result = dev->match_id == drv->match_id;
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ vuart_bus_priv.use_count++;
+
+ BUG_ON(vuart_bus_priv.use_count > 2);
+
+ if (vuart_bus_priv.use_count != 1) {
+ return 0;
+ }
+
+ BUG_ON(vuart_bus_priv.bmp);
+
+ vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
+
+ if (!vuart_bus_priv.bmp) {
+ pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
+ result = -ENOMEM;
+ goto fail_bmp_malloc;
+ }
+
+ result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
+ &vuart_bus_priv.virq);
+
+ if (result) {
+ pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
+ __func__, __LINE__, result);
+ result = -EPERM;
+ goto fail_alloc_irq;
+ }
+
+ result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+ IRQF_DISABLED, "vuart", &vuart_bus_priv);
- dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
- __LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
- drv->core.name, (result ? "match" : "miss"));
+ if (result) {
+ pr_debug("%s:%d: request_irq failed (%d)\n",
+ __func__, __LINE__, result);
+ goto fail_request_irq;
+ }
+ pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
return result;
+
+fail_request_irq:
+ ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+ vuart_bus_priv.virq = NO_IRQ;
+fail_alloc_irq:
+ kfree(vuart_bus_priv.bmp);
+ vuart_bus_priv.bmp = NULL;
+fail_bmp_malloc:
+ vuart_bus_priv.use_count--;
+ pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
+ return result;
+}
+
+static int ps3_vuart_bus_interrupt_put(void)
+{
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ vuart_bus_priv.use_count--;
+
+ BUG_ON(vuart_bus_priv.use_count < 0);
+
+ if (vuart_bus_priv.use_count != 0)
+ return 0;
+
+ free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+
+ ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+ vuart_bus_priv.virq = NO_IRQ;
+
+ kfree(vuart_bus_priv.bmp);
+ vuart_bus_priv.bmp = NULL;
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return 0;
}
-static int ps3_vuart_probe(struct device *_dev)
+static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
{
int result;
- unsigned int port_number;
- struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
- struct ps3_vuart_port_driver *drv =
- to_ps3_vuart_port_driver(_dev->driver);
+ struct ps3_vuart_port_driver *drv;
+ struct ps3_vuart_port_priv *priv = NULL;
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+ drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+ dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+ drv->core.core.name);
+
BUG_ON(!drv);
- down(&vuart_bus_priv.probe_mutex);
+ if (dev->port_number >= PORT_COUNT) {
+ BUG();
+ return -EINVAL;
+ }
- /* Setup vuart_bus_priv.devices[]. */
+ down(&vuart_bus_priv.probe_mutex);
- result = ps3_vuart_match_id_to_port(dev->match_id,
- &port_number);
+ result = ps3_vuart_bus_interrupt_get();
- if (result) {
- dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
- __func__, __LINE__, dev->match_id);
- result = -EINVAL;
- goto fail_match;
- }
+ if (result)
+ goto fail_setup_interrupt;
- if (vuart_bus_priv.devices[port_number]) {
+ if (vuart_bus_priv.devices[dev->port_number]) {
dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
- __LINE__, port_number);
+ __LINE__, dev->port_number);
result = -EBUSY;
- goto fail_match;
+ goto fail_busy;
}
- vuart_bus_priv.devices[port_number] = dev;
+ vuart_bus_priv.devices[dev->port_number] = dev;
- /* Setup dev->priv. */
+ /* Setup dev->driver_priv. */
- dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+ dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
+ GFP_KERNEL);
- if (!dev->priv) {
+ if (!dev->driver_priv) {
result = -ENOMEM;
- goto fail_alloc;
+ goto fail_dev_malloc;
}
- dev->priv->port_number = port_number;
-
- INIT_LIST_HEAD(&dev->priv->tx_list.head);
- spin_lock_init(&dev->priv->tx_list.lock);
+ priv = to_port_priv(dev);
- INIT_LIST_HEAD(&dev->priv->rx_list.head);
- spin_lock_init(&dev->priv->rx_list.lock);
+ INIT_LIST_HEAD(&priv->tx_list.head);
+ spin_lock_init(&priv->tx_list.lock);
- INIT_WORK(&dev->priv->work.work, NULL);
- spin_lock_init(&dev->priv->work.lock);
- dev->priv->work.trigger = 0;
- dev->priv->work.dev = dev;
+ INIT_LIST_HEAD(&priv->rx_list.head);
+ spin_lock_init(&priv->rx_list.lock);
- if (++vuart_bus_priv.use_count == 1) {
-
- result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
- (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
-
- if (result) {
- dev_dbg(&dev->core,
- "%s:%d: ps3_vuart_irq_setup failed (%d)\n",
- __func__, __LINE__, result);
- result = -EPERM;
- goto fail_alloc_irq;
- }
-
- result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
- IRQF_DISABLED, "vuart", &vuart_bus_priv);
-
- if (result) {
- dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
- __func__, __LINE__, result);
- goto fail_request_irq;
- }
- }
+ INIT_WORK(&priv->rx_list.work.work, NULL);
+ priv->rx_list.work.trigger = 0;
+ priv->rx_list.work.dev = dev;
/* clear stale pending interrupts */
@@ -936,150 +1084,158 @@ static int ps3_vuart_probe(struct device *_dev)
fail_probe:
ps3_vuart_set_interrupt_mask(dev, 0);
-fail_request_irq:
- ps3_vuart_irq_destroy(vuart_bus_priv.virq);
- vuart_bus_priv.virq = NO_IRQ;
-fail_alloc_irq:
- --vuart_bus_priv.use_count;
- kfree(dev->priv);
- dev->priv = NULL;
-fail_alloc:
- vuart_bus_priv.devices[port_number] = NULL;
-fail_match:
+ kfree(dev->driver_priv);
+ dev->driver_priv = NULL;
+fail_dev_malloc:
+ vuart_bus_priv.devices[dev->port_number] = NULL;
+fail_busy:
+ ps3_vuart_bus_interrupt_put();
+fail_setup_interrupt:
up(&vuart_bus_priv.probe_mutex);
- dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+ dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
return result;
}
-static int ps3_vuart_remove(struct device *_dev)
+/**
+ * ps3_vuart_cleanup - common cleanup helper.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources. Must be called with
+ * vuart_bus_priv.probe_mutex held. Used by ps3_vuart_remove and
+ * ps3_vuart_shutdown. After this call, polled reading will still work.
+ */
+
+static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
{
- struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
- struct ps3_vuart_port_driver *drv =
- to_ps3_vuart_port_driver(_dev->driver);
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ ps3_vuart_cancel_async(dev);
+ ps3_vuart_set_interrupt_mask(dev, 0);
+ ps3_vuart_bus_interrupt_put();
+ return 0;
+}
+
+/**
+ * ps3_vuart_remove - Completely clean the device instance.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans all memory, interrupts and HV resources. After this call the
+ * device can no longer be used.
+ */
+
+static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
+{
+ struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+ struct ps3_vuart_port_driver *drv;
+
+ BUG_ON(!dev);
down(&vuart_bus_priv.probe_mutex);
- dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
- dev->core.bus_id);
+ dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+ dev->match_id);
- BUG_ON(vuart_bus_priv.use_count < 1);
+ if (!dev->core.driver) {
+ dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+ __LINE__);
+ up(&vuart_bus_priv.probe_mutex);
+ return 0;
+ }
- if (drv->remove)
- drv->remove(dev);
- else
- dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
- __LINE__, dev->core.bus_id);
+ drv = ps3_system_bus_dev_to_vuart_drv(dev);
- vuart_bus_priv.devices[dev->priv->port_number] = NULL;
+ BUG_ON(!drv);
- if (--vuart_bus_priv.use_count == 0) {
+ if (drv->remove) {
+ drv->remove(dev);
+ } else {
+ dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
+ __LINE__);
BUG();
- free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
- ps3_vuart_irq_destroy(vuart_bus_priv.virq);
- vuart_bus_priv.virq = NO_IRQ;
}
- kfree(dev->priv);
- dev->priv = NULL;
+ ps3_vuart_cleanup(dev);
+
+ vuart_bus_priv.devices[dev->port_number] = NULL;
+ kfree(priv);
+ priv = NULL;
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
up(&vuart_bus_priv.probe_mutex);
return 0;
}
-static void ps3_vuart_shutdown(struct device *_dev)
-{
- struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
- struct ps3_vuart_port_driver *drv =
- to_ps3_vuart_port_driver(_dev->driver);
-
- dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
- dev->core.bus_id);
-
- if (drv->shutdown)
- drv->shutdown(dev);
- else
- dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
- __LINE__, dev->core.bus_id);
-}
-
/**
- * ps3_vuart_bus - The vuart bus instance.
+ * ps3_vuart_shutdown - Cleans interrupts and HV resources.
+ * @dev: The struct ps3_system_bus_device instance.
*
- * The vuart is managed as a bus that port devices connect to.
+ * Cleans interrupts and HV resources. After this call the
+ * device can still be used in polling mode. This behavior required
+ * by sys-manager to be able to complete the device power operation
+ * sequence.
*/
-struct bus_type ps3_vuart_bus = {
- .name = "ps3_vuart",
- .match = ps3_vuart_match,
- .probe = ps3_vuart_probe,
- .remove = ps3_vuart_remove,
- .shutdown = ps3_vuart_shutdown,
-};
-
-int __init ps3_vuart_bus_init(void)
+static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
{
- int result;
+ struct ps3_vuart_port_driver *drv;
- pr_debug("%s:%d:\n", __func__, __LINE__);
+ BUG_ON(!dev);
- if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
- return -ENODEV;
+ down(&vuart_bus_priv.probe_mutex);
- init_MUTEX(&vuart_bus_priv.probe_mutex);
- result = bus_register(&ps3_vuart_bus);
- BUG_ON(result);
+ dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+ dev->match_id);
- return result;
-}
+ if (!dev->core.driver) {
+ dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+ __LINE__);
+ up(&vuart_bus_priv.probe_mutex);
+ return 0;
+ }
-void __exit ps3_vuart_bus_exit(void)
-{
- pr_debug("%s:%d:\n", __func__, __LINE__);
- bus_unregister(&ps3_vuart_bus);
-}
+ drv = ps3_system_bus_dev_to_vuart_drv(dev);
-core_initcall(ps3_vuart_bus_init);
-module_exit(ps3_vuart_bus_exit);
+ BUG_ON(!drv);
-/**
- * ps3_vuart_port_release_device - Remove a vuart port device.
- */
+ if (drv->shutdown)
+ drv->shutdown(dev);
+ else if (drv->remove) {
+ dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
+ __func__, __LINE__);
+ drv->remove(dev);
+ } else {
+ dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
+ __LINE__);
+ BUG();
+ }
-static void ps3_vuart_port_release_device(struct device *_dev)
-{
-#if defined(DEBUG)
- struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+ ps3_vuart_cleanup(dev);
- dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+ dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
- BUG_ON(dev->priv && "forgot to free");
- memset(&dev->core, 0, sizeof(dev->core));
-#endif
+ up(&vuart_bus_priv.probe_mutex);
+ return 0;
}
-/**
- * ps3_vuart_port_device_register - Add a vuart port device.
- */
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
+static int __init ps3_vuart_bus_init(void)
{
- static unsigned int dev_count = 1;
-
- BUG_ON(dev->priv && "forgot to free");
+ pr_debug("%s:%d:\n", __func__, __LINE__);
- dev->core.parent = NULL;
- dev->core.bus = &ps3_vuart_bus;
- dev->core.release = ps3_vuart_port_release_device;
+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return -ENODEV;
- snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
- dev_count++);
+ init_MUTEX(&vuart_bus_priv.probe_mutex);
- dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
+ return 0;
+}
- return device_register(&dev->core);
+static void __exit ps3_vuart_bus_exit(void)
+{
+ pr_debug("%s:%d:\n", __func__, __LINE__);
}
-EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
+core_initcall(ps3_vuart_bus_init);
+module_exit(ps3_vuart_bus_exit);
/**
* ps3_vuart_port_driver_register - Add a vuart port device driver.
@@ -1089,12 +1245,18 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
{
int result;
- pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
- drv->core.bus = &ps3_vuart_bus;
- result = driver_register(&drv->core);
+ pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+
+ BUG_ON(!drv->core.match_id);
+ BUG_ON(!drv->core.core.name);
+
+ drv->core.probe = ps3_vuart_probe;
+ drv->core.remove = ps3_vuart_remove;
+ drv->core.shutdown = ps3_vuart_shutdown;
+
+ result = ps3_system_bus_driver_register(&drv->core);
return result;
}
-
EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
/**
@@ -1103,8 +1265,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
{
- pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
- driver_unregister(&drv->core);
+ pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+ ps3_system_bus_driver_unregister(&drv->core);
}
-
EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 1be992d568c8..eb7f6d94a890 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -34,29 +34,7 @@ struct ps3_vuart_stats {
struct ps3_vuart_work {
struct work_struct work;
unsigned long trigger;
- spinlock_t lock;
- struct ps3_vuart_port_device* dev; /* to convert work to device */
-};
-
-/**
- * struct ps3_vuart_port_priv - private vuart device data.
- */
-
-struct ps3_vuart_port_priv {
- unsigned int port_number;
- u64 interrupt_mask;
-
- struct {
- spinlock_t lock;
- struct list_head head;
- } tx_list;
- struct {
- unsigned long bytes_held;
- spinlock_t lock;
- struct list_head head;
- } rx_list;
- struct ps3_vuart_stats stats;
- struct ps3_vuart_work work;
+ struct ps3_system_bus_device *dev; /* to convert work to device */
};
/**
@@ -64,32 +42,30 @@ struct ps3_vuart_port_priv {
*/
struct ps3_vuart_port_driver {
- enum ps3_match_id match_id;
- struct device_driver core;
- int (*probe)(struct ps3_vuart_port_device *);
- int (*remove)(struct ps3_vuart_port_device *);
- void (*shutdown)(struct ps3_vuart_port_device *);
- int (*tx_event)(struct ps3_vuart_port_device *dev);
- int (*rx_event)(struct ps3_vuart_port_device *dev);
- int (*disconnect_event)(struct ps3_vuart_port_device *dev);
- /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
- /* int (*resume)(struct ps3_vuart_port_device *); */
+ struct ps3_system_bus_driver core;
+ int (*probe)(struct ps3_system_bus_device *);
+ int (*remove)(struct ps3_system_bus_device *);
+ void (*shutdown)(struct ps3_system_bus_device *);
+ void (*work)(struct ps3_system_bus_device *);
+ /* int (*tx_event)(struct ps3_system_bus_device *dev); */
+ /* int (*rx_event)(struct ps3_system_bus_device *dev); */
+ /* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
+ /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
+ /* int (*resume)(struct ps3_system_bus_device *); */
};
int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
-static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
- struct device_driver *_drv)
-{
- return container_of(_drv, struct ps3_vuart_port_driver, core);
-}
-static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
- struct device *_dev)
+static inline struct ps3_vuart_port_driver *
+ ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
{
- return container_of(_dev, struct ps3_vuart_port_device, core);
+ struct ps3_system_bus_driver *sbd =
+ ps3_system_bus_dev_to_system_bus_drv(_dev);
+ BUG_ON(!sbd);
+ return container_of(sbd, struct ps3_vuart_port_driver, core);
}
-static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
struct work_struct *_work)
{
struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@ static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
return vw->dev;
}
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
- unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
unsigned int bytes);
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
unsigned int bytes);
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
unsigned int bytes);
#endif
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4e4c10a7fd3a..cea401feb0f3 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -10,7 +10,6 @@ config RTC_LIB
config RTC_CLASS
tristate "RTC class"
- depends on EXPERIMENTAL
default n
select RTC_LIB
help
@@ -119,7 +118,7 @@ config RTC_DRV_TEST
will be called rtc-test.
comment "I2C RTC drivers"
- depends on RTC_CLASS
+ depends on RTC_CLASS && I2C
config RTC_DRV_DS1307
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00"
@@ -160,11 +159,11 @@ config RTC_DRV_MAX6900
will be called rtc-max6900.
config RTC_DRV_RS5C372
- tristate "Ricoh RS5C372A/B"
+ tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A"
depends on RTC_CLASS && I2C
help
If you say yes here you get support for the
- Ricoh RS5C372A and RS5C372B RTC chips.
+ Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-rs5c372.
@@ -213,12 +212,40 @@ config RTC_DRV_PCF8583
This driver can also be built as a module. If so, the module
will be called rtc-pcf8583.
+config RTC_DRV_M41T80
+ tristate "ST M41T80 series RTC"
+ depends on RTC_CLASS && I2C
+ help
+ If you say Y here you will get support for the
+ ST M41T80 RTC chips series. Currently following chips are
+ supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85
+ and M41ST87.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-m41t80.
+
+config RTC_DRV_M41T80_WDT
+ bool "ST M41T80 series RTC watchdog timer"
+ depends on RTC_DRV_M41T80
+ help
+ If you say Y here you will get support for the
+ watchdog timer in ST M41T80 RTC chips series.
+
+config RTC_DRV_TWL92330
+ boolean "TI TWL92330/Menelaus"
+ depends on RTC_CLASS && I2C && MENELAUS
+ help
+ If you say yes here you get support for the RTC on the
+ TWL92330 "Menelaus" power mangement chip, used with OMAP2
+ platforms. The support is integrated with the rest of
+ the Menelaus driver; it's not separate module.
+
comment "SPI RTC drivers"
- depends on RTC_CLASS
+ depends on RTC_CLASS && SPI_MASTER
config RTC_DRV_RS5C348
tristate "Ricoh RS5C348A/B"
- depends on RTC_CLASS && SPI
+ depends on RTC_CLASS && SPI_MASTER
help
If you say yes here you get support for the
Ricoh RS5C348A and RS5C348B RTC chips.
@@ -228,7 +255,7 @@ config RTC_DRV_RS5C348
config RTC_DRV_MAX6902
tristate "Maxim 6902"
- depends on RTC_CLASS && SPI
+ depends on RTC_CLASS && SPI_MASTER
help
If you say yes here you will get support for the
Maxim MAX6902 SPI RTC chip.
@@ -246,7 +273,7 @@ comment "Platform RTC drivers"
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
- || M32R || ATARI || POWERPC || MIPS)
+ || M32R || ATARI || PPC || MIPS)
help
Say "yes" here to get direct support for the real time clock
found in every PC or ACPI-based system, and some other boards.
@@ -262,6 +289,12 @@ config RTC_DRV_CMOS
This driver can also be built as a module. If so, the module
will be called rtc-cmos.
+config RTC_DRV_DS1216
+ tristate "Dallas DS1216"
+ depends on RTC_CLASS && SNI_RM
+ help
+ If you say yes here you get support for the Dallas DS1216 RTC chips.
+
config RTC_DRV_DS1553
tristate "Dallas DS1553"
depends on RTC_CLASS
@@ -292,6 +325,16 @@ config RTC_DRV_M48T86
This driver can also be built as a module. If so, the module
will be called rtc-m48t86.
+config RTC_DRV_M48T59
+ tristate "ST M48T59"
+ depends on RTC_CLASS
+ help
+ If you say Y here you will get support for the
+ ST M48T59 RTC chip.
+
+ This driver can also be built as a module, if so, the module
+ will be called "rtc-m48t59".
+
config RTC_DRV_V3020
tristate "EM Microelectronic V3020"
depends on RTC_CLASS
@@ -379,6 +422,13 @@ config RTC_DRV_PL031
To compile this driver as a module, choose M here: the
module will be called rtc-pl031.
+config RTC_DRV_AT32AP700X
+ tristate "AT32AP700X series RTC"
+ depends on RTC_CLASS && PLATFORM_AT32AP
+ help
+ Driver for the internal RTC (Realtime Clock) on Atmel AVR32
+ AT32AP700x family processors.
+
config RTC_DRV_AT91RM9200
tristate "AT91RM9200"
depends on RTC_CLASS && ARCH_AT91RM9200
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index a1afbc236073..3109af9a1651 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
+obj-$(CONFIG_RTC_DRV_AT32AP700X) += rtc-at32ap700x.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
+obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
@@ -41,3 +43,5 @@ obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
+obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
+obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
new file mode 100644
index 000000000000..2999214ca534
--- /dev/null
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -0,0 +1,317 @@
+/*
+ * An RTC driver for the AVR32 AT32AP700x processor series.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/io.h>
+
+/*
+ * This is a bare-bones RTC. It runs during most system sleep states, but has
+ * no battery backup and gets reset during system restart. It must be
+ * initialized from an external clock (network, I2C, etc) before it can be of
+ * much use.
+ *
+ * The alarm functionality is limited by the hardware, not supporting
+ * periodic interrupts.
+ */
+
+#define RTC_CTRL 0x00
+#define RTC_CTRL_EN 0
+#define RTC_CTRL_PCLR 1
+#define RTC_CTRL_TOPEN 2
+#define RTC_CTRL_PSEL 8
+
+#define RTC_VAL 0x04
+
+#define RTC_TOP 0x08
+
+#define RTC_IER 0x10
+#define RTC_IER_TOPI 0
+
+#define RTC_IDR 0x14
+#define RTC_IDR_TOPI 0
+
+#define RTC_IMR 0x18
+#define RTC_IMR_TOPI 0
+
+#define RTC_ISR 0x1c
+#define RTC_ISR_TOPI 0
+
+#define RTC_ICR 0x20
+#define RTC_ICR_TOPI 0
+
+#define RTC_BIT(name) (1 << RTC_##name)
+#define RTC_BF(name, value) ((value) << RTC_##name)
+
+#define rtc_readl(dev, reg) \
+ __raw_readl((dev)->regs + RTC_##reg)
+#define rtc_writel(dev, reg, value) \
+ __raw_writel((value), (dev)->regs + RTC_##reg)
+
+struct rtc_at32ap700x {
+ struct rtc_device *rtc;
+ void __iomem *regs;
+ unsigned long alarm_time;
+ unsigned long irq;
+ /* Protect against concurrent register access. */
+ spinlock_t lock;
+};
+
+static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+ unsigned long now;
+
+ now = rtc_readl(rtc, VAL);
+ rtc_time_to_tm(now, tm);
+
+ return 0;
+}
+
+static int at32_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+ unsigned long now;
+ int ret;
+
+ ret = rtc_tm_to_time(tm, &now);
+ if (ret == 0)
+ rtc_writel(rtc, VAL, now);
+
+ return ret;
+}
+
+static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+
+ rtc_time_to_tm(rtc->alarm_time, &alrm->time);
+ alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0;
+
+ return 0;
+}
+
+static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+ unsigned long rtc_unix_time;
+ unsigned long alarm_unix_time;
+ int ret;
+
+ rtc_unix_time = rtc_readl(rtc, VAL);
+
+ ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time);
+ if (ret)
+ return ret;
+
+ if (alarm_unix_time < rtc_unix_time)
+ return -EINVAL;
+
+ spin_lock_irq(&rtc->lock);
+ rtc->alarm_time = alarm_unix_time;
+ rtc_writel(rtc, TOP, rtc->alarm_time);
+ if (alrm->pending)
+ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+ | RTC_BIT(CTRL_TOPEN));
+ else
+ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+ & ~RTC_BIT(CTRL_TOPEN));
+ spin_unlock_irq(&rtc->lock);
+
+ return ret;
+}
+
+static int at32_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ struct rtc_at32ap700x *rtc = dev_get_drvdata(dev);
+ int ret = 0;
+
+ spin_lock_irq(&rtc->lock);
+
+ switch (cmd) {
+ case RTC_AIE_ON:
+ if (rtc_readl(rtc, VAL) > rtc->alarm_time) {
+ ret = -EINVAL;
+ break;
+ }
+ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+ | RTC_BIT(CTRL_TOPEN));
+ rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+ rtc_writel(rtc, IER, RTC_BIT(IER_TOPI));
+ break;
+ case RTC_AIE_OFF:
+ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+ & ~RTC_BIT(CTRL_TOPEN));
+ rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+ rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+
+ spin_unlock_irq(&rtc->lock);
+
+ return ret;
+}
+
+static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
+{
+ struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id;
+ unsigned long isr = rtc_readl(rtc, ISR);
+ unsigned long events = 0;
+ int ret = IRQ_NONE;
+
+ spin_lock(&rtc->lock);
+
+ if (isr & RTC_BIT(ISR_TOPI)) {
+ rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI));
+ rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+ rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL)
+ & ~RTC_BIT(CTRL_TOPEN));
+ rtc_writel(rtc, VAL, rtc->alarm_time);
+ events = RTC_AF | RTC_IRQF;
+ rtc_update_irq(rtc->rtc, 1, events);
+ ret = IRQ_HANDLED;
+ }
+
+ spin_unlock(&rtc->lock);
+
+ return ret;
+}
+
+static struct rtc_class_ops at32_rtc_ops = {
+ .ioctl = at32_rtc_ioctl,
+ .read_time = at32_rtc_readtime,
+ .set_time = at32_rtc_settime,
+ .read_alarm = at32_rtc_readalarm,
+ .set_alarm = at32_rtc_setalarm,
+};
+
+static int __init at32_rtc_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+ struct rtc_at32ap700x *rtc;
+ int irq = -1;
+ int ret;
+
+ rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL);
+ if (!rtc) {
+ dev_dbg(&pdev->dev, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_dbg(&pdev->dev, "no mmio resource defined\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_dbg(&pdev->dev, "could not get irq\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
+ goto out;
+ }
+
+ rtc->irq = irq;
+ rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!rtc->regs) {
+ ret = -ENOMEM;
+ dev_dbg(&pdev->dev, "could not map I/O memory\n");
+ goto out_free_irq;
+ }
+ spin_lock_init(&rtc->lock);
+
+ /*
+ * Maybe init RTC: count from zero at 1 Hz, disable wrap irq.
+ *
+ * Do not reset VAL register, as it can hold an old time
+ * from last JTAG reset.
+ */
+ if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) {
+ rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR));
+ rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI));
+ rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe)
+ | RTC_BIT(CTRL_EN));
+ }
+
+ rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &at32_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc->rtc)) {
+ dev_dbg(&pdev->dev, "could not register rtc device\n");
+ ret = PTR_ERR(rtc->rtc);
+ goto out_iounmap;
+ }
+
+ platform_set_drvdata(pdev, rtc);
+
+ dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
+ (unsigned long)rtc->regs, rtc->irq);
+
+ return 0;
+
+out_iounmap:
+ iounmap(rtc->regs);
+out_free_irq:
+ free_irq(irq, rtc);
+out:
+ kfree(rtc);
+ return ret;
+}
+
+static int __exit at32_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_at32ap700x *rtc = platform_get_drvdata(pdev);
+
+ free_irq(rtc->irq, rtc);
+ iounmap(rtc->regs);
+ rtc_device_unregister(rtc->rtc);
+ kfree(rtc);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+MODULE_ALIAS("at32ap700x_rtc");
+
+static struct platform_driver at32_rtc_driver = {
+ .remove = __exit_p(at32_rtc_remove),
+ .driver = {
+ .name = "at32ap700x_rtc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at32_rtc_init(void)
+{
+ return platform_driver_probe(&at32_rtc_driver, at32_rtc_probe);
+}
+module_init(at32_rtc_init);
+
+static void __exit at32_rtc_exit(void)
+{
+ platform_driver_unregister(&at32_rtc_driver);
+}
+module_exit(at32_rtc_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index f4e5f0040ff7..304535942de2 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -341,6 +341,8 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
case RTC_IRQP_READ:
if (ops->irq_set_freq)
err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
+ else
+ err = -ENOTTY;
break;
case RTC_IRQP_SET:
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
new file mode 100644
index 000000000000..83efb88f8f23
--- /dev/null
+++ b/drivers/rtc/rtc-ds1216.c
@@ -0,0 +1,226 @@
+/*
+ * Dallas DS1216 RTC driver
+ *
+ * Copyright (c) 2007 Thomas Bogendoerfer
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+
+#define DRV_VERSION "0.1"
+
+struct ds1216_regs {
+ u8 tsec;
+ u8 sec;
+ u8 min;
+ u8 hour;
+ u8 wday;
+ u8 mday;
+ u8 month;
+ u8 year;
+};
+
+#define DS1216_HOUR_1224 (1 << 7)
+#define DS1216_HOUR_AMPM (1 << 5)
+
+struct ds1216_priv {
+ struct rtc_device *rtc;
+ void __iomem *ioaddr;
+ size_t size;
+ unsigned long baseaddr;
+};
+
+static const u8 magic[] = {
+ 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
+};
+
+/*
+ * Read the 64 bit we'd like to have - It a series
+ * of 64 bits showing up in the LSB of the base register.
+ *
+ */
+static void ds1216_read(u8 __iomem *ioaddr, u8 *buf)
+{
+ unsigned char c;
+ int i, j;
+
+ for (i = 0; i < 8; i++) {
+ c = 0;
+ for (j = 0; j < 8; j++)
+ c |= (readb(ioaddr) & 0x1) << j;
+ buf[i] = c;
+ }
+}
+
+static void ds1216_write(u8 __iomem *ioaddr, const u8 *buf)
+{
+ unsigned char c;
+ int i, j;
+
+ for (i = 0; i < 8; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ writeb(c, ioaddr);
+ c = c >> 1;
+ }
+ }
+}
+
+static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr)
+{
+ /* Reset magic pointer */
+ readb(ioaddr);
+ /* Write 64 bit magic to DS1216 */
+ ds1216_write(ioaddr, magic);
+}
+
+static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ds1216_priv *priv = platform_get_drvdata(pdev);
+ struct ds1216_regs regs;
+
+ ds1216_switch_ds_to_clock(priv->ioaddr);
+ ds1216_read(priv->ioaddr, (u8 *)&regs);
+
+ tm->tm_sec = BCD2BIN(regs.sec);
+ tm->tm_min = BCD2BIN(regs.min);
+ if (regs.hour & DS1216_HOUR_1224) {
+ /* AM/PM mode */
+ tm->tm_hour = BCD2BIN(regs.hour & 0x1f);
+ if (regs.hour & DS1216_HOUR_AMPM)
+ tm->tm_hour += 12;
+ } else
+ tm->tm_hour = BCD2BIN(regs.hour & 0x3f);
+ tm->tm_wday = (regs.wday & 7) - 1;
+ tm->tm_mday = BCD2BIN(regs.mday & 0x3f);
+ tm->tm_mon = BCD2BIN(regs.month & 0x1f);
+ tm->tm_year = BCD2BIN(regs.year);
+ if (tm->tm_year < 70)
+ tm->tm_year += 100;
+ return 0;
+}
+
+static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ds1216_priv *priv = platform_get_drvdata(pdev);
+ struct ds1216_regs regs;
+
+ ds1216_switch_ds_to_clock(priv->ioaddr);
+ ds1216_read(priv->ioaddr, (u8 *)&regs);
+
+ regs.tsec = 0; /* clear 0.1 and 0.01 seconds */
+ regs.sec = BIN2BCD(tm->tm_sec);
+ regs.min = BIN2BCD(tm->tm_min);
+ regs.hour &= DS1216_HOUR_1224;
+ if (regs.hour && tm->tm_hour > 12) {
+ regs.hour |= DS1216_HOUR_AMPM;
+ tm->tm_hour -= 12;
+ }
+ regs.hour |= BIN2BCD(tm->tm_hour);
+ regs.wday &= ~7;
+ regs.wday |= tm->tm_wday;
+ regs.mday = BIN2BCD(tm->tm_mday);
+ regs.month = BIN2BCD(tm->tm_mon);
+ regs.year = BIN2BCD(tm->tm_year % 100);
+
+ ds1216_switch_ds_to_clock(priv->ioaddr);
+ ds1216_write(priv->ioaddr, (u8 *)&regs);
+ return 0;
+}
+
+static const struct rtc_class_ops ds1216_rtc_ops = {
+ .read_time = ds1216_rtc_read_time,
+ .set_time = ds1216_rtc_set_time,
+};
+
+static int __devinit ds1216_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ struct resource *res;
+ struct ds1216_priv *priv;
+ int ret = 0;
+ u8 dummy[8];
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+ priv = kzalloc(sizeof *priv, GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->size = res->end - res->start + 1;
+ if (!request_mem_region(res->start, priv->size, pdev->name)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ priv->baseaddr = res->start;
+ priv->ioaddr = ioremap(priv->baseaddr, priv->size);
+ if (!priv->ioaddr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ rtc = rtc_device_register("ds1216", &pdev->dev,
+ &ds1216_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc);
+ goto out;
+ }
+ priv->rtc = rtc;
+ platform_set_drvdata(pdev, priv);
+
+ /* dummy read to get clock into a known state */
+ ds1216_read(priv->ioaddr, dummy);
+ return 0;
+
+out:
+ if (priv->rtc)
+ rtc_device_unregister(priv->rtc);
+ if (priv->ioaddr)
+ iounmap(priv->ioaddr);
+ if (priv->baseaddr)
+ release_mem_region(priv->baseaddr, priv->size);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit ds1216_rtc_remove(struct platform_device *pdev)
+{
+ struct ds1216_priv *priv = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(priv->rtc);
+ iounmap(priv->ioaddr);
+ release_mem_region(priv->baseaddr, priv->size);
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver ds1216_rtc_platform_driver = {
+ .driver = {
+ .name = "rtc-ds1216",
+ .owner = THIS_MODULE,
+ },
+ .probe = ds1216_rtc_probe,
+ .remove = __devexit_p(ds1216_rtc_remove),
+};
+
+static int __init ds1216_rtc_init(void)
+{
+ return platform_driver_register(&ds1216_rtc_platform_driver);
+}
+
+static void __exit ds1216_rtc_exit(void)
+{
+ platform_driver_unregister(&ds1216_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("DS1216 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ds1216_rtc_init);
+module_exit(ds1216_rtc_exit);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 3f0f7b8fa813..5158a625671f 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -24,29 +24,29 @@
* setting the date and time), Linux can ignore the non-clock features.
* That's a natural job for a factory or repair bench.
*
- * If the I2C "force" mechanism is used, we assume the chip is a ds1337.
- * (Much better would be board-specific tables of I2C devices, along with
- * the platform_data drivers would use to sort such issues out.)
+ * This is currently a simple no-alarms driver. If your board has the
+ * alarm irq wired up on a ds1337 or ds1339, and you want to use that,
+ * then look at the rtc-rs5c372 driver for code to steal...
*/
enum ds_type {
- unknown = 0,
- ds_1307, /* or ds1338, ... */
- ds_1337, /* or ds1339, ... */
- ds_1340, /* or st m41t00, ... */
+ ds_1307,
+ ds_1337,
+ ds_1338,
+ ds_1339,
+ ds_1340,
+ m41t00,
// rs5c372 too? different address...
};
-static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
-
/* RTC registers don't differ much, except for the century flag */
#define DS1307_REG_SECS 0x00 /* 00-59 */
# define DS1307_BIT_CH 0x80
+# define DS1340_BIT_nEOSC 0x80
#define DS1307_REG_MIN 0x01 /* 00-59 */
#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
+# define DS1307_BIT_12HR 0x40 /* in REG_HOUR */
+# define DS1307_BIT_PM 0x20 /* in REG_HOUR */
# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */
# define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */
#define DS1307_REG_WDAY 0x03 /* 01-07 */
@@ -56,11 +56,12 @@ I2C_CLIENT_INSMOD;
#define DS1307_REG_YEAR 0x06 /* 00-99 */
/* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
- * start at 7, and they differ a lot. Only control and status matter for RTC;
- * be careful using them.
+ * start at 7, and they differ a LOT. Only control and status matter for
+ * basic RTC date and time functionality; be careful using them.
*/
-#define DS1307_REG_CONTROL 0x07
+#define DS1307_REG_CONTROL 0x07 /* or ds1338 */
# define DS1307_BIT_OUT 0x80
+# define DS1338_BIT_OSF 0x20
# define DS1307_BIT_SQWE 0x10
# define DS1307_BIT_RS1 0x02
# define DS1307_BIT_RS0 0x01
@@ -71,6 +72,13 @@ I2C_CLIENT_INSMOD;
# define DS1337_BIT_INTCN 0x04
# define DS1337_BIT_A2IE 0x02
# define DS1337_BIT_A1IE 0x01
+#define DS1340_REG_CONTROL 0x07
+# define DS1340_BIT_OUT 0x80
+# define DS1340_BIT_FT 0x40
+# define DS1340_BIT_CALIB_SIGN 0x20
+# define DS1340_M_CALIBRATION 0x1f
+#define DS1340_REG_FLAG 0x09
+# define DS1340_BIT_OSF 0x80
#define DS1337_REG_STATUS 0x0f
# define DS1337_BIT_OSF 0x80
# define DS1337_BIT_A2I 0x02
@@ -84,21 +92,63 @@ struct ds1307 {
u8 regs[8];
enum ds_type type;
struct i2c_msg msg[2];
- struct i2c_client client;
+ struct i2c_client *client;
+ struct i2c_client dev;
struct rtc_device *rtc;
};
+struct chip_desc {
+ char name[9];
+ unsigned nvram56:1;
+ unsigned alarm:1;
+ enum ds_type type;
+};
+
+static const struct chip_desc chips[] = { {
+ .name = "ds1307",
+ .type = ds_1307,
+ .nvram56 = 1,
+}, {
+ .name = "ds1337",
+ .type = ds_1337,
+ .alarm = 1,
+}, {
+ .name = "ds1338",
+ .type = ds_1338,
+ .nvram56 = 1,
+}, {
+ .name = "ds1339",
+ .type = ds_1339,
+ .alarm = 1,
+}, {
+ .name = "ds1340",
+ .type = ds_1340,
+}, {
+ .name = "m41t00",
+ .type = m41t00,
+}, };
+
+static inline const struct chip_desc *find_chip(const char *s)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(chips); i++)
+ if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
+ return &chips[i];
+ return NULL;
+}
static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
int tmp;
- /* read the RTC registers all at once */
+ /* read the RTC date and time registers all at once */
ds1307->msg[1].flags = I2C_M_RD;
ds1307->msg[1].len = 7;
- tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2);
+ tmp = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
+ ds1307->msg, 2);
if (tmp != 2) {
dev_err(dev, "%s error %d\n", "read", tmp);
return -EIO;
@@ -129,7 +179,8 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday);
- return 0;
+ /* initial clock setting can be undefined */
+ return rtc_valid_tm(t);
}
static int ds1307_set_time(struct device *dev, struct rtc_time *t)
@@ -157,11 +208,18 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
tmp = t->tm_year - 100;
buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
- if (ds1307->type == ds_1337)
+ switch (ds1307->type) {
+ case ds_1337:
+ case ds_1339:
buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
- else if (ds1307->type == ds_1340)
+ break;
+ case ds_1340:
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
| DS1340_BIT_CENTURY;
+ break;
+ default:
+ break;
+ }
ds1307->msg[1].flags = 0;
ds1307->msg[1].len = 8;
@@ -170,7 +228,8 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
"write", buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6]);
- result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1);
+ result = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
+ &ds1307->msg[1], 1);
if (result != 1) {
dev_err(dev, "%s error %d\n", "write", tmp);
return -EIO;
@@ -185,25 +244,29 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
static struct i2c_driver ds1307_driver;
-static int __devinit
-ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
+static int __devinit ds1307_probe(struct i2c_client *client)
{
struct ds1307 *ds1307;
int err = -ENODEV;
- struct i2c_client *client;
int tmp;
-
- if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
+ const struct chip_desc *chip;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+
+ chip = find_chip(client->name);
+ if (!chip) {
+ dev_err(&client->dev, "unknown chip type '%s'\n",
+ client->name);
+ return -ENODEV;
}
- client = &ds1307->client;
- client->addr = address;
- client->adapter = adapter;
- client->driver = &ds1307_driver;
- client->flags = 0;
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ return -EIO;
+
+ if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL)))
+ return -ENOMEM;
+ ds1307->client = client;
i2c_set_clientdata(client, ds1307);
ds1307->msg[0].addr = client->addr;
@@ -216,14 +279,16 @@ ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
ds1307->msg[1].len = sizeof(ds1307->regs);
ds1307->msg[1].buf = ds1307->regs;
- /* HACK: "force" implies "needs ds1337-style-oscillator setup" */
- if (kind >= 0) {
- ds1307->type = ds_1337;
+ ds1307->type = chip->type;
+ switch (ds1307->type) {
+ case ds_1337:
+ case ds_1339:
ds1307->reg_addr = DS1337_REG_CONTROL;
ds1307->msg[1].len = 2;
- tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+ /* get registers that the "rtc" read below won't read... */
+ tmp = i2c_transfer(adapter, ds1307->msg, 2);
if (tmp != 2) {
pr_debug("read error %d\n", tmp);
err = -EIO;
@@ -233,19 +298,26 @@ ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
ds1307->reg_addr = 0;
ds1307->msg[1].len = sizeof(ds1307->regs);
- /* oscillator is off; need to turn it on */
- if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
- || (ds1307->regs[1] & DS1337_BIT_OSF)) {
- printk(KERN_ERR "no ds1337 oscillator code\n");
- goto exit_free;
+ /* oscillator off? turn it on, so clock can tick. */
+ if (ds1307->regs[0] & DS1337_BIT_nEOSC)
+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+ ds1307->regs[0] & ~DS1337_BIT_nEOSC);
+
+ /* oscillator fault? clear flag, and warn */
+ if (ds1307->regs[1] & DS1337_BIT_OSF) {
+ i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
+ ds1307->regs[1] & ~DS1337_BIT_OSF);
+ dev_warn(&client->dev, "SET TIME!\n");
}
- } else
- ds1307->type = ds_1307;
+ break;
+ default:
+ break;
+ }
read_rtc:
/* read RTC registers */
- tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+ tmp = i2c_transfer(adapter, ds1307->msg, 2);
if (tmp != 2) {
pr_debug("read error %d\n", tmp);
err = -EIO;
@@ -257,72 +329,80 @@ read_rtc:
* still a few values that are clearly out-of-range.
*/
tmp = ds1307->regs[DS1307_REG_SECS];
- if (tmp & DS1307_BIT_CH) {
- if (ds1307->type && ds1307->type != ds_1307) {
- pr_debug("not a ds1307?\n");
- goto exit_free;
- }
- ds1307->type = ds_1307;
-
- /* this partial initialization should work for ds1307,
- * ds1338, ds1340, st m41t00, and more.
+ switch (ds1307->type) {
+ case ds_1340:
+ /* FIXME read register with DS1340_BIT_OSF, use that to
+ * trigger the "set time" warning (*after* restarting the
+ * oscillator!) instead of this weaker ds1307/m41t00 test.
*/
- dev_warn(&client->dev, "oscillator started; SET TIME!\n");
- i2c_smbus_write_byte_data(client, 0, 0);
- goto read_rtc;
+ case ds_1307:
+ case m41t00:
+ /* clock halted? turn it on, so clock can tick. */
+ if (tmp & DS1307_BIT_CH) {
+ i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+ dev_warn(&client->dev, "SET TIME!\n");
+ goto read_rtc;
+ }
+ break;
+ case ds_1338:
+ /* clock halted? turn it on, so clock can tick. */
+ if (tmp & DS1307_BIT_CH)
+ i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+
+ /* oscillator fault? clear flag, and warn */
+ if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
+ i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
+ ds1307->regs[DS1337_REG_CONTROL]
+ & ~DS1338_BIT_OSF);
+ dev_warn(&client->dev, "SET TIME!\n");
+ goto read_rtc;
+ }
+ break;
+ case ds_1337:
+ case ds_1339:
+ break;
}
+
+ tmp = ds1307->regs[DS1307_REG_SECS];
tmp = BCD2BIN(tmp & 0x7f);
if (tmp > 60)
- goto exit_free;
+ goto exit_bad;
tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
if (tmp > 60)
- goto exit_free;
+ goto exit_bad;
tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
if (tmp == 0 || tmp > 31)
- goto exit_free;
+ goto exit_bad;
tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
if (tmp == 0 || tmp > 12)
- goto exit_free;
+ goto exit_bad;
- /* force into in 24 hour mode (most chips) or
- * disable century bit (ds1340)
- */
tmp = ds1307->regs[DS1307_REG_HOUR];
- if (tmp & (1 << 6)) {
- if (tmp & (1 << 5))
- tmp = BCD2BIN(tmp & 0x1f) + 12;
- else
- tmp = BCD2BIN(tmp);
- i2c_smbus_write_byte_data(client,
- DS1307_REG_HOUR,
- BIN2BCD(tmp));
- }
-
- /* FIXME chips like 1337 can generate alarm irqs too; those are
- * worth exposing through the API (especially when the irq is
- * wakeup-capable).
- */
-
switch (ds1307->type) {
- case unknown:
- strlcpy(client->name, "unknown", I2C_NAME_SIZE);
- break;
- case ds_1307:
- strlcpy(client->name, "ds1307", I2C_NAME_SIZE);
- break;
- case ds_1337:
- strlcpy(client->name, "ds1337", I2C_NAME_SIZE);
- break;
case ds_1340:
- strlcpy(client->name, "ds1340", I2C_NAME_SIZE);
+ case m41t00:
+ /* NOTE: ignores century bits; fix before deploying
+ * systems that will run through year 2100.
+ */
break;
- }
+ default:
+ if (!(tmp & DS1307_BIT_12HR))
+ break;
- /* Tell the I2C layer a new client has arrived */
- if ((err = i2c_attach_client(client)))
- goto exit_free;
+ /* Be sure we're in 24 hour mode. Multi-master systems
+ * take note...
+ */
+ tmp = BCD2BIN(tmp & 0x1f);
+ if (tmp == 12)
+ tmp = 0;
+ if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
+ tmp += 12;
+ i2c_smbus_write_byte_data(client,
+ DS1307_REG_HOUR,
+ BIN2BCD(tmp));
+ }
ds1307->rtc = rtc_device_register(client->name, &client->dev,
&ds13xx_rtc_ops, THIS_MODULE);
@@ -330,46 +410,40 @@ read_rtc:
err = PTR_ERR(ds1307->rtc);
dev_err(&client->dev,
"unable to register the class device\n");
- goto exit_detach;
+ goto exit_free;
}
return 0;
-exit_detach:
- i2c_detach_client(client);
+exit_bad:
+ dev_dbg(&client->dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+ "bogus register",
+ ds1307->regs[0], ds1307->regs[1],
+ ds1307->regs[2], ds1307->regs[3],
+ ds1307->regs[4], ds1307->regs[5],
+ ds1307->regs[6]);
+
exit_free:
kfree(ds1307);
-exit:
return err;
}
-static int __devinit
-ds1307_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
- return 0;
- return i2c_probe(adapter, &addr_data, ds1307_detect);
-}
-
-static int __devexit ds1307_detach_client(struct i2c_client *client)
+static int __devexit ds1307_remove(struct i2c_client *client)
{
- int err;
struct ds1307 *ds1307 = i2c_get_clientdata(client);
rtc_device_unregister(ds1307->rtc);
- if ((err = i2c_detach_client(client)))
- return err;
kfree(ds1307);
return 0;
}
static struct i2c_driver ds1307_driver = {
.driver = {
- .name = "ds1307",
+ .name = "rtc-ds1307",
.owner = THIS_MODULE,
},
- .attach_adapter = ds1307_attach_adapter,
- .detach_client = __devexit_p(ds1307_detach_client),
+ .probe = ds1307_probe,
+ .remove = __devexit_p(ds1307_remove),
};
static int __init ds1307_init(void)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
new file mode 100644
index 000000000000..80c4a8463065
--- /dev/null
+++ b/drivers/rtc/rtc-m41t80.c
@@ -0,0 +1,917 @@
+/*
+ * I2C client/driver for the ST M41T80 family of i2c rtc chips.
+ *
+ * Author: Alexander Bigga <ab@mycable.de>
+ *
+ * Based on m41t00.c by Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) mycable GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#endif
+
+#define M41T80_REG_SSEC 0
+#define M41T80_REG_SEC 1
+#define M41T80_REG_MIN 2
+#define M41T80_REG_HOUR 3
+#define M41T80_REG_WDAY 4
+#define M41T80_REG_DAY 5
+#define M41T80_REG_MON 6
+#define M41T80_REG_YEAR 7
+#define M41T80_REG_ALARM_MON 0xa
+#define M41T80_REG_ALARM_DAY 0xb
+#define M41T80_REG_ALARM_HOUR 0xc
+#define M41T80_REG_ALARM_MIN 0xd
+#define M41T80_REG_ALARM_SEC 0xe
+#define M41T80_REG_FLAGS 0xf
+#define M41T80_REG_SQW 0x13
+
+#define M41T80_DATETIME_REG_SIZE (M41T80_REG_YEAR + 1)
+#define M41T80_ALARM_REG_SIZE \
+ (M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
+
+#define M41T80_SEC_ST (1 << 7) /* ST: Stop Bit */
+#define M41T80_ALMON_AFE (1 << 7) /* AFE: AF Enable Bit */
+#define M41T80_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */
+#define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
+#define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */
+#define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */
+
+#define M41T80_FEATURE_HT (1 << 0)
+#define M41T80_FEATURE_BL (1 << 1)
+
+#define DRV_VERSION "0.05"
+
+struct m41t80_chip_info {
+ const char *name;
+ u8 features;
+};
+
+static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
+ {
+ .name = "m41t80",
+ .features = 0,
+ },
+ {
+ .name = "m41t81",
+ .features = M41T80_FEATURE_HT,
+ },
+ {
+ .name = "m41t81s",
+ .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+ },
+ {
+ .name = "m41t82",
+ .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+ },
+ {
+ .name = "m41t83",
+ .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+ },
+ {
+ .name = "m41st84",
+ .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+ },
+ {
+ .name = "m41st85",
+ .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+ },
+ {
+ .name = "m41st87",
+ .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
+ },
+};
+
+struct m41t80_data {
+ const struct m41t80_chip_info *chip;
+ struct rtc_device *rtc;
+};
+
+static int m41t80_get_datetime(struct i2c_client *client,
+ struct rtc_time *tm)
+{
+ u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC };
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = dt_addr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
+ .buf = buf + M41T80_REG_SEC,
+ },
+ };
+
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ dev_err(&client->dev, "read error\n");
+ return -EIO;
+ }
+
+ tm->tm_sec = BCD2BIN(buf[M41T80_REG_SEC] & 0x7f);
+ tm->tm_min = BCD2BIN(buf[M41T80_REG_MIN] & 0x7f);
+ tm->tm_hour = BCD2BIN(buf[M41T80_REG_HOUR] & 0x3f);
+ tm->tm_mday = BCD2BIN(buf[M41T80_REG_DAY] & 0x3f);
+ tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07;
+ tm->tm_mon = BCD2BIN(buf[M41T80_REG_MON] & 0x1f) - 1;
+
+ /* assume 20YY not 19YY, and ignore the Century Bit */
+ tm->tm_year = BCD2BIN(buf[M41T80_REG_YEAR]) + 100;
+ return 0;
+}
+
+/* Sets the given date and time to the real time clock. */
+static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ u8 wbuf[1 + M41T80_DATETIME_REG_SIZE];
+ u8 *buf = &wbuf[1];
+ u8 dt_addr[1] = { M41T80_REG_SEC };
+ struct i2c_msg msgs_in[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = dt_addr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
+ .buf = buf + M41T80_REG_SEC,
+ },
+ };
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1 + M41T80_DATETIME_REG_SIZE,
+ .buf = wbuf,
+ },
+ };
+
+ /* Read current reg values into buf[1..7] */
+ if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
+ dev_err(&client->dev, "read error\n");
+ return -EIO;
+ }
+
+ wbuf[0] = 0; /* offset into rtc's regs */
+ /* Merge time-data and register flags into buf[0..7] */
+ buf[M41T80_REG_SSEC] = 0;
+ buf[M41T80_REG_SEC] =
+ BIN2BCD(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
+ buf[M41T80_REG_MIN] =
+ BIN2BCD(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
+ buf[M41T80_REG_HOUR] =
+ BIN2BCD(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
+ buf[M41T80_REG_WDAY] =
+ (tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
+ buf[M41T80_REG_DAY] =
+ BIN2BCD(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
+ buf[M41T80_REG_MON] =
+ BIN2BCD(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
+ /* assume 20YY not 19YY */
+ buf[M41T80_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+
+ if (i2c_transfer(client->adapter, msgs, 1) != 1) {
+ dev_err(&client->dev, "write error\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct m41t80_data *clientdata = i2c_get_clientdata(client);
+ u8 reg;
+
+ if (clientdata->chip->features & M41T80_FEATURE_BL) {
+ reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ seq_printf(seq, "battery\t\t: %s\n",
+ (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
+ }
+ return 0;
+}
+#else
+#define m41t80_rtc_proc NULL
+#endif
+
+static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return m41t80_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return m41t80_set_datetime(to_i2c_client(dev), tm);
+}
+
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+static int
+m41t80_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int rc;
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ case RTC_AIE_ON:
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+ if (rc < 0)
+ goto err;
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ rc &= ~M41T80_ALMON_AFE;
+ break;
+ case RTC_AIE_ON:
+ rc |= M41T80_ALMON_AFE;
+ break;
+ }
+ if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0)
+ goto err;
+ return 0;
+err:
+ return -EIO;
+}
+#else
+#define m41t80_rtc_ioctl NULL
+#endif
+
+static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 wbuf[1 + M41T80_ALARM_REG_SIZE];
+ u8 *buf = &wbuf[1];
+ u8 *reg = buf - M41T80_REG_ALARM_MON;
+ u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
+ struct i2c_msg msgs_in[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = dt_addr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = M41T80_ALARM_REG_SIZE,
+ .buf = buf,
+ },
+ };
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1 + M41T80_ALARM_REG_SIZE,
+ .buf = wbuf,
+ },
+ };
+
+ if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
+ dev_err(&client->dev, "read error\n");
+ return -EIO;
+ }
+ reg[M41T80_REG_ALARM_MON] &= ~(0x1f | M41T80_ALMON_AFE);
+ reg[M41T80_REG_ALARM_DAY] = 0;
+ reg[M41T80_REG_ALARM_HOUR] &= ~(0x3f | 0x80);
+ reg[M41T80_REG_ALARM_MIN] = 0;
+ reg[M41T80_REG_ALARM_SEC] = 0;
+
+ wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */
+ reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ?
+ BIN2BCD(t->time.tm_sec) : 0x80;
+ reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ?
+ BIN2BCD(t->time.tm_min) : 0x80;
+ reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ?
+ BIN2BCD(t->time.tm_hour) : 0x80;
+ reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ?
+ BIN2BCD(t->time.tm_mday) : 0x80;
+ if (t->time.tm_mon >= 0)
+ reg[M41T80_REG_ALARM_MON] |= BIN2BCD(t->time.tm_mon + 1);
+ else
+ reg[M41T80_REG_ALARM_DAY] |= 0x40;
+
+ if (i2c_transfer(client->adapter, msgs, 1) != 1) {
+ dev_err(&client->dev, "write error\n");
+ return -EIO;
+ }
+
+ if (t->enabled) {
+ reg[M41T80_REG_ALARM_MON] |= M41T80_ALMON_AFE;
+ if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ reg[M41T80_REG_ALARM_MON]) < 0) {
+ dev_err(&client->dev, "write error\n");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 buf[M41T80_ALARM_REG_SIZE + 1]; /* all alarm regs and flags */
+ u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
+ u8 *reg = buf - M41T80_REG_ALARM_MON;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = dt_addr,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = M41T80_ALARM_REG_SIZE + 1,
+ .buf = buf,
+ },
+ };
+
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ dev_err(&client->dev, "read error\n");
+ return -EIO;
+ }
+ t->time.tm_sec = -1;
+ t->time.tm_min = -1;
+ t->time.tm_hour = -1;
+ t->time.tm_mday = -1;
+ t->time.tm_mon = -1;
+ if (!(reg[M41T80_REG_ALARM_SEC] & 0x80))
+ t->time.tm_sec = BCD2BIN(reg[M41T80_REG_ALARM_SEC] & 0x7f);
+ if (!(reg[M41T80_REG_ALARM_MIN] & 0x80))
+ t->time.tm_min = BCD2BIN(reg[M41T80_REG_ALARM_MIN] & 0x7f);
+ if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80))
+ t->time.tm_hour = BCD2BIN(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
+ if (!(reg[M41T80_REG_ALARM_DAY] & 0x80))
+ t->time.tm_mday = BCD2BIN(reg[M41T80_REG_ALARM_DAY] & 0x3f);
+ if (!(reg[M41T80_REG_ALARM_DAY] & 0x40))
+ t->time.tm_mon = BCD2BIN(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
+ t->time.tm_year = -1;
+ t->time.tm_wday = -1;
+ t->time.tm_yday = -1;
+ t->time.tm_isdst = -1;
+ t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE);
+ t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF);
+ return 0;
+}
+
+static struct rtc_class_ops m41t80_rtc_ops = {
+ .read_time = m41t80_rtc_read_time,
+ .set_time = m41t80_rtc_set_time,
+ .read_alarm = m41t80_rtc_read_alarm,
+ .set_alarm = m41t80_rtc_set_alarm,
+ .proc = m41t80_rtc_proc,
+ .ioctl = m41t80_rtc_ioctl,
+};
+
+#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
+static ssize_t m41t80_sysfs_show_flags(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int val;
+
+ val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ if (val < 0)
+ return -EIO;
+ return sprintf(buf, "%#x\n", val);
+}
+static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL);
+
+static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int val;
+
+ val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
+ if (val < 0)
+ return -EIO;
+ val = (val >> 4) & 0xf;
+ switch (val) {
+ case 0:
+ break;
+ case 1:
+ val = 32768;
+ break;
+ default:
+ val = 32768 >> val;
+ }
+ return sprintf(buf, "%d\n", val);
+}
+static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int almon, sqw;
+ int val = simple_strtoul(buf, NULL, 0);
+
+ if (val) {
+ if (!is_power_of_2(val))
+ return -EINVAL;
+ val = ilog2(val);
+ if (val == 15)
+ val = 1;
+ else if (val < 14)
+ val = 15 - val;
+ else
+ return -EINVAL;
+ }
+ /* disable SQW, set SQW frequency & re-enable */
+ almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+ if (almon < 0)
+ return -EIO;
+ sqw = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
+ if (sqw < 0)
+ return -EIO;
+ sqw = (sqw & 0x0f) | (val << 4);
+ if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ almon & ~M41T80_ALMON_SQWE) < 0 ||
+ i2c_smbus_write_byte_data(client, M41T80_REG_SQW, sqw) < 0)
+ return -EIO;
+ if (val && i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ almon | M41T80_ALMON_SQWE) < 0)
+ return -EIO;
+ return count;
+}
+static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
+ m41t80_sysfs_show_sqwfreq, m41t80_sysfs_set_sqwfreq);
+
+static struct attribute *attrs[] = {
+ &dev_attr_flags.attr,
+ &dev_attr_sqwfreq.attr,
+ NULL,
+};
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
+static int m41t80_sysfs_register(struct device *dev)
+{
+ return sysfs_create_group(&dev->kobj, &attr_group);
+}
+#else
+static int m41t80_sysfs_register(struct device *dev)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+/*
+ *****************************************************************************
+ *
+ * Watchdog Driver
+ *
+ *****************************************************************************
+ */
+static struct i2c_client *save_client;
+
+/* Default margin */
+#define WD_TIMO 60 /* 1..31 seconds */
+
+static int wdt_margin = WD_TIMO;
+module_param(wdt_margin, int, 0);
+MODULE_PARM_DESC(wdt_margin, "Watchdog timeout in seconds (default 60s)");
+
+static unsigned long wdt_is_open;
+static int boot_flag;
+
+/**
+ * wdt_ping:
+ *
+ * Reload counter one with the watchdog timeout. We don't bother reloading
+ * the cascade counter.
+ */
+static void wdt_ping(void)
+{
+ unsigned char i2c_data[2];
+ struct i2c_msg msgs1[1] = {
+ {
+ .addr = save_client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = i2c_data,
+ },
+ };
+ i2c_data[0] = 0x09; /* watchdog register */
+
+ if (wdt_margin > 31)
+ i2c_data[1] = (wdt_margin & 0xFC) | 0x83; /* resolution = 4s */
+ else
+ /*
+ * WDS = 1 (0x80), mulitplier = WD_TIMO, resolution = 1s (0x02)
+ */
+ i2c_data[1] = wdt_margin<<2 | 0x82;
+
+ i2c_transfer(save_client->adapter, msgs1, 1);
+}
+
+/**
+ * wdt_disable:
+ *
+ * disables watchdog.
+ */
+static void wdt_disable(void)
+{
+ unsigned char i2c_data[2], i2c_buf[0x10];
+ struct i2c_msg msgs0[2] = {
+ {
+ .addr = save_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = i2c_data,
+ },
+ {
+ .addr = save_client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = i2c_buf,
+ },
+ };
+ struct i2c_msg msgs1[1] = {
+ {
+ .addr = save_client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = i2c_data,
+ },
+ };
+
+ i2c_data[0] = 0x09;
+ i2c_transfer(save_client->adapter, msgs0, 2);
+
+ i2c_data[0] = 0x09;
+ i2c_data[1] = 0x00;
+ i2c_transfer(save_client->adapter, msgs1, 1);
+}
+
+/**
+ * wdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /* Can't seek (pwrite) on this device
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ */
+ if (count) {
+ wdt_ping();
+ return 1;
+ }
+ return 0;
+}
+
+static ssize_t wdt_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return 0;
+}
+
+/**
+ * wdt_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features. We only actually usefully support
+ * querying capabilities and current status.
+ */
+static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int new_margin, rv;
+ static struct watchdog_info ident = {
+ .options = WDIOF_POWERUNDER | WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT,
+ .firmware_version = 1,
+ .identity = "M41T80 WTD"
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info __user *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(boot_flag, (int __user *)arg);
+ case WDIOC_KEEPALIVE:
+ wdt_ping();
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_margin, (int __user *)arg))
+ return -EFAULT;
+ /* Arbitrary, can't find the card's limits */
+ if (new_margin < 1 || new_margin > 124)
+ return -EINVAL;
+ wdt_margin = new_margin;
+ wdt_ping();
+ /* Fall */
+ case WDIOC_GETTIMEOUT:
+ return put_user(wdt_margin, (int __user *)arg);
+
+ case WDIOC_SETOPTIONS:
+ if (copy_from_user(&rv, (int __user *)arg, sizeof(int)))
+ return -EFAULT;
+
+ if (rv & WDIOS_DISABLECARD) {
+ printk(KERN_INFO
+ "rtc-m41t80: disable watchdog\n");
+ wdt_disable();
+ }
+
+ if (rv & WDIOS_ENABLECARD) {
+ printk(KERN_INFO
+ "rtc-m41t80: enable watchdog\n");
+ wdt_ping();
+ }
+
+ return -EINVAL;
+ }
+ return -ENOTTY;
+}
+
+/**
+ * wdt_open:
+ * @inode: inode of device
+ * @file: file handle to device
+ *
+ */
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ if (test_and_set_bit(0, &wdt_is_open))
+ return -EBUSY;
+ /*
+ * Activate
+ */
+ wdt_is_open = 1;
+ return 0;
+ }
+ return -ENODEV;
+}
+
+/**
+ * wdt_close:
+ * @inode: inode to board
+ * @file: file handle to board
+ *
+ */
+static int wdt_release(struct inode *inode, struct file *file)
+{
+ if (MINOR(inode->i_rdev) == WATCHDOG_MINOR)
+ clear_bit(0, &wdt_is_open);
+ return 0;
+}
+
+/**
+ * notify_sys:
+ * @this: our notifier block
+ * @code: the event being reported
+ * @unused: unused
+ *
+ * Our notifier is called on system shutdowns. We want to turn the card
+ * off at reboot otherwise the machine will reboot again during memory
+ * test or worse yet during the following fsck. This would suck, in fact
+ * trust me - if it happens it does suck.
+ */
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ /* Disable Watchdog */
+ wdt_disable();
+ return NOTIFY_DONE;
+}
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .read = wdt_read,
+ .ioctl = wdt_ioctl,
+ .write = wdt_write,
+ .open = wdt_open,
+ .release = wdt_release,
+};
+
+static struct miscdevice wdt_dev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+/*
+ * The WDT card needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+#endif /* CONFIG_RTC_DRV_M41T80_WDT */
+
+/*
+ *****************************************************************************
+ *
+ * Driver Interface
+ *
+ *****************************************************************************
+ */
+static int m41t80_probe(struct i2c_client *client)
+{
+ int i, rc = 0;
+ struct rtc_device *rtc = NULL;
+ struct rtc_time tm;
+ const struct m41t80_chip_info *chip;
+ struct m41t80_data *clientdata = NULL;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
+ | I2C_FUNC_SMBUS_BYTE_DATA)) {
+ rc = -ENODEV;
+ goto exit;
+ }
+
+ dev_info(&client->dev,
+ "chip found, driver version " DRV_VERSION "\n");
+
+ chip = NULL;
+ for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
+ if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
+ chip = &m41t80_chip_info_tbl[i];
+ break;
+ }
+ }
+ if (!chip) {
+ dev_err(&client->dev, "%s is not supported\n", client->name);
+ rc = -ENODEV;
+ goto exit;
+ }
+
+ clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
+ if (!clientdata) {
+ rc = -ENOMEM;
+ goto exit;
+ }
+
+ rtc = rtc_device_register(client->name, &client->dev,
+ &m41t80_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ rc = PTR_ERR(rtc);
+ rtc = NULL;
+ goto exit;
+ }
+
+ clientdata->rtc = rtc;
+ clientdata->chip = chip;
+ i2c_set_clientdata(client, clientdata);
+
+ /* Make sure HT (Halt Update) bit is cleared */
+ rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
+ if (rc < 0)
+ goto ht_err;
+
+ if (rc & M41T80_ALHOUR_HT) {
+ if (chip->features & M41T80_FEATURE_HT) {
+ m41t80_get_datetime(client, &tm);
+ dev_info(&client->dev, "HT bit was set!\n");
+ dev_info(&client->dev,
+ "Power Down at "
+ "%04i-%02i-%02i %02i:%02i:%02i\n",
+ tm.tm_year + 1900,
+ tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+ }
+ if (i2c_smbus_write_byte_data(client,
+ M41T80_REG_ALARM_HOUR,
+ rc & ~M41T80_ALHOUR_HT) < 0)
+ goto ht_err;
+ }
+
+ /* Make sure ST (stop) bit is cleared */
+ rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
+ if (rc < 0)
+ goto st_err;
+
+ if (rc & M41T80_SEC_ST) {
+ if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC,
+ rc & ~M41T80_SEC_ST) < 0)
+ goto st_err;
+ }
+
+ rc = m41t80_sysfs_register(&client->dev);
+ if (rc)
+ goto exit;
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+ if (chip->features & M41T80_FEATURE_HT) {
+ rc = misc_register(&wdt_dev);
+ if (rc)
+ goto exit;
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc) {
+ misc_deregister(&wdt_dev);
+ goto exit;
+ }
+ save_client = client;
+ }
+#endif
+ return 0;
+
+st_err:
+ rc = -EIO;
+ dev_err(&client->dev, "Can't clear ST bit\n");
+ goto exit;
+ht_err:
+ rc = -EIO;
+ dev_err(&client->dev, "Can't clear HT bit\n");
+ goto exit;
+
+exit:
+ if (rtc)
+ rtc_device_unregister(rtc);
+ kfree(clientdata);
+ return rc;
+}
+
+static int m41t80_remove(struct i2c_client *client)
+{
+ struct m41t80_data *clientdata = i2c_get_clientdata(client);
+ struct rtc_device *rtc = clientdata->rtc;
+
+#ifdef CONFIG_RTC_DRV_M41T80_WDT
+ if (clientdata->chip->features & M41T80_FEATURE_HT) {
+ misc_deregister(&wdt_dev);
+ unregister_reboot_notifier(&wdt_notifier);
+ }
+#endif
+ if (rtc)
+ rtc_device_unregister(rtc);
+ kfree(clientdata);
+
+ return 0;
+}
+
+static struct i2c_driver m41t80_driver = {
+ .driver = {
+ .name = "m41t80",
+ },
+ .probe = m41t80_probe,
+ .remove = m41t80_remove,
+};
+
+static int __init m41t80_rtc_init(void)
+{
+ return i2c_add_driver(&m41t80_driver);
+}
+
+static void __exit m41t80_rtc_exit(void)
+{
+ i2c_del_driver(&m41t80_driver);
+}
+
+MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>");
+MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(m41t80_rtc_init);
+module_exit(m41t80_rtc_exit);
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
new file mode 100644
index 000000000000..33b752350ab5
--- /dev/null
+++ b/drivers/rtc/rtc-m48t59.c
@@ -0,0 +1,491 @@
+/*
+ * ST M48T59 RTC driver
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Author: Mark Zhan <rongkai.zhan@windriver.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/init.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/rtc/m48t59.h>
+#include <linux/bcd.h>
+
+#ifndef NO_IRQ
+#define NO_IRQ (-1)
+#endif
+
+#define M48T59_READ(reg) pdata->read_byte(dev, reg)
+#define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val)
+
+#define M48T59_SET_BITS(mask, reg) \
+ M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
+#define M48T59_CLEAR_BITS(mask, reg) \
+ M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg))
+
+struct m48t59_private {
+ void __iomem *ioaddr;
+ unsigned int size; /* iomem size */
+ unsigned int irq;
+ struct rtc_device *rtc;
+ spinlock_t lock; /* serialize the NVRAM and RTC access */
+};
+
+/*
+ * This is the generic access method when the chip is memory-mapped
+ */
+static void
+m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+ writeb(val, m48t59->ioaddr+ofs);
+}
+
+static u8
+m48t59_mem_readb(struct device *dev, u32 ofs)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+ return readb(m48t59->ioaddr+ofs);
+}
+
+/*
+ * NOTE: M48T59 only uses BCD mode
+ */
+static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ unsigned long flags;
+ u8 val;
+
+ spin_lock_irqsave(&m48t59->lock, flags);
+ /* Issue the READ command */
+ M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+
+ tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+ /* tm_mon is 0-11 */
+ tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+ tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY));
+
+ val = M48T59_READ(M48T59_WDAY);
+ if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
+ dev_dbg(dev, "Century bit is enabled\n");
+ tm->tm_year += 100; /* one century */
+ }
+
+ tm->tm_wday = BCD2BIN(val & 0x07);
+ tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F);
+ tm->tm_min = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F);
+ tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F);
+
+ /* Clear the READ bit */
+ M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+
+ dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
+ tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return 0;
+}
+
+static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ unsigned long flags;
+ u8 val = 0;
+
+ dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
+ tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ spin_lock_irqsave(&m48t59->lock, flags);
+ /* Issue the WRITE command */
+ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+
+ M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC);
+ M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN);
+ M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR);
+ M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY);
+ /* tm_mon is 0-11 */
+ M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
+ M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
+
+ if (tm->tm_year/100)
+ val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
+ val |= (BIN2BCD(tm->tm_wday) & 0x07);
+ M48T59_WRITE(val, M48T59_WDAY);
+
+ /* Clear the WRITE bit */
+ M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+ return 0;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct rtc_time *tm = &alrm->time;
+ unsigned long flags;
+ u8 val;
+
+ /* If no irq, we don't support ALARM */
+ if (m48t59->irq == NO_IRQ)
+ return -EIO;
+
+ spin_lock_irqsave(&m48t59->lock, flags);
+ /* Issue the READ command */
+ M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+
+ tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+ /* tm_mon is 0-11 */
+ tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+
+ val = M48T59_READ(M48T59_WDAY);
+ if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
+ tm->tm_year += 100; /* one century */
+
+ tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE));
+ tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR));
+ tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN));
+ tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC));
+
+ /* Clear the READ bit */
+ M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+
+ dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
+ tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return 0;
+}
+
+/*
+ * Set alarm time and date in RTC
+ */
+static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct rtc_time *tm = &alrm->time;
+ u8 mday, hour, min, sec;
+ unsigned long flags;
+
+ /* If no irq, we don't support ALARM */
+ if (m48t59->irq == NO_IRQ)
+ return -EIO;
+
+ /*
+ * 0xff means "always match"
+ */
+ mday = tm->tm_mday;
+ mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+ if (mday == 0xff)
+ mday = M48T59_READ(M48T59_MDAY);
+
+ hour = tm->tm_hour;
+ hour = (hour < 24) ? BIN2BCD(hour) : 0x00;
+
+ min = tm->tm_min;
+ min = (min < 60) ? BIN2BCD(min) : 0x00;
+
+ sec = tm->tm_sec;
+ sec = (sec < 60) ? BIN2BCD(sec) : 0x00;
+
+ spin_lock_irqsave(&m48t59->lock, flags);
+ /* Issue the WRITE command */
+ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+
+ M48T59_WRITE(mday, M48T59_ALARM_DATE);
+ M48T59_WRITE(hour, M48T59_ALARM_HOUR);
+ M48T59_WRITE(min, M48T59_ALARM_MIN);
+ M48T59_WRITE(sec, M48T59_ALARM_SEC);
+
+ /* Clear the WRITE bit */
+ M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+
+ dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
+ tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&m48t59->lock, flags);
+ switch (cmd) {
+ case RTC_AIE_OFF: /* alarm interrupt off */
+ M48T59_WRITE(0x00, M48T59_INTR);
+ break;
+ case RTC_AIE_ON: /* alarm interrupt on */
+ M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+
+ return ret;
+}
+
+static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ unsigned long flags;
+ u8 val;
+
+ spin_lock_irqsave(&m48t59->lock, flags);
+ val = M48T59_READ(M48T59_FLAGS);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+
+ seq_printf(seq, "battery\t\t: %s\n",
+ (val & M48T59_FLAGS_BF) ? "low" : "normal");
+ return 0;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
+{
+ struct device *dev = (struct device *)dev_id;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ u8 event;
+
+ spin_lock(&m48t59->lock);
+ event = M48T59_READ(M48T59_FLAGS);
+ spin_unlock(&m48t59->lock);
+
+ if (event & M48T59_FLAGS_AF) {
+ rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF));
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static const struct rtc_class_ops m48t59_rtc_ops = {
+ .ioctl = m48t59_rtc_ioctl,
+ .read_time = m48t59_rtc_read_time,
+ .set_time = m48t59_rtc_set_time,
+ .read_alarm = m48t59_rtc_readalarm,
+ .set_alarm = m48t59_rtc_setalarm,
+ .proc = m48t59_rtc_proc,
+};
+
+static ssize_t m48t59_nvram_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ ssize_t cnt = 0;
+ unsigned long flags;
+
+ for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+ spin_lock_irqsave(&m48t59->lock, flags);
+ *buf++ = M48T59_READ(cnt);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+ }
+
+ return cnt;
+}
+
+static ssize_t m48t59_nvram_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ ssize_t cnt = 0;
+ unsigned long flags;
+
+ for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
+ spin_lock_irqsave(&m48t59->lock, flags);
+ M48T59_WRITE(*buf++, cnt);
+ spin_unlock_irqrestore(&m48t59->lock, flags);
+ }
+
+ return cnt;
+}
+
+static struct bin_attribute m48t59_nvram_attr = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUGO,
+ .owner = THIS_MODULE,
+ },
+ .read = m48t59_nvram_read,
+ .write = m48t59_nvram_write,
+};
+
+static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
+{
+ struct m48t59_plat_data *pdata = pdev->dev.platform_data;
+ struct m48t59_private *m48t59 = NULL;
+ struct resource *res;
+ int ret = -ENOMEM;
+
+ /* This chip could be memory-mapped or I/O-mapped */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
+ return -EINVAL;
+ }
+
+ if (res->flags & IORESOURCE_IO) {
+ /* If we are I/O-mapped, the platform should provide
+ * the operations accessing chip registers.
+ */
+ if (!pdata || !pdata->write_byte || !pdata->read_byte)
+ return -EINVAL;
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* we are memory-mapped */
+ if (!pdata) {
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ /* Ensure we only kmalloc platform data once */
+ pdev->dev.platform_data = pdata;
+ }
+
+ /* Try to use the generic memory read/write ops */
+ if (!pdata->write_byte)
+ pdata->write_byte = m48t59_mem_writeb;
+ if (!pdata->read_byte)
+ pdata->read_byte = m48t59_mem_readb;
+ }
+
+ m48t59 = kzalloc(sizeof(*m48t59), GFP_KERNEL);
+ if (!m48t59)
+ return -ENOMEM;
+
+ m48t59->size = res->end - res->start + 1;
+ m48t59->ioaddr = ioremap(res->start, m48t59->size);
+ if (!m48t59->ioaddr)
+ goto out;
+
+ /* Try to get irq number. We also can work in
+ * the mode without IRQ.
+ */
+ m48t59->irq = platform_get_irq(pdev, 0);
+ if (m48t59->irq < 0)
+ m48t59->irq = NO_IRQ;
+
+ if (m48t59->irq != NO_IRQ) {
+ ret = request_irq(m48t59->irq, m48t59_rtc_interrupt,
+ IRQF_SHARED, "rtc-m48t59", &pdev->dev);
+ if (ret)
+ goto out;
+ }
+
+ m48t59->rtc = rtc_device_register("m48t59", &pdev->dev,
+ &m48t59_rtc_ops, THIS_MODULE);
+ if (IS_ERR(m48t59->rtc)) {
+ ret = PTR_ERR(m48t59->rtc);
+ goto out;
+ }
+
+ ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+ if (ret)
+ goto out;
+
+ spin_lock_init(&m48t59->lock);
+ platform_set_drvdata(pdev, m48t59);
+ return 0;
+
+out:
+ if (!IS_ERR(m48t59->rtc))
+ rtc_device_unregister(m48t59->rtc);
+ if (m48t59->irq != NO_IRQ)
+ free_irq(m48t59->irq, &pdev->dev);
+ if (m48t59->ioaddr)
+ iounmap(m48t59->ioaddr);
+ if (m48t59)
+ kfree(m48t59);
+ return ret;
+}
+
+static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
+{
+ struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+
+ sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+ if (!IS_ERR(m48t59->rtc))
+ rtc_device_unregister(m48t59->rtc);
+ if (m48t59->ioaddr)
+ iounmap(m48t59->ioaddr);
+ if (m48t59->irq != NO_IRQ)
+ free_irq(m48t59->irq, &pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(m48t59);
+ return 0;
+}
+
+static struct platform_driver m48t59_rtc_platdrv = {
+ .driver = {
+ .name = "rtc-m48t59",
+ .owner = THIS_MODULE,
+ },
+ .probe = m48t59_rtc_probe,
+ .remove = __devexit_p(m48t59_rtc_remove),
+};
+
+static int __init m48t59_rtc_init(void)
+{
+ return platform_driver_register(&m48t59_rtc_platdrv);
+}
+
+static void __exit m48t59_rtc_exit(void)
+{
+ platform_driver_unregister(&m48t59_rtc_platdrv);
+}
+
+module_init(m48t59_rtc_init);
+module_exit(m48t59_rtc_exit);
+
+MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
+MODULE_DESCRIPTION("M48T59 RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 09bbe575647b..6b67b5097927 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -13,13 +13,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
-#define DRV_VERSION "0.4"
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "0.5"
/*
@@ -88,9 +82,6 @@ struct rs5c372 {
unsigned has_irq:1;
char buf[17];
char *regs;
-
- /* on conversion to a "new style" i2c driver, this vanishes */
- struct i2c_client dev;
};
static int rs5c_get_regs(struct rs5c372 *rs5c)
@@ -483,25 +474,35 @@ static int rs5c_sysfs_register(struct device *dev)
return err;
}
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_trim);
+ device_remove_file(dev, &dev_attr_osc);
+}
+
#else
static int rs5c_sysfs_register(struct device *dev)
{
return 0;
}
+
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+ /* nothing */
+}
#endif /* SYSFS */
static struct i2c_driver rs5c372_driver;
-static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
+static int rs5c372_probe(struct i2c_client *client)
{
int err = 0;
- struct i2c_client *client;
struct rs5c372 *rs5c372;
struct rtc_time tm;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ dev_dbg(&client->dev, "%s\n", __FUNCTION__);
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit;
}
@@ -514,35 +515,22 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
rs5c372->regs=&rs5c372->buf[1];
- /* On conversion to a "new style" i2c driver, we'll be handed
- * the i2c_client (we won't create it)
- */
- client = &rs5c372->dev;
rs5c372->client = client;
-
- /* I2C client */
- client->addr = address;
- client->driver = &rs5c372_driver;
- client->adapter = adapter;
-
- strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
-
i2c_set_clientdata(client, rs5c372);
- /* Inform the i2c layer */
- if ((err = i2c_attach_client(client)))
- goto exit_kfree;
-
err = rs5c_get_regs(rs5c372);
if (err < 0)
- goto exit_detach;
+ goto exit_kfree;
- /* For "new style" drivers, irq is in i2c_client and chip type
- * info comes from i2c_client.dev.platform_data. Meanwhile:
- *
- * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE
- */
- if (rs5c372->type == rtc_undef) {
+ if (strcmp(client->name, "rs5c372a") == 0)
+ rs5c372->type = rtc_rs5c372a;
+ else if (strcmp(client->name, "rs5c372b") == 0)
+ rs5c372->type = rtc_rs5c372b;
+ else if (strcmp(client->name, "rv5c386") == 0)
+ rs5c372->type = rtc_rv5c386;
+ else if (strcmp(client->name, "rv5c387a") == 0)
+ rs5c372->type = rtc_rv5c387a;
+ else {
rs5c372->type = rtc_rs5c372b;
dev_warn(&client->dev, "assuming rs5c372b\n");
}
@@ -567,7 +555,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
break;
default:
dev_err(&client->dev, "unknown RTC type\n");
- goto exit_detach;
+ goto exit_kfree;
}
/* if the oscillator lost power and no other software (like
@@ -601,7 +589,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
if ((i2c_master_send(client, buf, 3)) != 3) {
dev_err(&client->dev, "setup error\n");
- goto exit_detach;
+ goto exit_kfree;
}
rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
@@ -621,14 +609,14 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
rs5c372->time24 ? "24hr" : "am/pm"
);
- /* FIXME when client->irq exists, use it to register alarm irq */
+ /* REVISIT use client->irq to register alarm irq ... */
rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
&client->dev, &rs5c372_rtc_ops, THIS_MODULE);
if (IS_ERR(rs5c372->rtc)) {
err = PTR_ERR(rs5c372->rtc);
- goto exit_detach;
+ goto exit_kfree;
}
err = rs5c_sysfs_register(&client->dev);
@@ -640,9 +628,6 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
exit_devreg:
rtc_device_unregister(rs5c372->rtc);
-exit_detach:
- i2c_detach_client(client);
-
exit_kfree:
kfree(rs5c372);
@@ -650,24 +635,12 @@ exit:
return err;
}
-static int rs5c372_attach(struct i2c_adapter *adapter)
+static int rs5c372_remove(struct i2c_client *client)
{
- return i2c_probe(adapter, &addr_data, rs5c372_probe);
-}
-
-static int rs5c372_detach(struct i2c_client *client)
-{
- int err;
struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
- if (rs5c372->rtc)
- rtc_device_unregister(rs5c372->rtc);
-
- /* REVISIT properly destroy the sysfs files ... */
-
- if ((err = i2c_detach_client(client)))
- return err;
-
+ rtc_device_unregister(rs5c372->rtc);
+ rs5c_sysfs_unregister(&client->dev);
kfree(rs5c372);
return 0;
}
@@ -676,8 +649,8 @@ static struct i2c_driver rs5c372_driver = {
.driver = {
.name = "rtc-rs5c372",
},
- .attach_adapter = &rs5c372_attach,
- .detach_client = &rs5c372_detach,
+ .probe = rs5c372_probe,
+ .remove = rs5c372_remove,
};
static __init int rs5c372_init(void)
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 1340451ea408..35765f6a86e0 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -747,14 +747,9 @@ dcssblk_check_params(void)
static void __exit
dcssblk_exit(void)
{
- int rc;
-
PRINT_DEBUG("DCSSBLOCK EXIT...\n");
s390_root_dev_unregister(dcssblk_root_dev);
- rc = unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
- if (rc) {
- PRINT_ERR("unregister_blkdev() failed!\n");
- }
+ unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
PRINT_DEBUG("...finished!\n");
}
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 66102a184322..3f36cb3910ee 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -164,3 +164,10 @@ config MONWRITER
help
Character device driver for writing z/VM monitor service records
+config S390_VMUR
+ tristate "z/VM unit record device driver"
+ depends on S390
+ default "m"
+ help
+ Character device driver for z/VM reader, puncher and printer.
+
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index c210784bdf46..130de19916f2 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o
obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o
obj-$(CONFIG_MONREADER) += monreader.o
obj-$(CONFIG_MONWRITER) += monwriter.o
+obj-$(CONFIG_S390_VMUR) += vmur.o
zcore_mod-objs := sclp_sdias.o zcore.o
obj-$(CONFIG_ZFCPDUMP) += zcore_mod.o
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 82e6a6b253eb..2f419b0ea628 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2004,2005 IBM Corporation
+ * Copyright IBM Corp. 2004,2007
* Interface implementation for communication with the z/VM control program
- * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
*
*
* z/VMs CP offers the possibility to issue commands via the diagnose code 8
@@ -22,9 +22,11 @@
#include "vmcp.h"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>");
+MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>");
MODULE_DESCRIPTION("z/VM CP interface");
+#define PRINTK_HEADER "vmcp: "
+
static debug_info_t *vmcp_debug;
static int vmcp_open(struct inode *inode, struct file *file)
@@ -40,7 +42,7 @@ static int vmcp_open(struct inode *inode, struct file *file)
session->bufsize = PAGE_SIZE;
session->response = NULL;
session->resp_size = 0;
- init_MUTEX(&session->mutex);
+ mutex_init(&session->mutex);
file->private_data = session;
return nonseekable_open(inode, file);
}
@@ -57,37 +59,37 @@ static int vmcp_release(struct inode *inode, struct file *file)
}
static ssize_t
-vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos)
+vmcp_read(struct file *file, char __user *buff, size_t count, loff_t *ppos)
{
size_t tocopy;
struct vmcp_session *session;
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex))
+ if (mutex_lock_interruptible(&session->mutex))
return -ERESTARTSYS;
if (!session->response) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return 0;
}
if (*ppos > session->resp_size) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return 0;
}
tocopy = min(session->resp_size - (size_t) (*ppos), count);
- tocopy = min(tocopy,session->bufsize - (size_t) (*ppos));
+ tocopy = min(tocopy, session->bufsize - (size_t) (*ppos));
if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return -EFAULT;
}
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
*ppos += tocopy;
return tocopy;
}
static ssize_t
-vmcp_write(struct file *file, const char __user * buff, size_t count,
- loff_t * ppos)
+vmcp_write(struct file *file, const char __user *buff, size_t count,
+ loff_t *ppos)
{
char *cmd;
struct vmcp_session *session;
@@ -103,24 +105,23 @@ vmcp_write(struct file *file, const char __user * buff, size_t count,
}
cmd[count] = '\0';
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex)) {
+ if (mutex_lock_interruptible(&session->mutex)) {
kfree(cmd);
return -ERESTARTSYS;
}
if (!session->response)
session->response = (char *)__get_free_pages(GFP_KERNEL
- | __GFP_REPEAT | GFP_DMA,
+ | __GFP_REPEAT | GFP_DMA,
get_order(session->bufsize));
if (!session->response) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
kfree(cmd);
return -ENOMEM;
}
debug_text_event(vmcp_debug, 1, cmd);
- session->resp_size = cpcmd(cmd, session->response,
- session->bufsize,
- &session->resp_code);
- up(&session->mutex);
+ session->resp_size = cpcmd(cmd, session->response, session->bufsize,
+ &session->resp_code);
+ mutex_unlock(&session->mutex);
kfree(cmd);
*ppos = 0; /* reset the file pointer after a command */
return count;
@@ -145,12 +146,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int temp;
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex))
+ if (mutex_lock_interruptible(&session->mutex))
return -ERESTARTSYS;
switch (cmd) {
case VMCP_GETCODE:
temp = session->resp_code;
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return put_user(temp, (int __user *)arg);
case VMCP_SETBUF:
free_pages((unsigned long)session->response,
@@ -161,14 +162,14 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
session->bufsize = PAGE_SIZE;
temp = -EINVAL;
}
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return temp;
case VMCP_GETSIZE:
temp = session->resp_size;
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return put_user(temp, (int __user *)arg);
default:
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return -ENOIOCTLCMD;
}
}
@@ -180,7 +181,7 @@ static const struct file_operations vmcp_fops = {
.read = vmcp_read,
.write = vmcp_write,
.unlocked_ioctl = vmcp_ioctl,
- .compat_ioctl = vmcp_ioctl
+ .compat_ioctl = vmcp_ioctl,
};
static struct miscdevice vmcp_dev = {
@@ -194,26 +195,38 @@ static int __init vmcp_init(void)
int ret;
if (!MACHINE_IS_VM) {
- printk(KERN_WARNING
- "z/VM CP interface is only available under z/VM\n");
+ PRINT_WARN("z/VM CP interface is only available under z/VM\n");
return -ENODEV;
}
- ret = misc_register(&vmcp_dev);
- if (!ret)
- printk(KERN_INFO "z/VM CP interface loaded\n");
- else
- printk(KERN_WARNING
- "z/VM CP interface not loaded. Could not register misc device.\n");
vmcp_debug = debug_register("vmcp", 1, 1, 240);
- debug_register_view(vmcp_debug, &debug_hex_ascii_view);
- return ret;
+ if (!vmcp_debug) {
+ PRINT_ERR("z/VM CP interface not loaded. Could not register "
+ "debug feature\n");
+ return -ENOMEM;
+ }
+ ret = debug_register_view(vmcp_debug, &debug_hex_ascii_view);
+ if (ret) {
+ PRINT_ERR("z/VM CP interface not loaded. Could not register "
+ "debug feature view. Error code: %d\n", ret);
+ debug_unregister(vmcp_debug);
+ return ret;
+ }
+ ret = misc_register(&vmcp_dev);
+ if (ret) {
+ PRINT_ERR("z/VM CP interface not loaded. Could not register "
+ "misc device. Error code: %d\n", ret);
+ debug_unregister(vmcp_debug);
+ return ret;
+ }
+ PRINT_INFO("z/VM CP interface loaded\n");
+ return 0;
}
static void __exit vmcp_exit(void)
{
- WARN_ON(misc_deregister(&vmcp_dev) != 0);
+ misc_deregister(&vmcp_dev);
debug_unregister(vmcp_debug);
- printk(KERN_INFO "z/VM CP interface unloaded.\n");
+ PRINT_INFO("z/VM CP interface unloaded.\n");
}
module_init(vmcp_init);
diff --git a/drivers/s390/char/vmcp.h b/drivers/s390/char/vmcp.h
index 8a5975f3dad7..6a993948e188 100644
--- a/drivers/s390/char/vmcp.h
+++ b/drivers/s390/char/vmcp.h
@@ -12,8 +12,8 @@
* The idea of this driver is based on cpint from Neale Ferguson
*/
-#include <asm/semaphore.h>
#include <linux/ioctl.h>
+#include <linux/mutex.h>
#define VMCP_GETCODE _IOR(0x10, 1, int)
#define VMCP_SETBUF _IOW(0x10, 2, int)
@@ -26,5 +26,5 @@ struct vmcp_session {
int resp_code;
/* As we use copy_from/to_user, which might *
* sleep and cannot use a spinlock */
- struct semaphore mutex;
+ struct mutex mutex;
};
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
new file mode 100644
index 000000000000..e90b0f846195
--- /dev/null
+++ b/drivers/s390/char/vmur.c
@@ -0,0 +1,906 @@
+/*
+ * Linux driver for System z and s390 unit record devices
+ * (z/VM virtual punch, reader, printer)
+ *
+ * Copyright IBM Corp. 2001, 2007
+ * Authors: Malcolm Beattie <beattiem@uk.ibm.com>
+ * Michael Holzheu <holzheu@de.ibm.com>
+ * Frank Munzert <munzert@de.ibm.com>
+ */
+
+#include <linux/cdev.h>
+
+#include <asm/uaccess.h>
+#include <asm/cio.h>
+#include <asm/ccwdev.h>
+#include <asm/debug.h>
+
+#include "vmur.h"
+
+/*
+ * Driver overview
+ *
+ * Unit record device support is implemented as a character device driver.
+ * We can fit at least 16 bits into a device minor number and use the
+ * simple method of mapping a character device number with minor abcd
+ * to the unit record device with devno abcd.
+ * I/O to virtual unit record devices is handled as follows:
+ * Reads: Diagnose code 0x14 (input spool file manipulation)
+ * is used to read spool data page-wise.
+ * Writes: The CCW used is WRITE_CCW_CMD (0x01). The device's record length
+ * is available by reading sysfs attr reclen. Each write() to the device
+ * must specify an integral multiple (maximal 511) of reclen.
+ */
+
+static char ur_banner[] = "z/VM virtual unit record device driver";
+
+MODULE_AUTHOR("IBM Corporation");
+MODULE_DESCRIPTION("s390 z/VM virtual unit record device driver");
+MODULE_LICENSE("GPL");
+
+#define PRINTK_HEADER "vmur: "
+
+static dev_t ur_first_dev_maj_min;
+static struct class *vmur_class;
+static struct debug_info *vmur_dbf;
+
+/* We put the device's record length (for writes) in the driver_info field */
+static struct ccw_device_id ur_ids[] = {
+ { CCWDEV_CU_DI(READER_PUNCH_DEVTYPE, 80) },
+ { CCWDEV_CU_DI(PRINTER_DEVTYPE, 132) },
+ { /* end of list */ }
+};
+
+MODULE_DEVICE_TABLE(ccw, ur_ids);
+
+static int ur_probe(struct ccw_device *cdev);
+static void ur_remove(struct ccw_device *cdev);
+static int ur_set_online(struct ccw_device *cdev);
+static int ur_set_offline(struct ccw_device *cdev);
+
+static struct ccw_driver ur_driver = {
+ .name = "vmur",
+ .owner = THIS_MODULE,
+ .ids = ur_ids,
+ .probe = ur_probe,
+ .remove = ur_remove,
+ .set_online = ur_set_online,
+ .set_offline = ur_set_offline,
+};
+
+/*
+ * Allocation, freeing, getting and putting of urdev structures
+ */
+static struct urdev *urdev_alloc(struct ccw_device *cdev)
+{
+ struct urdev *urd;
+
+ urd = kzalloc(sizeof(struct urdev), GFP_KERNEL);
+ if (!urd)
+ return NULL;
+ urd->cdev = cdev;
+ urd->reclen = cdev->id.driver_info;
+ ccw_device_get_id(cdev, &urd->dev_id);
+ mutex_init(&urd->io_mutex);
+ mutex_init(&urd->open_mutex);
+ return urd;
+}
+
+static void urdev_free(struct urdev *urd)
+{
+ kfree(urd);
+}
+
+/*
+ * This is how the character device driver gets a reference to a
+ * ur device. When this call returns successfully, a reference has
+ * been taken (by get_device) on the underlying kobject. The recipient
+ * of this urdev pointer must eventually drop it with urdev_put(urd)
+ * which does the corresponding put_device().
+ */
+static struct urdev *urdev_get_from_devno(u16 devno)
+{
+ char bus_id[16];
+ struct ccw_device *cdev;
+
+ sprintf(bus_id, "0.0.%04x", devno);
+ cdev = get_ccwdev_by_busid(&ur_driver, bus_id);
+ if (!cdev)
+ return NULL;
+
+ return cdev->dev.driver_data;
+}
+
+static void urdev_put(struct urdev *urd)
+{
+ put_device(&urd->cdev->dev);
+}
+
+/*
+ * Low-level functions to do I/O to a ur device.
+ * alloc_chan_prog
+ * do_ur_io
+ * ur_int_handler
+ *
+ * alloc_chan_prog allocates and builds the channel program
+ *
+ * do_ur_io issues the channel program to the device and blocks waiting
+ * on a completion event it publishes at urd->io_done. The function
+ * serialises itself on the device's mutex so that only one I/O
+ * is issued at a time (and that I/O is synchronous).
+ *
+ * ur_int_handler catches the "I/O done" interrupt, writes the
+ * subchannel status word into the scsw member of the urdev structure
+ * and complete()s the io_done to wake the waiting do_ur_io.
+ *
+ * The caller of do_ur_io is responsible for kfree()ing the channel program
+ * address pointer that alloc_chan_prog returned.
+ */
+
+
+/*
+ * alloc_chan_prog
+ * The channel program we use is write commands chained together
+ * with a final NOP CCW command-chained on (which ensures that CE and DE
+ * are presented together in a single interrupt instead of as separate
+ * interrupts unless an incorrect length indication kicks in first). The
+ * data length in each CCW is reclen. The caller must ensure that count
+ * is an integral multiple of reclen.
+ * The channel program pointer returned by this function must be freed
+ * with kfree. The caller is responsible for checking that
+ * count/reclen is not ridiculously large.
+ */
+static struct ccw1 *alloc_chan_prog(char *buf, size_t count, size_t reclen)
+{
+ size_t num_ccws;
+ struct ccw1 *cpa;
+ int i;
+
+ TRACE("alloc_chan_prog(%p, %zu, %zu)\n", buf, count, reclen);
+
+ /*
+ * We chain a NOP onto the writes to force CE+DE together.
+ * That means we allocate room for CCWs to cover count/reclen
+ * records plus a NOP.
+ */
+ num_ccws = count / reclen + 1;
+ cpa = kmalloc(num_ccws * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+ if (!cpa)
+ return NULL;
+
+ for (i = 0; count; i++) {
+ cpa[i].cmd_code = WRITE_CCW_CMD;
+ cpa[i].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
+ cpa[i].count = reclen;
+ cpa[i].cda = __pa(buf);
+ buf += reclen;
+ count -= reclen;
+ }
+ /* The following NOP CCW forces CE+DE to be presented together */
+ cpa[i].cmd_code = CCW_CMD_NOOP;
+ cpa[i].flags = 0;
+ cpa[i].count = 0;
+ cpa[i].cda = 0;
+
+ return cpa;
+}
+
+static int do_ur_io(struct urdev *urd, struct ccw1 *cpa)
+{
+ int rc;
+ struct ccw_device *cdev = urd->cdev;
+ DECLARE_COMPLETION(event);
+
+ TRACE("do_ur_io: cpa=%p\n", cpa);
+
+ rc = mutex_lock_interruptible(&urd->io_mutex);
+ if (rc)
+ return rc;
+
+ urd->io_done = &event;
+
+ spin_lock_irq(get_ccwdev_lock(cdev));
+ rc = ccw_device_start(cdev, cpa, 1, 0, 0);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
+
+ TRACE("do_ur_io: ccw_device_start returned %d\n", rc);
+ if (rc)
+ goto out;
+
+ wait_for_completion(&event);
+ TRACE("do_ur_io: I/O complete\n");
+ rc = 0;
+
+out:
+ mutex_unlock(&urd->io_mutex);
+ return rc;
+}
+
+/*
+ * ur interrupt handler, called from the ccw_device layer
+ */
+static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ struct irb *irb)
+{
+ struct urdev *urd;
+
+ TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
+ intparm, irb->scsw.cstat, irb->scsw.dstat, irb->scsw.count);
+
+ if (!intparm) {
+ TRACE("ur_int_handler: unsolicited interrupt\n");
+ return;
+ }
+ urd = cdev->dev.driver_data;
+ /* On special conditions irb is an error pointer */
+ if (IS_ERR(irb))
+ urd->io_request_rc = PTR_ERR(irb);
+ else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+ urd->io_request_rc = 0;
+ else
+ urd->io_request_rc = -EIO;
+
+ complete(urd->io_done);
+}
+
+/*
+ * reclen sysfs attribute - The record length to be used for write CCWs
+ */
+static ssize_t ur_attr_reclen_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct urdev *urd = dev->driver_data;
+
+ return sprintf(buf, "%zu\n", urd->reclen);
+}
+
+static DEVICE_ATTR(reclen, 0444, ur_attr_reclen_show, NULL);
+
+static int ur_create_attributes(struct device *dev)
+{
+ return device_create_file(dev, &dev_attr_reclen);
+}
+
+static void ur_remove_attributes(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_reclen);
+}
+
+/*
+ * diagnose code 0x210 - retrieve device information
+ * cc=0 normal completion, we have a real device
+ * cc=1 CP paging error
+ * cc=2 The virtual device exists, but is not associated with a real device
+ * cc=3 Invalid device address, or the virtual device does not exist
+ */
+static int get_urd_class(struct urdev *urd)
+{
+ static struct diag210 ur_diag210;
+ int cc;
+
+ ur_diag210.vrdcdvno = urd->dev_id.devno;
+ ur_diag210.vrdclen = sizeof(struct diag210);
+
+ cc = diag210(&ur_diag210);
+ switch (cc) {
+ case 0:
+ return -ENOTSUPP;
+ case 2:
+ return ur_diag210.vrdcvcla; /* virtual device class */
+ case 3:
+ return -ENODEV;
+ default:
+ return -EIO;
+ }
+}
+
+/*
+ * Allocation and freeing of urfile structures
+ */
+static struct urfile *urfile_alloc(struct urdev *urd)
+{
+ struct urfile *urf;
+
+ urf = kzalloc(sizeof(struct urfile), GFP_KERNEL);
+ if (!urf)
+ return NULL;
+ urf->urd = urd;
+
+ TRACE("urfile_alloc: urd=%p urf=%p rl=%zu\n", urd, urf,
+ urf->dev_reclen);
+
+ return urf;
+}
+
+static void urfile_free(struct urfile *urf)
+{
+ TRACE("urfile_free: urf=%p urd=%p\n", urf, urf->urd);
+ kfree(urf);
+}
+
+/*
+ * The fops implementation of the character device driver
+ */
+static ssize_t do_write(struct urdev *urd, const char __user *udata,
+ size_t count, size_t reclen, loff_t *ppos)
+{
+ struct ccw1 *cpa;
+ char *buf;
+ int rc;
+
+ /* Data buffer must be under 2GB line for fmt1 CCWs: hence GFP_DMA */
+ buf = kmalloc(count, GFP_KERNEL | GFP_DMA);
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, udata, count)) {
+ rc = -EFAULT;
+ goto fail_kfree_buf;
+ }
+
+ cpa = alloc_chan_prog(buf, count, reclen);
+ if (!cpa) {
+ rc = -ENOMEM;
+ goto fail_kfree_buf;
+ }
+
+ rc = do_ur_io(urd, cpa);
+ if (rc)
+ goto fail_kfree_cpa;
+
+ if (urd->io_request_rc) {
+ rc = urd->io_request_rc;
+ goto fail_kfree_cpa;
+ }
+ *ppos += count;
+ rc = count;
+fail_kfree_cpa:
+ kfree(cpa);
+fail_kfree_buf:
+ kfree(buf);
+ return rc;
+}
+
+static ssize_t ur_write(struct file *file, const char __user *udata,
+ size_t count, loff_t *ppos)
+{
+ struct urfile *urf = file->private_data;
+
+ TRACE("ur_write: count=%zu\n", count);
+
+ if (count == 0)
+ return 0;
+
+ if (count % urf->dev_reclen)
+ return -EINVAL; /* count must be a multiple of reclen */
+
+ if (count > urf->dev_reclen * MAX_RECS_PER_IO)
+ count = urf->dev_reclen * MAX_RECS_PER_IO;
+
+ return do_write(urf->urd, udata, count, urf->dev_reclen, ppos);
+}
+
+static int do_diag_14(unsigned long rx, unsigned long ry1,
+ unsigned long subcode)
+{
+ register unsigned long _ry1 asm("2") = ry1;
+ register unsigned long _ry2 asm("3") = subcode;
+ int rc = 0;
+
+ asm volatile(
+#ifdef CONFIG_64BIT
+ " sam31\n"
+ " diag %2,2,0x14\n"
+ " sam64\n"
+#else
+ " diag %2,2,0x14\n"
+#endif
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (rc), "+d" (_ry2)
+ : "d" (rx), "d" (_ry1)
+ : "cc");
+
+ TRACE("diag 14: subcode=0x%lx, cc=%i\n", subcode, rc);
+ return rc;
+}
+
+/*
+ * diagnose code 0x14 subcode 0x0028 - position spool file to designated
+ * record
+ * cc=0 normal completion
+ * cc=2 no file active on the virtual reader or device not ready
+ * cc=3 record specified is beyond EOF
+ */
+static int diag_position_to_record(int devno, int record)
+{
+ int cc;
+
+ cc = do_diag_14(record, devno, 0x28);
+ switch (cc) {
+ case 0:
+ return 0;
+ case 2:
+ return -ENOMEDIUM;
+ case 3:
+ return -ENODATA; /* position beyond end of file */
+ default:
+ return -EIO;
+ }
+}
+
+/*
+ * diagnose code 0x14 subcode 0x0000 - read next spool file buffer
+ * cc=0 normal completion
+ * cc=1 EOF reached
+ * cc=2 no file active on the virtual reader, and no file eligible
+ * cc=3 file already active on the virtual reader or specified virtual
+ * reader does not exist or is not a reader
+ */
+static int diag_read_file(int devno, char *buf)
+{
+ int cc;
+
+ cc = do_diag_14((unsigned long) buf, devno, 0x00);
+ switch (cc) {
+ case 0:
+ return 0;
+ case 1:
+ return -ENODATA;
+ case 2:
+ return -ENOMEDIUM;
+ default:
+ return -EIO;
+ }
+}
+
+static ssize_t diag14_read(struct file *file, char __user *ubuf, size_t count,
+ loff_t *offs)
+{
+ size_t len, copied, res;
+ char *buf;
+ int rc;
+ u16 reclen;
+ struct urdev *urd;
+
+ urd = ((struct urfile *) file->private_data)->urd;
+ reclen = ((struct urfile *) file->private_data)->file_reclen;
+
+ rc = diag_position_to_record(urd->dev_id.devno, *offs / PAGE_SIZE + 1);
+ if (rc == -ENODATA)
+ return 0;
+ if (rc)
+ return rc;
+
+ len = min((size_t) PAGE_SIZE, count);
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ copied = 0;
+ res = (size_t) (*offs % PAGE_SIZE);
+ do {
+ rc = diag_read_file(urd->dev_id.devno, buf);
+ if (rc == -ENODATA) {
+ break;
+ }
+ if (rc)
+ goto fail;
+ if (reclen)
+ *((u16 *) &buf[FILE_RECLEN_OFFSET]) = reclen;
+ len = min(count - copied, PAGE_SIZE - res);
+ if (copy_to_user(ubuf + copied, buf + res, len)) {
+ rc = -EFAULT;
+ goto fail;
+ }
+ res = 0;
+ copied += len;
+ } while (copied != count);
+
+ *offs += copied;
+ rc = copied;
+fail:
+ kfree(buf);
+ return rc;
+}
+
+static ssize_t ur_read(struct file *file, char __user *ubuf, size_t count,
+ loff_t *offs)
+{
+ struct urdev *urd;
+ int rc;
+
+ TRACE("ur_read: count=%zu ppos=%li\n", count, (unsigned long) *offs);
+
+ if (count == 0)
+ return 0;
+
+ urd = ((struct urfile *) file->private_data)->urd;
+ rc = mutex_lock_interruptible(&urd->io_mutex);
+ if (rc)
+ return rc;
+ rc = diag14_read(file, ubuf, count, offs);
+ mutex_unlock(&urd->io_mutex);
+ return rc;
+}
+
+/*
+ * diagnose code 0x14 subcode 0x0fff - retrieve next file descriptor
+ * cc=0 normal completion
+ * cc=1 no files on reader queue or no subsequent file
+ * cc=2 spid specified is invalid
+ */
+static int diag_read_next_file_info(struct file_control_block *buf, int spid)
+{
+ int cc;
+
+ cc = do_diag_14((unsigned long) buf, spid, 0xfff);
+ switch (cc) {
+ case 0:
+ return 0;
+ default:
+ return -ENODATA;
+ }
+}
+
+static int verify_device(struct urdev *urd)
+{
+ struct file_control_block fcb;
+ char *buf;
+ int rc;
+
+ switch (urd->class) {
+ case DEV_CLASS_UR_O:
+ return 0; /* no check needed here */
+ case DEV_CLASS_UR_I:
+ /* check for empty reader device (beginning of chain) */
+ rc = diag_read_next_file_info(&fcb, 0);
+ if (rc)
+ return rc;
+
+ /* open file on virtual reader */
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ rc = diag_read_file(urd->dev_id.devno, buf);
+ kfree(buf);
+
+ if ((rc != 0) && (rc != -ENODATA)) /* EOF does not hurt */
+ return rc;
+ return 0;
+ default:
+ return -ENOTSUPP;
+ }
+}
+
+static int get_file_reclen(struct urdev *urd)
+{
+ struct file_control_block fcb;
+ int rc;
+
+ switch (urd->class) {
+ case DEV_CLASS_UR_O:
+ return 0;
+ case DEV_CLASS_UR_I:
+ rc = diag_read_next_file_info(&fcb, 0);
+ if (rc)
+ return rc;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ if (fcb.file_stat & FLG_CP_DUMP)
+ return 0;
+
+ return fcb.rec_len;
+}
+
+static int ur_open(struct inode *inode, struct file *file)
+{
+ u16 devno;
+ struct urdev *urd;
+ struct urfile *urf;
+ unsigned short accmode;
+ int rc;
+
+ accmode = file->f_flags & O_ACCMODE;
+
+ if (accmode == O_RDWR)
+ return -EACCES;
+
+ /*
+ * We treat the minor number as the devno of the ur device
+ * to find in the driver tree.
+ */
+ devno = MINOR(file->f_dentry->d_inode->i_rdev);
+
+ urd = urdev_get_from_devno(devno);
+ if (!urd)
+ return -ENXIO;
+
+ if (file->f_flags & O_NONBLOCK) {
+ if (!mutex_trylock(&urd->open_mutex)) {
+ rc = -EBUSY;
+ goto fail_put;
+ }
+ } else {
+ if (mutex_lock_interruptible(&urd->open_mutex)) {
+ rc = -ERESTARTSYS;
+ goto fail_put;
+ }
+ }
+
+ TRACE("ur_open\n");
+
+ if (((accmode == O_RDONLY) && (urd->class != DEV_CLASS_UR_I)) ||
+ ((accmode == O_WRONLY) && (urd->class != DEV_CLASS_UR_O))) {
+ TRACE("ur_open: unsupported dev class (%d)\n", urd->class);
+ rc = -EACCES;
+ goto fail_unlock;
+ }
+
+ rc = verify_device(urd);
+ if (rc)
+ goto fail_unlock;
+
+ urf = urfile_alloc(urd);
+ if (!urf) {
+ rc = -ENOMEM;
+ goto fail_unlock;
+ }
+
+ urf->dev_reclen = urd->reclen;
+ rc = get_file_reclen(urd);
+ if (rc < 0)
+ goto fail_urfile_free;
+ urf->file_reclen = rc;
+ file->private_data = urf;
+ return 0;
+
+fail_urfile_free:
+ urfile_free(urf);
+fail_unlock:
+ mutex_unlock(&urd->open_mutex);
+fail_put:
+ urdev_put(urd);
+ return rc;
+}
+
+static int ur_release(struct inode *inode, struct file *file)
+{
+ struct urfile *urf = file->private_data;
+
+ TRACE("ur_release\n");
+ mutex_unlock(&urf->urd->open_mutex);
+ urdev_put(urf->urd);
+ urfile_free(urf);
+ return 0;
+}
+
+static loff_t ur_llseek(struct file *file, loff_t offset, int whence)
+{
+ loff_t newpos;
+
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ return -ESPIPE; /* seek allowed only for reader */
+ if (offset % PAGE_SIZE)
+ return -ESPIPE; /* only multiples of 4K allowed */
+ switch (whence) {
+ case 0: /* SEEK_SET */
+ newpos = offset;
+ break;
+ case 1: /* SEEK_CUR */
+ newpos = file->f_pos + offset;
+ break;
+ default:
+ return -EINVAL;
+ }
+ file->f_pos = newpos;
+ return newpos;
+}
+
+static struct file_operations ur_fops = {
+ .owner = THIS_MODULE,
+ .open = ur_open,
+ .release = ur_release,
+ .read = ur_read,
+ .write = ur_write,
+ .llseek = ur_llseek,
+};
+
+/*
+ * ccw_device infrastructure:
+ * ur_probe gets its own ref to the device (i.e. get_device),
+ * creates the struct urdev, the device attributes, sets up
+ * the interrupt handler and validates the virtual unit record device.
+ * ur_remove removes the device attributes, frees the struct urdev
+ * and drops (put_device) the ref to the device we got in ur_probe.
+ */
+static int ur_probe(struct ccw_device *cdev)
+{
+ struct urdev *urd;
+ int rc;
+
+ TRACE("ur_probe: cdev=%p state=%d\n", cdev, *(int *) cdev->private);
+
+ if (!get_device(&cdev->dev))
+ return -ENODEV;
+
+ urd = urdev_alloc(cdev);
+ if (!urd) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+ rc = ur_create_attributes(&cdev->dev);
+ if (rc) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+ cdev->dev.driver_data = urd;
+ cdev->handler = ur_int_handler;
+
+ /* validate virtual unit record device */
+ urd->class = get_urd_class(urd);
+ if (urd->class < 0) {
+ rc = urd->class;
+ goto fail;
+ }
+ if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) {
+ rc = -ENOTSUPP;
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ urdev_free(urd);
+ put_device(&cdev->dev);
+ return rc;
+}
+
+static void ur_remove(struct ccw_device *cdev)
+{
+ struct urdev *urd = cdev->dev.driver_data;
+
+ TRACE("ur_remove\n");
+ if (cdev->online)
+ ur_set_offline(cdev);
+ ur_remove_attributes(&cdev->dev);
+ urdev_free(urd);
+ put_device(&cdev->dev);
+}
+
+static int ur_set_online(struct ccw_device *cdev)
+{
+ struct urdev *urd;
+ int minor, major, rc;
+ char node_id[16];
+
+ TRACE("ur_set_online: cdev=%p state=%d\n", cdev,
+ *(int *) cdev->private);
+
+ if (!try_module_get(ur_driver.owner))
+ return -EINVAL;
+
+ urd = (struct urdev *) cdev->dev.driver_data;
+ minor = urd->dev_id.devno;
+ major = MAJOR(ur_first_dev_maj_min);
+
+ urd->char_device = cdev_alloc();
+ if (!urd->char_device) {
+ rc = -ENOMEM;
+ goto fail_module_put;
+ }
+
+ cdev_init(urd->char_device, &ur_fops);
+ urd->char_device->dev = MKDEV(major, minor);
+ urd->char_device->owner = ur_fops.owner;
+
+ rc = cdev_add(urd->char_device, urd->char_device->dev, 1);
+ if (rc)
+ goto fail_free_cdev;
+ if (urd->cdev->id.cu_type == READER_PUNCH_DEVTYPE) {
+ if (urd->class == DEV_CLASS_UR_I)
+ sprintf(node_id, "vmrdr-%s", cdev->dev.bus_id);
+ if (urd->class == DEV_CLASS_UR_O)
+ sprintf(node_id, "vmpun-%s", cdev->dev.bus_id);
+ } else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) {
+ sprintf(node_id, "vmprt-%s", cdev->dev.bus_id);
+ } else {
+ rc = -ENOTSUPP;
+ goto fail_free_cdev;
+ }
+
+ urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
+ "%s", node_id);
+ if (IS_ERR(urd->device)) {
+ rc = PTR_ERR(urd->device);
+ TRACE("ur_set_online: device_create rc=%d\n", rc);
+ goto fail_free_cdev;
+ }
+
+ return 0;
+
+fail_free_cdev:
+ cdev_del(urd->char_device);
+fail_module_put:
+ module_put(ur_driver.owner);
+
+ return rc;
+}
+
+static int ur_set_offline(struct ccw_device *cdev)
+{
+ struct urdev *urd;
+
+ TRACE("ur_set_offline: cdev=%p cdev->private=%p state=%d\n",
+ cdev, cdev->private, *(int *) cdev->private);
+ urd = (struct urdev *) cdev->dev.driver_data;
+ device_destroy(vmur_class, urd->char_device->dev);
+ cdev_del(urd->char_device);
+ module_put(ur_driver.owner);
+
+ return 0;
+}
+
+/*
+ * Module initialisation and cleanup
+ */
+static int __init ur_init(void)
+{
+ int rc;
+ dev_t dev;
+
+ if (!MACHINE_IS_VM) {
+ PRINT_ERR("%s is only available under z/VM.\n", ur_banner);
+ return -ENODEV;
+ }
+
+ vmur_dbf = debug_register("vmur", 4, 1, 4 * sizeof(long));
+ if (!vmur_dbf)
+ return -ENOMEM;
+ rc = debug_register_view(vmur_dbf, &debug_sprintf_view);
+ if (rc)
+ goto fail_free_dbf;
+
+ debug_set_level(vmur_dbf, 6);
+
+ rc = ccw_driver_register(&ur_driver);
+ if (rc)
+ goto fail_free_dbf;
+
+ rc = alloc_chrdev_region(&dev, 0, NUM_MINORS, "vmur");
+ if (rc) {
+ PRINT_ERR("alloc_chrdev_region failed: err = %d\n", rc);
+ goto fail_unregister_driver;
+ }
+ ur_first_dev_maj_min = MKDEV(MAJOR(dev), 0);
+
+ vmur_class = class_create(THIS_MODULE, "vmur");
+ if (IS_ERR(vmur_class)) {
+ rc = PTR_ERR(vmur_class);
+ goto fail_unregister_region;
+ }
+ PRINT_INFO("%s loaded.\n", ur_banner);
+ return 0;
+
+fail_unregister_region:
+ unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS);
+fail_unregister_driver:
+ ccw_driver_unregister(&ur_driver);
+fail_free_dbf:
+ debug_unregister(vmur_dbf);
+ return rc;
+}
+
+static void __exit ur_exit(void)
+{
+ class_destroy(vmur_class);
+ unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS);
+ ccw_driver_unregister(&ur_driver);
+ debug_unregister(vmur_dbf);
+ PRINT_INFO("%s unloaded.\n", ur_banner);
+}
+
+module_init(ur_init);
+module_exit(ur_exit);
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
new file mode 100644
index 000000000000..16d0a4e38e40
--- /dev/null
+++ b/drivers/s390/char/vmur.h
@@ -0,0 +1,104 @@
+/*
+ * Linux driver for System z and s390 unit record devices
+ * (z/VM virtual punch, reader, printer)
+ *
+ * Copyright IBM Corp. 2001, 2007
+ * Authors: Malcolm Beattie <beattiem@uk.ibm.com>
+ * Michael Holzheu <holzheu@de.ibm.com>
+ * Frank Munzert <munzert@de.ibm.com>
+ */
+
+#ifndef _VMUR_H_
+#define _VMUR_H_
+
+#define DEV_CLASS_UR_I 0x20 /* diag210 unit record input device class */
+#define DEV_CLASS_UR_O 0x10 /* diag210 unit record output device class */
+/*
+ * we only support z/VM's default unit record devices:
+ * both in SPOOL directory control statement and in CP DEFINE statement
+ * RDR defaults to 2540 reader
+ * PUN defaults to 2540 punch
+ * PRT defaults to 1403 printer
+ */
+#define READER_PUNCH_DEVTYPE 0x2540
+#define PRINTER_DEVTYPE 0x1403
+
+/* z/VM spool file control block SFBLOK */
+struct file_control_block {
+ char reserved_1[8];
+ char user_owner[8];
+ char user_orig[8];
+ __s32 data_recs;
+ __s16 rec_len;
+ __s16 file_num;
+ __u8 file_stat;
+ __u8 dev_type;
+ char reserved_2[6];
+ char file_name[12];
+ char file_type[12];
+ char create_date[8];
+ char create_time[8];
+ char reserved_3[6];
+ __u8 file_class;
+ __u8 sfb_lok;
+ __u64 distr_code;
+ __u32 reserved_4;
+ __u8 current_starting_copy_number;
+ __u8 sfblock_cntrl_flags;
+ __u8 reserved_5;
+ __u8 more_status_flags;
+ char rest[200];
+} __attribute__ ((packed));
+
+#define FLG_CP_DUMP 0x10
+
+/*
+ * A struct urdev is created for each ur device that is made available
+ * via the ccw_device driver model.
+ */
+struct urdev {
+ struct ccw_device *cdev; /* Backpointer to ccw device */
+ struct mutex io_mutex; /* Serialises device IO */
+ struct mutex open_mutex; /* Serialises access to device */
+ struct completion *io_done; /* do_ur_io waits; irq completes */
+ struct device *device;
+ struct cdev *char_device;
+ struct ccw_dev_id dev_id; /* device id */
+ size_t reclen; /* Record length for *write* CCWs */
+ int class; /* VM device class */
+ int io_request_rc; /* return code from I/O request */
+};
+
+/*
+ * A struct urfile is allocated at open() time for each device and
+ * freed on release().
+ */
+struct urfile {
+ struct urdev *urd;
+ unsigned int flags;
+ size_t dev_reclen;
+ __u16 file_reclen;
+};
+
+/*
+ * Device major/minor definitions.
+ */
+
+#define UR_MAJOR 0 /* get dynamic major */
+/*
+ * We map minor numbers directly to device numbers (0-FFFF) for simplicity.
+ * This avoids having to allocate (and manage) slot numbers.
+ */
+#define NUM_MINORS 65536
+
+/* Limiting each I/O to 511 records limits chan prog to 4KB (511 r/w + 1 NOP) */
+#define MAX_RECS_PER_IO 511
+#define WRITE_CCW_CMD 0x01
+
+#define TRACE(x...) debug_sprintf_event(vmur_dbf, 1, x)
+#define CCWDEV_CU_DI(cutype, di) \
+ CCW_DEVICE(cutype, 0x00), .driver_info = (di)
+
+#define FILE_RECLEN_OFFSET 4064 /* reclen offset in spool data block */
+
+#endif /* _VMUR_H_ */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 6b264bdb5bfb..001682e70f67 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -272,7 +272,7 @@ modalias_show (struct device *dev, struct device_attribute *attr, char *buf)
struct ccw_device_id *id = &(cdev->id);
int len;
- len = snprint_alias(buf, PAGE_SIZE, id, "\n") + 1;
+ len = snprint_alias(buf, PAGE_SIZE, id, "\n");
return len > PAGE_SIZE ? PAGE_SIZE : len;
}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index e70aeb7a3781..ed026a1dc324 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -166,9 +166,9 @@ qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
{
char dbf_text[15];
- if (ccq == 0 || ccq == 32 || ccq == 96)
+ if (ccq == 0 || ccq == 32)
return 0;
- if (ccq == 97)
+ if (ccq == 96 || ccq == 97)
return 1;
/*notify devices immediately*/
sprintf(dbf_text,"%d", ccq);
@@ -2306,8 +2306,8 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
if (!ssqd_area) {
QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
"SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
- irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+ irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+ CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
irq_ptr->is_qebsm = 0;
irq_ptr->sch_token = 0;
@@ -2328,8 +2328,8 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
"SIGAs for sch 0.%x.%x.\n", result,
irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+ qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+ CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
irq_ptr->is_qebsm = 0;
goto out;
@@ -2340,8 +2340,8 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
"is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
ssqd_area->response.code,
irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+ qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+ CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
irq_ptr->is_qebsm = 0;
goto out;
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index b34eb82edd98..ec18bae05df0 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -211,6 +211,10 @@ struct qeth_perf_stats {
/* initial values when measuring starts */
unsigned long initial_rx_packets;
unsigned long initial_tx_packets;
+ /* inbound scatter gather data */
+ unsigned int sg_skbs_rx;
+ unsigned int sg_frags_rx;
+ unsigned int sg_alloc_page_rx;
};
/* Routing stuff */
@@ -341,6 +345,9 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
#define QETH_IP_HEADER_SIZE 40
+/* large receive scatter gather copy break */
+#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+
struct qeth_hdr_layer3 {
__u8 id;
__u8 flags;
@@ -771,6 +778,7 @@ struct qeth_card_options {
int layer2;
enum qeth_large_send_types large_send;
int performance_stats;
+ int rx_sg_cb;
};
/*
@@ -828,6 +836,7 @@ struct qeth_card {
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
unsigned short,void *,void *,unsigned);
struct qeth_osn_info osn_info;
+ atomic_t force_alloc_skb;
};
struct qeth_card_list_struct {
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 86b0c44165c1..57f69434fbf9 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1054,6 +1054,7 @@ qeth_set_intial_options(struct qeth_card *card)
else
card->options.layer2 = 0;
card->options.performance_stats = 0;
+ card->options.rx_sg_cb = QETH_RX_SG_CB;
}
/**
@@ -1934,6 +1935,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
atomic_inc(&reply->received);
wake_up(&reply->wait_q);
}
+ cpu_relax();
};
rc = reply->rc;
qeth_put_reply(reply);
@@ -2258,6 +2260,89 @@ qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
return skb;
}
+static inline int
+qeth_create_skb_frag(struct qdio_buffer_element *element,
+ struct sk_buff **pskb,
+ int offset, int *pfrag, int data_len)
+{
+ struct page *page = virt_to_page(element->addr);
+ if (*pfrag == 0) {
+ /* the upper protocol layers assume that there is data in the
+ * skb itself. Copy a small amount (64 bytes) to make them
+ * happy. */
+ *pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
+ if (!(*pskb))
+ return -ENOMEM;
+ skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
+ if (data_len <= 64) {
+ memcpy(skb_put(*pskb, data_len), element->addr + offset,
+ data_len);
+ } else {
+ get_page(page);
+ memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+ skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+ data_len - 64);
+ (*pskb)->data_len += data_len - 64;
+ (*pskb)->len += data_len - 64;
+ (*pskb)->truesize += data_len - 64;
+ }
+ } else {
+ get_page(page);
+ skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+ (*pskb)->data_len += data_len;
+ (*pskb)->len += data_len;
+ (*pskb)->truesize += data_len;
+ }
+ (*pfrag)++;
+ return 0;
+}
+
+static inline struct qeth_buffer_pool_entry *
+qeth_find_free_buffer_pool_entry(struct qeth_card *card)
+{
+ struct list_head *plh;
+ struct qeth_buffer_pool_entry *entry;
+ int i, free;
+ struct page *page;
+
+ if (list_empty(&card->qdio.in_buf_pool.entry_list))
+ return NULL;
+
+ list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+ entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+ free = 1;
+ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+ if (page_count(virt_to_page(entry->elements[i])) > 1) {
+ free = 0;
+ break;
+ }
+ }
+ if (free) {
+ list_del_init(&entry->list);
+ return entry;
+ }
+ }
+
+ /* no free buffer in pool so take first one and swap pages */
+ entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+ struct qeth_buffer_pool_entry, list);
+ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+ if (page_count(virt_to_page(entry->elements[i])) > 1) {
+ page = alloc_page(GFP_ATOMIC|GFP_DMA);
+ if (!page) {
+ return NULL;
+ } else {
+ free_page((unsigned long)entry->elements[i]);
+ entry->elements[i] = page_address(page);
+ if (card->options.performance_stats)
+ card->perf_stats.sg_alloc_page_rx++;
+ }
+ }
+ }
+ list_del_init(&entry->list);
+ return entry;
+}
+
static struct sk_buff *
qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
struct qdio_buffer_element **__element, int *__offset,
@@ -2269,6 +2354,8 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
int skb_len;
void *data_ptr;
int data_len;
+ int use_rx_sg = 0;
+ int frag = 0;
QETH_DBF_TEXT(trace,6,"nextskb");
/* qeth_hdr must not cross element boundaries */
@@ -2293,23 +2380,43 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
if (!skb_len)
return NULL;
- if (card->options.fake_ll){
- if(card->dev->type == ARPHRD_IEEE802_TR){
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
- goto no_mem;
- skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
+ if ((skb_len >= card->options.rx_sg_cb) &&
+ (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+ (!atomic_read(&card->force_alloc_skb))) {
+ use_rx_sg = 1;
+ } else {
+ if (card->options.fake_ll) {
+ if (card->dev->type == ARPHRD_IEEE802_TR) {
+ if (!(skb = qeth_get_skb(skb_len +
+ QETH_FAKE_LL_LEN_TR, *hdr)))
+ goto no_mem;
+ skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
+ } else {
+ if (!(skb = qeth_get_skb(skb_len +
+ QETH_FAKE_LL_LEN_ETH, *hdr)))
+ goto no_mem;
+ skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
+ }
} else {
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
+ skb = qeth_get_skb(skb_len, *hdr);
+ if (!skb)
goto no_mem;
- skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
}
- } else if (!(skb = qeth_get_skb(skb_len, *hdr)))
- goto no_mem;
+ }
+
data_ptr = element->addr + offset;
while (skb_len) {
data_len = min(skb_len, (int)(element->length - offset));
- if (data_len)
- memcpy(skb_put(skb, data_len), data_ptr, data_len);
+ if (data_len) {
+ if (use_rx_sg) {
+ if (qeth_create_skb_frag(element, &skb, offset,
+ &frag, data_len))
+ goto no_mem;
+ } else {
+ memcpy(skb_put(skb, data_len), data_ptr,
+ data_len);
+ }
+ }
skb_len -= data_len;
if (skb_len){
if (qeth_is_last_sbale(element)){
@@ -2331,6 +2438,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
}
*__element = element;
*__offset = offset;
+ if (use_rx_sg && card->options.performance_stats) {
+ card->perf_stats.sg_skbs_rx++;
+ card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+ }
return skb;
no_mem:
if (net_ratelimit()){
@@ -2608,28 +2719,15 @@ qeth_process_inbound_buffer(struct qeth_card *card,
}
}
-static struct qeth_buffer_pool_entry *
-qeth_get_buffer_pool_entry(struct qeth_card *card)
-{
- struct qeth_buffer_pool_entry *entry;
-
- QETH_DBF_TEXT(trace, 6, "gtbfplen");
- if (!list_empty(&card->qdio.in_buf_pool.entry_list)) {
- entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
- struct qeth_buffer_pool_entry, list);
- list_del_init(&entry->list);
- return entry;
- }
- return NULL;
-}
-
-static void
+static int
qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
{
struct qeth_buffer_pool_entry *pool_entry;
int i;
-
- pool_entry = qeth_get_buffer_pool_entry(card);
+
+ pool_entry = qeth_find_free_buffer_pool_entry(card);
+ if (!pool_entry)
+ return 1;
/*
* since the buffer is accessed only from the input_tasklet
* there shouldn't be a need to synchronize; also, since we use
@@ -2648,6 +2746,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
buf->buffer->element[i].flags = 0;
}
buf->state = QETH_QDIO_BUF_EMPTY;
+ return 0;
}
static void
@@ -2682,6 +2781,7 @@ qeth_queue_input_buffer(struct qeth_card *card, int index)
int count;
int i;
int rc;
+ int newcount = 0;
QETH_DBF_TEXT(trace,6,"queinbuf");
count = (index < queue->next_buf_to_init)?
@@ -2692,9 +2792,27 @@ qeth_queue_input_buffer(struct qeth_card *card, int index)
/* only requeue at a certain threshold to avoid SIGAs */
if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
for (i = queue->next_buf_to_init;
- i < queue->next_buf_to_init + count; ++i)
- qeth_init_input_buffer(card,
- &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]);
+ i < queue->next_buf_to_init + count; ++i) {
+ if (qeth_init_input_buffer(card,
+ &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+ break;
+ } else {
+ newcount++;
+ }
+ }
+
+ if (newcount < count) {
+ /* we are in memory shortage so we switch back to
+ traditional skb allocation and drop packages */
+ if (atomic_cmpxchg(&card->force_alloc_skb, 0, 1))
+ printk(KERN_WARNING
+ "qeth: switch to alloc skb\n");
+ count = newcount;
+ } else {
+ if (atomic_cmpxchg(&card->force_alloc_skb, 1, 0))
+ printk(KERN_WARNING "qeth: switch to sg\n");
+ }
+
/*
* according to old code it should be avoided to requeue all
* 128 buffers in order to benefit from PCI avoidance.
@@ -6494,6 +6612,7 @@ qeth_hardsetup_card(struct qeth_card *card)
QETH_DBF_TEXT(setup, 2, "hrdsetup");
+ atomic_set(&card->force_alloc_skb, 0);
retry:
if (retries < 3){
PRINT_WARN("Retrying to do IDX activates.\n");
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 89d56c8ecdd2..f1ff165a5e05 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -212,6 +212,12 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
" Skb fragments sent in SG mode : %u\n\n",
card->perf_stats.sg_skbs_sent,
card->perf_stats.sg_frags_sent);
+ seq_printf(s, " Skbs received in SG mode : %u\n"
+ " Skb fragments received in SG mode : %u\n"
+ " Page allocations for rx SG mode : %u\n\n",
+ card->perf_stats.sg_skbs_rx,
+ card->perf_stats.sg_frags_rx,
+ card->perf_stats.sg_alloc_page_rx);
seq_printf(s, " large_send tx (in Kbytes) : %u\n"
" large_send count : %u\n\n",
card->perf_stats.large_send_bytes >> 10,
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 022e869c44dd..7b5773d88212 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/smp_lock.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/ebus.h>
#include <asm/oplib.h>
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 512857a23169..5157a2abc58d 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -619,8 +619,7 @@ static void __exit jsflash_cleanup_module(void)
jsf0.busy = 0;
misc_deregister(&jsf_dev);
- if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0)
- printk("jsfd: cleanup_module failed\n");
+ unregister_blkdev(JSFD_MAJOR, "jsfd");
blk_cleanup_queue(jsf_queue);
}
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 9d2119b53ac9..372723161c97 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -545,7 +545,7 @@ config SCSI_HPTIOP
config SCSI_BUSLOGIC
tristate "BusLogic SCSI support"
- depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
+ depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API && VIRT_TO_BUS
---help---
This is support for BusLogic MultiMaster and FlashPoint SCSI Host
Adapters. Consult the SCSI-HOWTO, available from
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index d70ddfda93fc..9c5342e7a69c 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -40,6 +40,7 @@
#include <linux/err.h>
#include <linux/blkdev.h>
+#include <linux/freezer.h>
#include <linux/scatterlist.h>
/* ---------- SCSI Host glue ---------- */
@@ -868,8 +869,6 @@ static int sas_queue_thread(void *_sas_ha)
{
struct sas_ha_struct *sas_ha = _sas_ha;
- current->flags |= PF_NOFREEZE;
-
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
schedule();
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 9adb64ac054c..8a525abda30f 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -19,6 +19,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
@@ -1516,8 +1517,6 @@ int scsi_error_handler(void *data)
{
struct Scsi_Host *shost = data;
- current->flags |= PF_NOFREEZE;
-
/*
* We use TASK_INTERRUPTIBLE so that the thread is not
* counted against the load average as a running process.
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 448d316f12d7..424d557284a9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -684,7 +684,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
case SCSI_IOCTL_GET_BUS_NUMBER:
return scsi_ioctl(sdp, cmd, p);
default:
- error = scsi_cmd_ioctl(filp, disk, cmd, p);
+ error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
if (error != -ENOTTY)
return error;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 55bfeccf68a2..a4f7b8465773 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3549,7 +3549,8 @@ static int st_ioctl(struct inode *inode, struct file *file,
!capable(CAP_SYS_RAWIO))
i = -EPERM;
else
- i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
+ i = scsi_cmd_ioctl(file, STp->disk->queue,
+ STp->disk, cmd_in, p);
if (i != -ENOTTY)
return i;
break;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 68817a7d8c0d..2aa6bfe8fdb3 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -934,8 +934,6 @@ static void change_speed(ser_info_t *info)
/*
* Set up parity check flag
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
if (I_INPCK(info->tty))
info->read_status_mask |= BD_SC_FR | BD_SC_PR;
@@ -1527,11 +1525,6 @@ static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_term
{
ser_info_t *info = (ser_info_t *)tty->driver_data;
- if ( (tty->termios->c_cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_speed(info);
#ifdef modem_control
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab083a85..0b3ec38ae614 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2514,12 +2514,18 @@ static int __init serial8250_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
+static int __init serial8250_console_early_setup(void)
+{
+ return serial8250_find_port_for_earlycon();
+}
+
static struct uart_driver serial8250_reg;
static struct console serial8250_console = {
.name = "ttyS",
.write = serial8250_console_write,
.device = uart_console_device,
.setup = serial8250_console_setup,
+ .early_setup = serial8250_console_early_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &serial8250_reg,
@@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void)
}
console_initcall(serial8250_console_init);
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
{
int line;
struct uart_port *port;
@@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p)
return -ENODEV;
}
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
- int line;
-
- line = find_port(port);
- if (line < 0)
- return -ENODEV;
-
- add_preferred_console("ttyS", line, options);
- printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
- line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
- port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
- (unsigned long) port->iobase, options);
- if (!(serial8250_console.flags & CON_ENABLED)) {
- serial8250_console.flags &= ~CON_PRINTBUFFER;
- register_console(&serial8250_console);
- }
- return line;
-}
-
#define SERIAL8250_CONSOLE &serial8250_console
#else
#define SERIAL8250_CONSOLE NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e511199b4c5..947c20507e1f 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
* we locate the device directly by its MMIO or I/O port address.
*
* The user can specify the device directly, e.g.,
- * console=uart,io,0x3f8,9600n8
- * console=uart,mmio,0xff5e0000,115200n8
- * or platform code can call early_uart_console_init() to set
- * the early UART device.
- *
- * After the normal serial driver starts, we try to locate the
- * matching ttyS device and start a console there.
+ * earlycon=uart8250,io,0x3f8,9600n8
+ * earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * or
+ * console=uart8250,io,0x3f8,9600n8
+ * console=uart8250,mmio,0xff5e0000,115200n8
*/
#include <linux/tty.h>
@@ -32,17 +30,21 @@
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/serial.h>
+#include <linux/serial_8250.h>
#include <asm/io.h>
#include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
-struct early_uart_device {
+struct early_serial8250_device {
struct uart_port port;
char options[16]; /* e.g., 115200n8 */
unsigned int baud;
};
-static struct early_uart_device early_device __initdata;
-static int early_uart_registered __initdata;
+static struct early_serial8250_device early_device;
static unsigned int __init serial_in(struct uart_port *port, int offset)
{
@@ -80,7 +82,7 @@ static void __init putc(struct uart_port *port, int c)
serial_out(port, UART_TX, c);
}
-static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
+static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
{
struct uart_port *port = &early_device.port;
unsigned int ier;
@@ -111,7 +113,7 @@ static unsigned int __init probe_baud(struct uart_port *port)
return (port->uartclk / 16) / quot;
}
-static void __init init_port(struct early_uart_device *device)
+static void __init init_port(struct early_serial8250_device *device)
{
struct uart_port *port = &device->port;
unsigned int divisor;
@@ -130,10 +132,9 @@ static void __init init_port(struct early_uart_device *device)
serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
}
-static int __init parse_options(struct early_uart_device *device, char *options)
+static int __init parse_options(struct early_serial8250_device *device, char *options)
{
struct uart_port *port = &device->port;
- int mapsize = 64;
int mmio, length;
if (!options)
@@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options)
if (!strncmp(options, "mmio,", 5)) {
port->iotype = UPIO_MEM;
port->mapbase = simple_strtoul(options + 5, &options, 0);
- port->membase = ioremap(port->mapbase, mapsize);
+#ifdef CONFIG_FIX_EARLYCON_MEM
+ set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
+ port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+ port->membase += port->mapbase & ~PAGE_MASK;
+#else
+ port->membase = ioremap(port->mapbase, 64);
if (!port->membase) {
printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
__FUNCTION__, port->mapbase);
return -ENOMEM;
}
+#endif
mmio = 1;
} else if (!strncmp(options, "io,", 3)) {
port->iotype = UPIO_PORT;
@@ -175,9 +182,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
return 0;
}
-static int __init early_uart_setup(struct console *console, char *options)
+static struct console early_serial8250_console __initdata = {
+ .name = "uart",
+ .write = early_serial8250_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+ .index = -1,
+};
+
+static int __init early_serial8250_setup(char *options)
{
- struct early_uart_device *device = &early_device;
+ struct early_serial8250_device *device = &early_device;
int err;
if (device->port.membase || device->port.iobase)
@@ -190,61 +204,48 @@ static int __init early_uart_setup(struct console *console, char *options)
return 0;
}
-static struct console early_uart_console __initdata = {
- .name = "uart",
- .write = early_uart_write,
- .setup = early_uart_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static int __init early_uart_console_init(void)
-{
- if (!early_uart_registered) {
- register_console(&early_uart_console);
- early_uart_registered = 1;
- }
- return 0;
-}
-console_initcall(early_uart_console_init);
-
-int __init early_serial_console_init(char *cmdline)
+int __init setup_early_serial8250_console(char *cmdline)
{
char *options;
int err;
- options = strstr(cmdline, "console=uart,");
- if (!options)
- return -ENODEV;
+ options = strstr(cmdline, "uart8250,");
+ if (!options) {
+ options = strstr(cmdline, "uart,");
+ if (!options)
+ return 0;
+ }
options = strchr(cmdline, ',') + 1;
- if ((err = early_uart_setup(NULL, options)) < 0)
+ if ((err = early_serial8250_setup(options)) < 0)
return err;
- return early_uart_console_init();
+
+ register_console(&early_serial8250_console);
+
+ return 0;
}
-static int __init early_uart_console_switch(void)
+int __init serial8250_find_port_for_earlycon(void)
{
- struct early_uart_device *device = &early_device;
+ struct early_serial8250_device *device = &early_device;
struct uart_port *port = &device->port;
- int mmio, line;
+ int line;
+ int ret;
- if (!(early_uart_console.flags & CON_ENABLED))
- return 0;
+ if (!device->port.membase && !device->port.iobase)
+ return -ENODEV;
- /* Try to start the normal driver on a matching line. */
- mmio = (port->iotype == UPIO_MEM);
- line = serial8250_start_console(port, device->options);
+ line = serial8250_find_port(port);
if (line < 0)
- printk("No ttyS device at %s 0x%lx for console\n",
- mmio ? "MMIO" : "I/O port",
- mmio ? port->mapbase :
- (unsigned long) port->iobase);
+ return -ENODEV;
- unregister_console(&early_uart_console);
- if (mmio)
- iounmap(port->membase);
+ ret = update_console_cmdline("uart", 8250,
+ "ttyS", line, device->options);
+ if (ret < 0)
+ ret = update_console_cmdline("uart", 0,
+ "ttyS", line, device->options);
- return 0;
+ return ret;
}
-late_initcall(early_uart_console_switch);
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 2adbed4e10f3..7fa413ddccf5 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,8 +62,22 @@ config SERIAL_8250_CONSOLE
kernel will automatically use the first serial line, /dev/ttyS0, as
system console.
+ you can set that using a kernel command line option such as
+ "console=uart8250,io,0x3f8,9600n8"
+ "console=uart8250,mmio,0xff5e0000,115200n8".
+ and it will switch to normal serial console when correponding port is
+ ready.
+ "earlycon=uart8250,io,0x3f8,9600n8"
+ "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+ it will not only setup early console.
+
If unsure, say N.
+config FIX_EARLYCON_MEM
+ bool
+ depends on X86
+ default y
+
config SERIAL_8250_GSC
tristate
depends on SERIAL_8250 && GSC
@@ -324,6 +338,34 @@ config SERIAL_AMBA_PL011_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
+config SERIAL_SB1250_DUART
+ tristate "BCM1xxx on-chip DUART serial support"
+ depends on SIBYTE_SB1xxx_SOC=y
+ select SERIAL_CORE
+ default y
+ ---help---
+ Support for the asynchronous serial interface (DUART) included in
+ the BCM1250 and derived System-On-a-Chip (SOC) devices. Note that
+ the letter D in DUART stands for "dual", which is how the device
+ is implemented. Depending on the SOC configuration there may be
+ one or more DUARTs available of which all are handled.
+
+ If unsure, say Y. To compile this driver as a module, choose M here:
+ the module will be called sb1250-duart.
+
+config SERIAL_SB1250_DUART_CONSOLE
+ bool "Support for console on a BCM1xxx DUART serial port"
+ depends on SERIAL_SB1250_DUART=y
+ select SERIAL_CORE_CONSOLE
+ default y
+ ---help---
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode).
+
+ If unsure, say Y.
+
config SERIAL_ATMEL
bool "AT91 / AT32 on-chip serial port support"
depends on (ARM && ARCH_AT91) || AVR32
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 08ad0d978183..c48cdd61b736 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
obj-$(CONFIG_SERIAL_ICOM) += icom.o
obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
+obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 3320bcd92c0a..4d6b3c56d20e 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -114,6 +114,7 @@ struct atmel_uart_port {
struct uart_port uart; /* uart */
struct clk *clk; /* uart clock */
unsigned short suspended; /* is port suspended? */
+ int break_active; /* break being received */
};
static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@@ -252,6 +253,7 @@ static void atmel_break_ctl(struct uart_port *port, int break_state)
*/
static void atmel_rx_chars(struct uart_port *port)
{
+ struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, flg;
@@ -267,13 +269,29 @@ static void atmel_rx_chars(struct uart_port *port)
* note that the error handling code is
* out of the main execution path
*/
- if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
+ if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
+ | ATMEL_US_OVRE | ATMEL_US_RXBRK)
+ || atmel_port->break_active)) {
UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */
- if (status & ATMEL_US_RXBRK) {
+ if (status & ATMEL_US_RXBRK
+ && !atmel_port->break_active) {
status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */
port->icount.brk++;
+ atmel_port->break_active = 1;
+ UART_PUT_IER(port, ATMEL_US_RXBRK);
if (uart_handle_break(port))
goto ignore_char;
+ } else {
+ /*
+ * This is either the end-of-break
+ * condition or we've received at
+ * least one character without RXBRK
+ * being set. In both cases, the next
+ * RXBRK will indicate start-of-break.
+ */
+ UART_PUT_IDR(port, ATMEL_US_RXBRK);
+ status &= ~ATMEL_US_RXBRK;
+ atmel_port->break_active = 0;
}
if (status & ATMEL_US_PARE)
port->icount.parity++;
@@ -352,6 +370,16 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
/* Interrupt receive */
if (pending & ATMEL_US_RXRDY)
atmel_rx_chars(port);
+ else if (pending & ATMEL_US_RXBRK) {
+ /*
+ * End of break detected. If it came along
+ * with a character, atmel_rx_chars will
+ * handle it.
+ */
+ UART_PUT_CR(port, ATMEL_US_RSTSTA);
+ UART_PUT_IDR(port, ATMEL_US_RXBRK);
+ atmel_port->break_active = 0;
+ }
// TODO: All reads to CSR will clear these interrupts!
if (pending & ATMEL_US_RIIC) port->icount.rng++;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b63ff8dd7304..cefde58dbad2 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -678,7 +678,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
}
bdp->cbd_datlen = count;
bdp->cbd_sc |= BD_SC_READY;
- __asm__("eieio");
+ eieio();
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index c3abfb39f316..f3257f708ef9 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -862,6 +862,7 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
up->cflag = termios->c_cflag;
ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+ uart_update_timeout(port, termios->c_cflag, baud);
spin_unlock_irqrestore(&up->port.lock, flags);
}
@@ -1017,6 +1018,8 @@ ip22serial_console_termios(struct console *con, char *options)
}
con->cflag = cflag | CS8; /* 8N1 */
+
+ uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud);
}
static int __init ip22zilog_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
index 7ffdaeaf0545..a64d85821996 100644
--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -17,6 +17,11 @@
#include <asm/of_platform.h>
#include <asm/prom.h>
+struct of_serial_info {
+ int type;
+ int line;
+};
+
/*
* Fill a struct uart_port for a given device node
*/
@@ -62,6 +67,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
static int __devinit of_platform_serial_probe(struct of_device *ofdev,
const struct of_device_id *id)
{
+ struct of_serial_info *info;
struct uart_port port;
int port_type;
int ret;
@@ -69,30 +75,35 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev,
if (of_find_property(ofdev->node, "used-by-rtas", NULL))
return -EBUSY;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (info == NULL)
+ return -ENOMEM;
+
port_type = (unsigned long)id->data;
ret = of_platform_serial_setup(ofdev, port_type, &port);
if (ret)
goto out;
switch (port_type) {
- case PORT_UNKNOWN:
- dev_info(&ofdev->dev, "Unknown serial port found, "
- "attempting to use 8250 driver\n");
- /* fallthrough */
case PORT_8250 ... PORT_MAX_8250:
ret = serial8250_register_port(&port);
break;
default:
/* need to add code for these */
+ case PORT_UNKNOWN:
+ dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
ret = -ENODEV;
break;
}
if (ret < 0)
goto out;
- ofdev->dev.driver_data = (void *)(unsigned long)ret;
+ info->type = port_type;
+ info->line = ret;
+ ofdev->dev.driver_data = info;
return 0;
out:
+ kfree(info);
irq_dispose_mapping(port.irq);
return ret;
}
@@ -102,8 +113,16 @@ out:
*/
static int of_platform_serial_remove(struct of_device *ofdev)
{
- int line = (unsigned long)ofdev->dev.driver_data;
- serial8250_unregister_port(line);
+ struct of_serial_info *info = ofdev->dev.driver_data;
+ switch (info->type) {
+ case PORT_8250 ... PORT_MAX_8250:
+ serial8250_unregister_port(info->line);
+ break;
+ default:
+ /* need to add code for these */
+ break;
+ }
+ kfree(info);
return 0;
}
diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c
new file mode 100644
index 000000000000..1d9d7285172a
--- /dev/null
+++ b/drivers/serial/sb1250-duart.c
@@ -0,0 +1,972 @@
+/*
+ * drivers/serial/sb1250-duart.c
+ *
+ * Support for the asynchronous serial interface (DUART) included
+ * in the BCM1250 and derived System-On-a-Chip (SOC) devices.
+ *
+ * Copyright (c) 2007 Maciej W. Rozycki
+ *
+ * Derived from drivers/char/sb1250_duart.c for which the following
+ * copyright applies:
+ *
+ * Copyright (c) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * References:
+ *
+ * "BCM1250/BCM1125/BCM1125H User Manual", Broadcom Corporation
+ */
+
+#if defined(CONFIG_SERIAL_SB1250_DUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/war.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/swarm.h>
+
+
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+#define SBD_CHANREGS(line) A_BCM1480_DUART_CHANREG((line), 0)
+#define SBD_CTRLREGS(line) A_BCM1480_DUART_CTRLREG((line), 0)
+#define SBD_INT(line) (K_BCM1480_INT_UART_0 + (line))
+
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+
+#define SBD_CHANREGS(line) A_DUART_CHANREG((line), 0)
+#define SBD_CTRLREGS(line) A_DUART_CTRLREG(0)
+#define SBD_INT(line) (K_INT_UART_0 + (line))
+
+#else
+#error invalid SB1250 UART configuration
+
+#endif
+
+
+MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
+MODULE_DESCRIPTION("BCM1xxx on-chip DUART serial driver");
+MODULE_LICENSE("GPL");
+
+
+#define DUART_MAX_CHIP 2
+#define DUART_MAX_SIDE 2
+
+/*
+ * Per-port state.
+ */
+struct sbd_port {
+ struct sbd_duart *duart;
+ struct uart_port port;
+ unsigned char __iomem *memctrl;
+ int tx_stopped;
+ int initialised;
+};
+
+/*
+ * Per-DUART state for the shared register space.
+ */
+struct sbd_duart {
+ struct sbd_port sport[2];
+ unsigned long mapctrl;
+ atomic_t map_guard;
+};
+
+#define to_sport(uport) container_of(uport, struct sbd_port, port)
+
+static struct sbd_duart sbd_duarts[DUART_MAX_CHIP];
+
+#define __unused __attribute__((__unused__))
+
+
+/*
+ * Reading and writing SB1250 DUART registers.
+ *
+ * There are three register spaces: two per-channel ones and
+ * a shared one. We have to define accessors appropriately.
+ * All registers are 64-bit and all but the Baud Rate Clock
+ * registers only define 8 least significant bits. There is
+ * also a workaround to take into account. Raw accessors use
+ * the full register width, but cooked ones truncate it
+ * intentionally so that the rest of the driver does not care.
+ */
+static u64 __read_sbdchn(struct sbd_port *sport, int reg)
+{
+ void __iomem *csr = sport->port.membase + reg;
+
+ return __raw_readq(csr);
+}
+
+static u64 __read_sbdshr(struct sbd_port *sport, int reg)
+{
+ void __iomem *csr = sport->memctrl + reg;
+
+ return __raw_readq(csr);
+}
+
+static void __write_sbdchn(struct sbd_port *sport, int reg, u64 value)
+{
+ void __iomem *csr = sport->port.membase + reg;
+
+ __raw_writeq(value, csr);
+}
+
+static void __write_sbdshr(struct sbd_port *sport, int reg, u64 value)
+{
+ void __iomem *csr = sport->memctrl + reg;
+
+ __raw_writeq(value, csr);
+}
+
+/*
+ * In bug 1956, we get glitches that can mess up uart registers. This
+ * "read-mode-reg after any register access" is an accepted workaround.
+ */
+static void __war_sbd1956(struct sbd_port *sport)
+{
+ __read_sbdchn(sport, R_DUART_MODE_REG_1);
+ __read_sbdchn(sport, R_DUART_MODE_REG_2);
+}
+
+static unsigned char read_sbdchn(struct sbd_port *sport, int reg)
+{
+ unsigned char retval;
+
+ retval = __read_sbdchn(sport, reg);
+ if (SIBYTE_1956_WAR)
+ __war_sbd1956(sport);
+ return retval;
+}
+
+static unsigned char read_sbdshr(struct sbd_port *sport, int reg)
+{
+ unsigned char retval;
+
+ retval = __read_sbdshr(sport, reg);
+ if (SIBYTE_1956_WAR)
+ __war_sbd1956(sport);
+ return retval;
+}
+
+static void write_sbdchn(struct sbd_port *sport, int reg, unsigned int value)
+{
+ __write_sbdchn(sport, reg, value);
+ if (SIBYTE_1956_WAR)
+ __war_sbd1956(sport);
+}
+
+static void write_sbdshr(struct sbd_port *sport, int reg, unsigned int value)
+{
+ __write_sbdshr(sport, reg, value);
+ if (SIBYTE_1956_WAR)
+ __war_sbd1956(sport);
+}
+
+
+static int sbd_receive_ready(struct sbd_port *sport)
+{
+ return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_RX_RDY;
+}
+
+static int sbd_receive_drain(struct sbd_port *sport)
+{
+ int loops = 10000;
+
+ while (sbd_receive_ready(sport) && loops--)
+ read_sbdchn(sport, R_DUART_RX_HOLD);
+ return loops;
+}
+
+static int __unused sbd_transmit_ready(struct sbd_port *sport)
+{
+ return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_RDY;
+}
+
+static int __unused sbd_transmit_drain(struct sbd_port *sport)
+{
+ int loops = 10000;
+
+ while (!sbd_transmit_ready(sport) && loops--)
+ udelay(2);
+ return loops;
+}
+
+static int sbd_transmit_empty(struct sbd_port *sport)
+{
+ return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_EMT;
+}
+
+static int sbd_line_drain(struct sbd_port *sport)
+{
+ int loops = 10000;
+
+ while (!sbd_transmit_empty(sport) && loops--)
+ udelay(2);
+ return loops;
+}
+
+
+static unsigned int sbd_tx_empty(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ return sbd_transmit_empty(sport) ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int sbd_get_mctrl(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+ unsigned int mctrl, status;
+
+ status = read_sbdshr(sport, R_DUART_IN_PORT);
+ status >>= (uport->line) % 2;
+ mctrl = (!(status & M_DUART_IN_PIN0_VAL) ? TIOCM_CTS : 0) |
+ (!(status & M_DUART_IN_PIN4_VAL) ? TIOCM_CAR : 0) |
+ (!(status & M_DUART_RIN0_PIN) ? TIOCM_RNG : 0) |
+ (!(status & M_DUART_IN_PIN2_VAL) ? TIOCM_DSR : 0);
+ return mctrl;
+}
+
+static void sbd_set_mctrl(struct uart_port *uport, unsigned int mctrl)
+{
+ struct sbd_port *sport = to_sport(uport);
+ unsigned int clr = 0, set = 0, mode2;
+
+ if (mctrl & TIOCM_DTR)
+ set |= M_DUART_SET_OPR2;
+ else
+ clr |= M_DUART_CLR_OPR2;
+ if (mctrl & TIOCM_RTS)
+ set |= M_DUART_SET_OPR0;
+ else
+ clr |= M_DUART_CLR_OPR0;
+ clr <<= (uport->line) % 2;
+ set <<= (uport->line) % 2;
+
+ mode2 = read_sbdchn(sport, R_DUART_MODE_REG_2);
+ mode2 &= ~M_DUART_CHAN_MODE;
+ if (mctrl & TIOCM_LOOP)
+ mode2 |= V_DUART_CHAN_MODE_LCL_LOOP;
+ else
+ mode2 |= V_DUART_CHAN_MODE_NORMAL;
+
+ write_sbdshr(sport, R_DUART_CLEAR_OPR, clr);
+ write_sbdshr(sport, R_DUART_SET_OPR, set);
+ write_sbdchn(sport, R_DUART_MODE_REG_2, mode2);
+}
+
+static void sbd_stop_tx(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+ sport->tx_stopped = 1;
+};
+
+static void sbd_start_tx(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+ unsigned int mask;
+
+ /* Enable tx interrupts. */
+ mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+ mask |= M_DUART_IMR_TX;
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+
+ /* Go!, go!, go!... */
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+ sport->tx_stopped = 0;
+};
+
+static void sbd_stop_rx(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
+};
+
+static void sbd_enable_ms(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ write_sbdchn(sport, R_DUART_AUXCTL_X,
+ M_DUART_CIN_CHNG_ENA | M_DUART_CTS_CHNG_ENA);
+}
+
+static void sbd_break_ctl(struct uart_port *uport, int break_state)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ if (break_state == -1)
+ write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_START_BREAK);
+ else
+ write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_STOP_BREAK);
+}
+
+
+static void sbd_receive_chars(struct sbd_port *sport)
+{
+ struct uart_port *uport = &sport->port;
+ struct uart_icount *icount;
+ unsigned int status, ch, flag;
+ int count;
+
+ for (count = 16; count; count--) {
+ status = read_sbdchn(sport, R_DUART_STATUS);
+ if (!(status & M_DUART_RX_RDY))
+ break;
+
+ ch = read_sbdchn(sport, R_DUART_RX_HOLD);
+
+ flag = TTY_NORMAL;
+
+ icount = &uport->icount;
+ icount->rx++;
+
+ if (unlikely(status &
+ (M_DUART_RCVD_BRK | M_DUART_FRM_ERR |
+ M_DUART_PARITY_ERR | M_DUART_OVRUN_ERR))) {
+ if (status & M_DUART_RCVD_BRK) {
+ icount->brk++;
+ if (uart_handle_break(uport))
+ continue;
+ } else if (status & M_DUART_FRM_ERR)
+ icount->frame++;
+ else if (status & M_DUART_PARITY_ERR)
+ icount->parity++;
+ if (status & M_DUART_OVRUN_ERR)
+ icount->overrun++;
+
+ status &= uport->read_status_mask;
+ if (status & M_DUART_RCVD_BRK)
+ flag = TTY_BREAK;
+ else if (status & M_DUART_FRM_ERR)
+ flag = TTY_FRAME;
+ else if (status & M_DUART_PARITY_ERR)
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(uport, ch))
+ continue;
+
+ uart_insert_char(uport, status, M_DUART_OVRUN_ERR, ch, flag);
+ }
+
+ tty_flip_buffer_push(uport->info->tty);
+}
+
+static void sbd_transmit_chars(struct sbd_port *sport)
+{
+ struct uart_port *uport = &sport->port;
+ struct circ_buf *xmit = &sport->port.info->xmit;
+ unsigned int mask;
+ int stop_tx;
+
+ /* XON/XOFF chars. */
+ if (sport->port.x_char) {
+ write_sbdchn(sport, R_DUART_TX_HOLD, sport->port.x_char);
+ sport->port.icount.tx++;
+ sport->port.x_char = 0;
+ return;
+ }
+
+ /* If nothing to do or stopped or hardware stopped. */
+ stop_tx = (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port));
+
+ /* Send char. */
+ if (!stop_tx) {
+ write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ sport->port.icount.tx++;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&sport->port);
+ }
+
+ /* Are we are done? */
+ if (stop_tx || uart_circ_empty(xmit)) {
+ /* Disable tx interrupts. */
+ mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+ mask &= ~M_DUART_IMR_TX;
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+ }
+}
+
+static void sbd_status_handle(struct sbd_port *sport)
+{
+ struct uart_port *uport = &sport->port;
+ unsigned int delta;
+
+ delta = read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
+ delta >>= (uport->line) % 2;
+
+ if (delta & (M_DUART_IN_PIN0_VAL << S_DUART_IN_PIN_CHNG))
+ uart_handle_cts_change(uport, !(delta & M_DUART_IN_PIN0_VAL));
+
+ if (delta & (M_DUART_IN_PIN2_VAL << S_DUART_IN_PIN_CHNG))
+ uport->icount.dsr++;
+
+ if (delta & ((M_DUART_IN_PIN2_VAL | M_DUART_IN_PIN0_VAL) <<
+ S_DUART_IN_PIN_CHNG))
+ wake_up_interruptible(&uport->info->delta_msr_wait);
+}
+
+static irqreturn_t sbd_interrupt(int irq, void *dev_id)
+{
+ struct sbd_port *sport = dev_id;
+ struct uart_port *uport = &sport->port;
+ irqreturn_t status = IRQ_NONE;
+ unsigned int intstat;
+ int count;
+
+ for (count = 16; count; count--) {
+ intstat = read_sbdshr(sport,
+ R_DUART_ISRREG((uport->line) % 2));
+ intstat &= read_sbdshr(sport,
+ R_DUART_IMRREG((uport->line) % 2));
+ intstat &= M_DUART_ISR_ALL;
+ if (!intstat)
+ break;
+
+ if (intstat & M_DUART_ISR_RX)
+ sbd_receive_chars(sport);
+ if (intstat & M_DUART_ISR_IN)
+ sbd_status_handle(sport);
+ if (intstat & M_DUART_ISR_TX)
+ sbd_transmit_chars(sport);
+
+ status = IRQ_HANDLED;
+ }
+
+ return status;
+}
+
+
+static int sbd_startup(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+ unsigned int mode1;
+ int ret;
+
+ ret = request_irq(sport->port.irq, sbd_interrupt,
+ IRQF_SHARED, "sb1250-duart", sport);
+ if (ret)
+ return ret;
+
+ /* Clear the receive FIFO. */
+ sbd_receive_drain(sport);
+
+ /* Clear the interrupt registers. */
+ write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT);
+ read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
+
+ /* Set rx/tx interrupt to FIFO available. */
+ mode1 = read_sbdchn(sport, R_DUART_MODE_REG_1);
+ mode1 &= ~(M_DUART_RX_IRQ_SEL_RXFULL | M_DUART_TX_IRQ_SEL_TXEMPT);
+ write_sbdchn(sport, R_DUART_MODE_REG_1, mode1);
+
+ /* Disable tx, enable rx. */
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_EN);
+ sport->tx_stopped = 1;
+
+ /* Enable interrupts. */
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+ M_DUART_IMR_IN | M_DUART_IMR_RX);
+
+ return 0;
+}
+
+static void sbd_shutdown(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
+ sport->tx_stopped = 1;
+ free_irq(sport->port.irq, sport);
+}
+
+
+static void sbd_init_port(struct sbd_port *sport)
+{
+ struct uart_port *uport = &sport->port;
+
+ if (sport->initialised)
+ return;
+
+ /* There is no DUART reset feature, so just set some sane defaults. */
+ write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_TX);
+ write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_RX);
+ write_sbdchn(sport, R_DUART_MODE_REG_1, V_DUART_BITS_PER_CHAR_8);
+ write_sbdchn(sport, R_DUART_MODE_REG_2, 0);
+ write_sbdchn(sport, R_DUART_FULL_CTL,
+ V_DUART_INT_TIME(0) | V_DUART_SIG_FULL(15));
+ write_sbdchn(sport, R_DUART_OPCR_X, 0);
+ write_sbdchn(sport, R_DUART_AUXCTL_X, 0);
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
+
+ sport->initialised = 1;
+}
+
+static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios,
+ struct ktermios *old_termios)
+{
+ struct sbd_port *sport = to_sport(uport);
+ unsigned int mode1 = 0, mode2 = 0, aux = 0;
+ unsigned int mode1mask = 0, mode2mask = 0, auxmask = 0;
+ unsigned int oldmode1, oldmode2, oldaux;
+ unsigned int baud, brg;
+ unsigned int command;
+
+ mode1mask |= ~(M_DUART_PARITY_MODE | M_DUART_PARITY_TYPE_ODD |
+ M_DUART_BITS_PER_CHAR);
+ mode2mask |= ~M_DUART_STOP_BIT_LEN_2;
+ auxmask |= ~M_DUART_CTS_CHNG_ENA;
+
+ /* Byte size. */
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ case CS6:
+ /* Unsupported, leave unchanged. */
+ mode1mask |= M_DUART_PARITY_MODE;
+ break;
+ case CS7:
+ mode1 |= V_DUART_BITS_PER_CHAR_7;
+ break;
+ case CS8:
+ default:
+ mode1 |= V_DUART_BITS_PER_CHAR_8;
+ break;
+ }
+
+ /* Parity and stop bits. */
+ if (termios->c_cflag & CSTOPB)
+ mode2 |= M_DUART_STOP_BIT_LEN_2;
+ else
+ mode2 |= M_DUART_STOP_BIT_LEN_1;
+ if (termios->c_cflag & PARENB)
+ mode1 |= V_DUART_PARITY_MODE_ADD;
+ else
+ mode1 |= V_DUART_PARITY_MODE_NONE;
+ if (termios->c_cflag & PARODD)
+ mode1 |= M_DUART_PARITY_TYPE_ODD;
+ else
+ mode1 |= M_DUART_PARITY_TYPE_EVEN;
+
+ baud = uart_get_baud_rate(uport, termios, old_termios, 1200, 5000000);
+ brg = V_DUART_BAUD_RATE(baud);
+ /* The actual lower bound is 1221bps, so compensate. */
+ if (brg > M_DUART_CLK_COUNTER)
+ brg = M_DUART_CLK_COUNTER;
+
+ uart_update_timeout(uport, termios->c_cflag, baud);
+
+ uport->read_status_mask = M_DUART_OVRUN_ERR;
+ if (termios->c_iflag & INPCK)
+ uport->read_status_mask |= M_DUART_FRM_ERR |
+ M_DUART_PARITY_ERR;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ uport->read_status_mask |= M_DUART_RCVD_BRK;
+
+ uport->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ uport->ignore_status_mask |= M_DUART_FRM_ERR |
+ M_DUART_PARITY_ERR;
+ if (termios->c_iflag & IGNBRK) {
+ uport->ignore_status_mask |= M_DUART_RCVD_BRK;
+ if (termios->c_iflag & IGNPAR)
+ uport->ignore_status_mask |= M_DUART_OVRUN_ERR;
+ }
+
+ if (termios->c_cflag & CREAD)
+ command = M_DUART_RX_EN;
+ else
+ command = M_DUART_RX_DIS;
+
+ if (termios->c_cflag & CRTSCTS)
+ aux |= M_DUART_CTS_CHNG_ENA;
+ else
+ aux &= ~M_DUART_CTS_CHNG_ENA;
+
+ spin_lock(&uport->lock);
+
+ if (sport->tx_stopped)
+ command |= M_DUART_TX_DIS;
+ else
+ command |= M_DUART_TX_EN;
+
+ oldmode1 = read_sbdchn(sport, R_DUART_MODE_REG_1) & mode1mask;
+ oldmode2 = read_sbdchn(sport, R_DUART_MODE_REG_2) & mode2mask;
+ oldaux = read_sbdchn(sport, R_DUART_AUXCTL_X) & auxmask;
+
+ if (!sport->tx_stopped)
+ sbd_line_drain(sport);
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
+
+ write_sbdchn(sport, R_DUART_MODE_REG_1, mode1 | oldmode1);
+ write_sbdchn(sport, R_DUART_MODE_REG_2, mode2 | oldmode2);
+ write_sbdchn(sport, R_DUART_CLK_SEL, brg);
+ write_sbdchn(sport, R_DUART_AUXCTL_X, aux | oldaux);
+
+ write_sbdchn(sport, R_DUART_CMD, command);
+
+ spin_unlock(&uport->lock);
+}
+
+
+static const char *sbd_type(struct uart_port *uport)
+{
+ return "SB1250 DUART";
+}
+
+static void sbd_release_port(struct uart_port *uport)
+{
+ struct sbd_port *sport = to_sport(uport);
+ struct sbd_duart *duart = sport->duart;
+ int map_guard;
+
+ iounmap(sport->memctrl);
+ sport->memctrl = NULL;
+ iounmap(uport->membase);
+ uport->membase = NULL;
+
+ map_guard = atomic_add_return(-1, &duart->map_guard);
+ if (!map_guard)
+ release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
+ release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
+}
+
+static int sbd_map_port(struct uart_port *uport)
+{
+ static const char *err = KERN_ERR "sbd: Cannot map MMIO\n";
+ struct sbd_port *sport = to_sport(uport);
+ struct sbd_duart *duart = sport->duart;
+
+ if (!uport->membase)
+ uport->membase = ioremap_nocache(uport->mapbase,
+ DUART_CHANREG_SPACING);
+ if (!uport->membase) {
+ printk(err);
+ return -ENOMEM;
+ }
+
+ if (!sport->memctrl)
+ sport->memctrl = ioremap_nocache(duart->mapctrl,
+ DUART_CHANREG_SPACING);
+ if (!sport->memctrl) {
+ printk(err);
+ iounmap(uport->membase);
+ uport->membase = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int sbd_request_port(struct uart_port *uport)
+{
+ static const char *err = KERN_ERR
+ "sbd: Unable to reserve MMIO resource\n";
+ struct sbd_duart *duart = to_sport(uport)->duart;
+ int map_guard;
+ int ret = 0;
+
+ if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
+ "sb1250-duart")) {
+ printk(err);
+ return -EBUSY;
+ }
+ map_guard = atomic_add_return(1, &duart->map_guard);
+ if (map_guard == 1) {
+ if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
+ "sb1250-duart")) {
+ atomic_add(-1, &duart->map_guard);
+ printk(err);
+ ret = -EBUSY;
+ }
+ }
+ if (!ret) {
+ ret = sbd_map_port(uport);
+ if (ret) {
+ map_guard = atomic_add_return(-1, &duart->map_guard);
+ if (!map_guard)
+ release_mem_region(duart->mapctrl,
+ DUART_CHANREG_SPACING);
+ }
+ }
+ if (ret) {
+ release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
+ return ret;
+ }
+ return 0;
+}
+
+static void sbd_config_port(struct uart_port *uport, int flags)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ if (flags & UART_CONFIG_TYPE) {
+ if (sbd_request_port(uport))
+ return;
+
+ uport->type = PORT_SB1250_DUART;
+
+ sbd_init_port(sport);
+ }
+}
+
+static int sbd_verify_port(struct uart_port *uport, struct serial_struct *ser)
+{
+ int ret = 0;
+
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_SB1250_DUART)
+ ret = -EINVAL;
+ if (ser->irq != uport->irq)
+ ret = -EINVAL;
+ if (ser->baud_base != uport->uartclk / 16)
+ ret = -EINVAL;
+ return ret;
+}
+
+
+static struct uart_ops sbd_ops = {
+ .tx_empty = sbd_tx_empty,
+ .set_mctrl = sbd_set_mctrl,
+ .get_mctrl = sbd_get_mctrl,
+ .stop_tx = sbd_stop_tx,
+ .start_tx = sbd_start_tx,
+ .stop_rx = sbd_stop_rx,
+ .enable_ms = sbd_enable_ms,
+ .break_ctl = sbd_break_ctl,
+ .startup = sbd_startup,
+ .shutdown = sbd_shutdown,
+ .set_termios = sbd_set_termios,
+ .type = sbd_type,
+ .release_port = sbd_release_port,
+ .request_port = sbd_request_port,
+ .config_port = sbd_config_port,
+ .verify_port = sbd_verify_port,
+};
+
+/* Initialize SB1250 DUART port structures. */
+static void __init sbd_probe_duarts(void)
+{
+ static int probed;
+ int chip, side;
+ int max_lines, line;
+
+ if (probed)
+ return;
+
+ /* Set the number of available units based on the SOC type. */
+ switch (soc_type) {
+ case K_SYS_SOC_TYPE_BCM1x55:
+ case K_SYS_SOC_TYPE_BCM1x80:
+ max_lines = 4;
+ break;
+ default:
+ /* Assume at least two serial ports at the normal address. */
+ max_lines = 2;
+ break;
+ }
+
+ probed = 1;
+
+ for (chip = 0, line = 0; chip < DUART_MAX_CHIP && line < max_lines;
+ chip++) {
+ sbd_duarts[chip].mapctrl = SBD_CTRLREGS(line);
+
+ for (side = 0; side < DUART_MAX_SIDE && line < max_lines;
+ side++, line++) {
+ struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+ struct uart_port *uport = &sport->port;
+
+ sport->duart = &sbd_duarts[chip];
+
+ uport->irq = SBD_INT(line);
+ uport->uartclk = 100000000 / 20 * 16;
+ uport->fifosize = 16;
+ uport->iotype = UPIO_MEM;
+ uport->flags = UPF_BOOT_AUTOCONF;
+ uport->ops = &sbd_ops;
+ uport->line = line;
+ uport->mapbase = SBD_CHANREGS(line);
+ }
+ }
+}
+
+
+#ifdef CONFIG_SERIAL_SB1250_DUART_CONSOLE
+/*
+ * Serial console stuff. Very basic, polling driver for doing serial
+ * console output. The console_sem is held by the caller, so we
+ * shouldn't be interrupted for more console activity.
+ */
+static void sbd_console_putchar(struct uart_port *uport, int ch)
+{
+ struct sbd_port *sport = to_sport(uport);
+
+ sbd_transmit_drain(sport);
+ write_sbdchn(sport, R_DUART_TX_HOLD, ch);
+}
+
+static void sbd_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ int chip = co->index / DUART_MAX_SIDE;
+ int side = co->index % DUART_MAX_SIDE;
+ struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+ struct uart_port *uport = &sport->port;
+ unsigned long flags;
+ unsigned int mask;
+
+ /* Disable transmit interrupts and enable the transmitter. */
+ spin_lock_irqsave(&uport->lock, flags);
+ mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+ mask & ~M_DUART_IMR_TX);
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+ spin_unlock_irqrestore(&uport->lock, flags);
+
+ uart_console_write(&sport->port, s, count, sbd_console_putchar);
+
+ /* Restore transmit interrupts and the transmitter enable. */
+ spin_lock_irqsave(&uport->lock, flags);
+ sbd_line_drain(sport);
+ if (sport->tx_stopped)
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+ spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+static int __init sbd_console_setup(struct console *co, char *options)
+{
+ int chip = co->index / DUART_MAX_SIDE;
+ int side = co->index % DUART_MAX_SIDE;
+ struct sbd_port *sport = &sbd_duarts[chip].sport[side];
+ struct uart_port *uport = &sport->port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+ int ret;
+
+ if (!sport->duart)
+ return -ENXIO;
+
+ ret = sbd_map_port(uport);
+ if (ret)
+ return ret;
+
+ sbd_init_port(sport);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ return uart_set_options(uport, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver sbd_reg;
+static struct console sbd_console = {
+ .name = "duart",
+ .write = sbd_console_write,
+ .device = uart_console_device,
+ .setup = sbd_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &sbd_reg
+};
+
+static int __init sbd_serial_console_init(void)
+{
+ sbd_probe_duarts();
+ register_console(&sbd_console);
+
+ return 0;
+}
+
+console_initcall(sbd_serial_console_init);
+
+#define SERIAL_SB1250_DUART_CONSOLE &sbd_console
+#else
+#define SERIAL_SB1250_DUART_CONSOLE NULL
+#endif /* CONFIG_SERIAL_SB1250_DUART_CONSOLE */
+
+
+static struct uart_driver sbd_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "duart",
+ .major = TTY_MAJOR,
+ .minor = SB1250_DUART_MINOR_BASE,
+ .nr = DUART_MAX_CHIP * DUART_MAX_SIDE,
+ .cons = SERIAL_SB1250_DUART_CONSOLE,
+};
+
+/* Set up the driver and register it. */
+static int __init sbd_init(void)
+{
+ int i, ret;
+
+ sbd_probe_duarts();
+
+ ret = uart_register_driver(&sbd_reg);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < DUART_MAX_CHIP * DUART_MAX_SIDE; i++) {
+ struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
+ struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
+ struct uart_port *uport = &sport->port;
+
+ if (sport->duart)
+ uart_add_one_port(&sbd_reg, uport);
+ }
+
+ return 0;
+}
+
+/* Unload the driver. Unregister stuff, get ready to go away. */
+static void __exit sbd_exit(void)
+{
+ int i;
+
+ for (i = DUART_MAX_CHIP * DUART_MAX_SIDE - 1; i >= 0; i--) {
+ struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
+ struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
+ struct uart_port *uport = &sport->port;
+
+ if (sport->duart)
+ uart_remove_one_port(&sbd_reg, uport);
+ }
+
+ uart_unregister_driver(&sbd_reg);
+}
+
+module_init(sbd_init);
+module_exit(sbd_exit);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 326020f86f75..9c57486c2e7f 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1910,6 +1910,12 @@ uart_set_options(struct uart_port *port, struct console *co,
if (flow == 'r')
termios.c_cflag |= CRTSCTS;
+ /*
+ * some uarts on other side don't support no flow control.
+ * So we set * DTR in host uart to make them happy
+ */
+ port->mctrl |= TIOCM_DTR;
+
port->ops->set_termios(port, &termios, NULL);
co->cflag = termios.c_cflag;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 1f89496d530e..672cd1042539 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -367,7 +367,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
} else {
#ifdef CONFIG_CPU_SUBTYPE_SH7343
/* Nothing */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+ defined(CONFIG_CPU_SUBTYPE_SHX3)
ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
#else
ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index fb04fb5f9843..247fb66bf0f4 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -53,7 +53,12 @@
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7091) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
# define SCSPTR1 0xffe0001c /* 8 bit SCI */
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -73,7 +78,7 @@
# define SCPDR 0xA4050136 /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
# define SCSPTR0 0xA4400000 /* 16 bit SCIF */
# define SCI_NPORTS 2
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -168,6 +173,14 @@
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+# define SCSPTR0 0xffc30020 /* 16 bit SCIF */
+# define SCSPTR1 0xffc40020 /* 16 bit SCIF */
+# define SCSPTR2 0xffc50020 /* 16 bit SCIF */
+# define SCSPTR3 0xffc60020 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001 /* Overrun error bit */
+# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
#else
# error CPU subtype not defined
#endif
@@ -177,10 +190,15 @@
#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
#define SCI_CTRL_FLAGS_TE 0x20 /* all */
#define SCI_CTRL_FLAGS_RE 0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7091) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+ defined(CONFIG_CPU_SUBTYPE_SHX3)
#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
#else
#define SCI_CTRL_FLAGS_REIE 0
@@ -514,8 +532,12 @@ static inline void set_sh771x_scif_pfc(struct uart_port *port)
}
}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7091) || \
defined(CONFIG_CPU_SUBTYPE_SH4_202)
static inline int sci_rxd_in(struct uart_port *port)
{
@@ -653,6 +675,18 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
return 1;
}
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xffc30000)
+ return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffc40000)
+ return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffc50000)
+ return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffc60000)
+ return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+}
#endif
/*
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index a27e9e92cb5e..41fc61264443 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -759,7 +759,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port)
*/
static void sn_sal_console_write(struct console *, const char *, unsigned);
-static int __init sn_sal_console_setup(struct console *, char *);
+static int sn_sal_console_setup(struct console *, char *);
static struct uart_driver sal_console_uart;
extern struct tty_driver *uart_console_device(struct console *, int *);
@@ -1006,7 +1006,7 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
* here so providing it is easier.
*
*/
-static int __init sn_sal_console_setup(struct console *co, char *options)
+static int sn_sal_console_setup(struct console *co, char *options)
{
return 0;
}
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 96557e6dba60..d82be42ff29a 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -258,17 +258,7 @@ static void sunhv_stop_tx(struct uart_port *port)
/* port->lock held by caller. */
static void sunhv_start_tx(struct uart_port *port)
{
- struct circ_buf *xmit = &port->info->xmit;
-
- while (!uart_circ_empty(xmit)) {
- long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
-
- if (status != HV_EOK)
- break;
-
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- }
+ transmit_chars(port);
}
/* port->lock is not held. */
@@ -440,8 +430,16 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
{
struct uart_port *port = sunhv_port;
unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (port->sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->lock);
+ } else
+ spin_lock(&port->lock);
- spin_lock_irqsave(&port->lock, flags);
while (n > 0) {
unsigned long ra = __pa(con_write_page);
unsigned long page_bytes;
@@ -469,7 +467,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
ra += written;
}
}
- spin_unlock_irqrestore(&port->lock, flags);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
}
static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -488,7 +489,15 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
{
struct uart_port *port = sunhv_port;
unsigned long flags;
- int i;
+ int i, locked = 1;
+
+ local_irq_save(flags);
+ if (port->sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->lock);
+ } else
+ spin_lock(&port->lock);
spin_lock_irqsave(&port->lock, flags);
for (i = 0; i < n; i++) {
@@ -496,7 +505,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
sunhv_console_putchar(port, '\r');
sunhv_console_putchar(port, *s++);
}
- spin_unlock_irqrestore(&port->lock, flags);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
}
static struct console sunhv_console = {
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index deb9ab4b5a0b..8a0f9e4408d4 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -860,22 +860,31 @@ static int num_channels;
static void sunsab_console_putchar(struct uart_port *port, int c)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
sunsab_tec_wait(up);
writeb(c, &up->regs->w.tic);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
}
static void sunsab_console_write(struct console *con, const char *s, unsigned n)
{
struct uart_sunsab_port *up = &sunsab_ports[con->index];
+ unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
uart_console_write(&up->port, s, n, sunsab_console_putchar);
sunsab_tec_wait(up);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
}
static int sunsab_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2a63cdba3208..26d720baf88c 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct console *co, const char *s,
unsigned int count)
{
struct uart_sunsu_port *up = &sunsu_ports[co->index];
+ unsigned long flags;
unsigned int ier;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
/*
* First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct console *co, const char *s,
*/
wait_for_xmitr(up);
serial_out(up, UART_IER, ier);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
}
/*
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 15b6e1cb040b..0a3e10a4a35d 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -9,7 +9,7 @@
* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
* work there.
*
- * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count)
{
struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
- spin_lock_irqsave(&up->port.lock, flags);
uart_console_write(&up->port, s, count, sunzilog_putchar);
udelay(2);
- spin_unlock_irqrestore(&up->port.lock, flags);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
}
static int __init sunzilog_console_setup(struct console *con, char *options)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5e3f748f2693..b91571122daa 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -107,6 +107,15 @@ config SPI_IMX
This enables using the Freescale iMX SPI controller in master
mode.
+config SPI_LM70_LLP
+ tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This driver supports the NS LM70 LLP Evaluation Board,
+ which interfaces to an LM70 temperature sensor using
+ a parallel port.
+
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
@@ -133,6 +142,12 @@ config SPI_OMAP_UWIRE
help
This hooks up to the MicroWire controller on OMAP1 chips.
+config SPI_OMAP24XX
+ tristate "McSPI driver for OMAP24xx"
+ depends on SPI_MASTER && ARCH_OMAP24XX
+ help
+ SPI master controller for OMAP24xx Multichannel SPI
+ (McSPI) modules.
config SPI_PXA2XX
tristate "PXA2xx SSP SPI master"
@@ -145,17 +160,36 @@ config SPI_PXA2XX
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs
config SPI_S3C24XX_GPIO
tristate "Samsung S3C24XX series SPI by GPIO"
- depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
+ depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs using
GPIO lines to provide the SPI bus. This can be used where
the inbuilt hardware cannot provide the transfer mode, or
where the board is using non hardware connected pins.
+
+config SPI_TXX9
+ tristate "Toshiba TXx9 SPI controller"
+ depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+ help
+ SPI driver for Toshiba TXx9 MIPS SoCs
+
+config SPI_XILINX
+ tristate "Xilinx SPI controller"
+ depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This exposes the SPI controller IP from the Xilinx EDK.
+
+ See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
+ Product Specification document (DS464) for hardware details.
+
#
# Add new SPI master controllers in alphabetical order above this line
#
@@ -187,6 +221,15 @@ config SPI_SPIDEV
Note that this application programming interface is EXPERIMENTAL
and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
+config SPI_TLE62X0
+ tristate "Infineon TLE62X0 (for power switching)"
+ depends on SPI_MASTER && SYSFS
+ help
+ SPI driver for Infineon TLE62X0 series line driver chips,
+ such as the TLE6220, TLE6230 and TLE6240. This provides a
+ sysfs interface, with each line presented as a kind of GPIO
+ exposing both switch control and diagnostic feedback.
+
#
# Add new SPI protocol masters in alphabetical order above this line
#
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5788d867de84..41fbac45c323 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,17 +17,22 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
+obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
+obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
+obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
+obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
# ... add above this line ...
# SPI protocol drivers (device/link on bus)
obj-$(CONFIG_SPI_AT25) += at25.o
obj-$(CONFIG_SPI_SPIDEV) += spidev.o
+obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
# ... add above this line ...
# SPI slave controller drivers (upstream link)
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 8b2601de3630..ad144054da30 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -46,6 +46,7 @@ struct atmel_spi {
struct clk *clk;
struct platform_device *pdev;
unsigned new_1:1;
+ struct spi_device *stay;
u8 stopping;
struct list_head queue;
@@ -62,29 +63,62 @@ struct atmel_spi {
/*
* Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
* they assume that spi slave device state will not change on deselect, so
- * that automagic deselection is OK. Not so! Workaround uses nCSx pins
- * as GPIOs; or newer controllers have CSAAT and friends.
+ * that automagic deselection is OK. ("NPCSx rises if no data is to be
+ * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer
+ * controllers have CSAAT and friends.
*
- * Since the CSAAT functionality is a bit weird on newer controllers
- * as well, we use GPIO to control nCSx pins on all controllers.
+ * Since the CSAAT functionality is a bit weird on newer controllers as
+ * well, we use GPIO to control nCSx pins on all controllers, updating
+ * MR.PCS to avoid confusing the controller. Using GPIOs also lets us
+ * support active-high chipselects despite the controller's belief that
+ * only active-low devices/systems exists.
+ *
+ * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
+ * right when driven with GPIO. ("Mode Fault does not allow more than one
+ * Master on Chip Select 0.") No workaround exists for that ... so for
+ * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
+ * and (c) will trigger that first erratum in some cases.
*/
-static inline void cs_activate(struct spi_device *spi)
+static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
{
unsigned gpio = (unsigned) spi->controller_data;
unsigned active = spi->mode & SPI_CS_HIGH;
+ u32 mr;
+
+ mr = spi_readl(as, MR);
+ mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
- dev_dbg(&spi->dev, "activate %u%s\n", gpio, active ? " (high)" : "");
- gpio_set_value(gpio, active);
+ dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
+ gpio, active ? " (high)" : "",
+ mr);
+
+ if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+ gpio_set_value(gpio, active);
+ spi_writel(as, MR, mr);
}
-static inline void cs_deactivate(struct spi_device *spi)
+static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
{
unsigned gpio = (unsigned) spi->controller_data;
unsigned active = spi->mode & SPI_CS_HIGH;
+ u32 mr;
- dev_dbg(&spi->dev, "DEactivate %u%s\n", gpio, active ? " (low)" : "");
- gpio_set_value(gpio, !active);
+ /* only deactivate *this* device; sometimes transfers to
+ * another device may be active when this routine is called.
+ */
+ mr = spi_readl(as, MR);
+ if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
+ mr = SPI_BFINS(PCS, 0xf, mr);
+ spi_writel(as, MR, mr);
+ }
+
+ dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
+ gpio, active ? " (low)" : "",
+ mr);
+
+ if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
+ gpio_set_value(gpio, !active);
}
/*
@@ -140,6 +174,7 @@ static void atmel_spi_next_xfer(struct spi_master *master,
/* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
* mechanism might help avoid the IRQ latency between transfers
+ * (and improve the nCS0 errata handling on at91rm9200 chips)
*
* We're also waiting for ENDRX before we start the next
* transfer because we need to handle some difficult timing
@@ -169,33 +204,62 @@ static void atmel_spi_next_message(struct spi_master *master)
{
struct atmel_spi *as = spi_master_get_devdata(master);
struct spi_message *msg;
- u32 mr;
+ struct spi_device *spi;
BUG_ON(as->current_transfer);
msg = list_entry(as->queue.next, struct spi_message, queue);
+ spi = msg->spi;
- /* Select the chip */
- mr = spi_readl(as, MR);
- mr = SPI_BFINS(PCS, ~(1 << msg->spi->chip_select), mr);
- spi_writel(as, MR, mr);
- cs_activate(msg->spi);
+ dev_dbg(master->cdev.dev, "start message %p for %s\n",
+ msg, spi->dev.bus_id);
+
+ /* select chip if it's not still active */
+ if (as->stay) {
+ if (as->stay != spi) {
+ cs_deactivate(as, as->stay);
+ cs_activate(as, spi);
+ }
+ as->stay = NULL;
+ } else
+ cs_activate(as, spi);
atmel_spi_next_xfer(master, msg);
}
-static void
+/*
+ * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
+ * - The buffer is either valid for CPU access, else NULL
+ * - If the buffer is valid, so is its DMA addresss
+ *
+ * This driver manages the dma addresss unless message->is_dma_mapped.
+ */
+static int
atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
{
+ struct device *dev = &as->pdev->dev;
+
xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
- if (xfer->tx_buf)
- xfer->tx_dma = dma_map_single(&as->pdev->dev,
+ if (xfer->tx_buf) {
+ xfer->tx_dma = dma_map_single(dev,
(void *) xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
- if (xfer->rx_buf)
- xfer->rx_dma = dma_map_single(&as->pdev->dev,
+ if (dma_mapping_error(xfer->tx_dma))
+ return -ENOMEM;
+ }
+ if (xfer->rx_buf) {
+ xfer->rx_dma = dma_map_single(dev,
xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(xfer->tx_dma)) {
+ if (xfer->tx_buf)
+ dma_unmap_single(dev,
+ xfer->tx_dma, xfer->len,
+ DMA_TO_DEVICE);
+ return -ENOMEM;
+ }
+ }
+ return 0;
}
static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
@@ -211,9 +275,13 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
static void
atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
- struct spi_message *msg, int status)
+ struct spi_message *msg, int status, int stay)
{
- cs_deactivate(msg->spi);
+ if (!stay || status < 0)
+ cs_deactivate(as, msg->spi);
+ else
+ as->stay = msg->spi;
+
list_del(&msg->queue);
msg->status = status;
@@ -303,7 +371,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
/* Clear any overrun happening while cleaning up */
spi_readl(as, SR);
- atmel_spi_msg_done(master, as, msg, -EIO);
+ atmel_spi_msg_done(master, as, msg, -EIO, 0);
} else if (pending & SPI_BIT(ENDRX)) {
ret = IRQ_HANDLED;
@@ -321,12 +389,13 @@ atmel_spi_interrupt(int irq, void *dev_id)
if (msg->transfers.prev == &xfer->transfer_list) {
/* report completed message */
- atmel_spi_msg_done(master, as, msg, 0);
+ atmel_spi_msg_done(master, as, msg, 0,
+ xfer->cs_change);
} else {
if (xfer->cs_change) {
- cs_deactivate(msg->spi);
+ cs_deactivate(as, msg->spi);
udelay(1);
- cs_activate(msg->spi);
+ cs_activate(as, msg->spi);
}
/*
@@ -350,6 +419,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
return ret;
}
+/* the spi->mode bits understood by this driver: */
#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
static int atmel_spi_setup(struct spi_device *spi)
@@ -388,6 +458,14 @@ static int atmel_spi_setup(struct spi_device *spi)
return -EINVAL;
}
+ /* see notes above re chipselect */
+ if (cpu_is_at91rm9200()
+ && spi->chip_select == 0
+ && (spi->mode & SPI_CS_HIGH)) {
+ dev_dbg(&spi->dev, "setup: can't be active-high\n");
+ return -EINVAL;
+ }
+
/* speed zero convention is used by some upper layers */
bus_hz = clk_get_rate(as->clk);
if (spi->max_speed_hz) {
@@ -397,8 +475,9 @@ static int atmel_spi_setup(struct spi_device *spi)
scbr = ((bus_hz + spi->max_speed_hz - 1)
/ spi->max_speed_hz);
if (scbr >= (1 << SPI_SCBR_SIZE)) {
- dev_dbg(&spi->dev, "setup: %d Hz too slow, scbr %u\n",
- spi->max_speed_hz, scbr);
+ dev_dbg(&spi->dev,
+ "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+ spi->max_speed_hz, scbr, bus_hz/255);
return -EINVAL;
}
} else
@@ -423,6 +502,14 @@ static int atmel_spi_setup(struct spi_device *spi)
return ret;
spi->controller_state = (void *)npcs_pin;
gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
+ } else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&as->lock, flags);
+ if (as->stay == spi)
+ as->stay = NULL;
+ cs_deactivate(as, spi);
+ spin_unlock_irqrestore(&as->lock, flags);
}
dev_dbg(&spi->dev,
@@ -464,14 +551,22 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
dev_dbg(&spi->dev, "no protocol options yet\n");
return -ENOPROTOOPT;
}
- }
- /* scrub dcache "early" */
- if (!msg->is_dma_mapped) {
- list_for_each_entry(xfer, &msg->transfers, transfer_list)
- atmel_spi_dma_map_xfer(as, xfer);
+ /*
+ * DMA map early, for performance (empties dcache ASAP) and
+ * better fault reporting. This is a DMA-only driver.
+ *
+ * NOTE that if dma_unmap_single() ever starts to do work on
+ * platforms supported by this driver, we would need to clean
+ * up mappings for previously-mapped transfers.
+ */
+ if (!msg->is_dma_mapped) {
+ if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+ return -ENOMEM;
+ }
}
+#ifdef VERBOSE
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
dev_dbg(controller,
" xfer %p: len %u tx %p/%08x rx %p/%08x\n",
@@ -479,6 +574,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
xfer->tx_buf, xfer->tx_dma,
xfer->rx_buf, xfer->rx_dma);
}
+#endif
msg->status = -EINPROGRESS;
msg->actual_length = 0;
@@ -494,8 +590,21 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
static void atmel_spi_cleanup(struct spi_device *spi)
{
- if (spi->controller_state)
- gpio_free((unsigned int)spi->controller_data);
+ struct atmel_spi *as = spi_master_get_devdata(spi->master);
+ unsigned gpio = (unsigned) spi->controller_data;
+ unsigned long flags;
+
+ if (!spi->controller_state)
+ return;
+
+ spin_lock_irqsave(&as->lock, flags);
+ if (as->stay == spi) {
+ as->stay = NULL;
+ cs_deactivate(as, spi);
+ }
+ spin_unlock_irqrestore(&as->lock, flags);
+
+ gpio_free(gpio);
}
/*-------------------------------------------------------------------------*/
@@ -536,6 +645,10 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
as = spi_master_get_devdata(master);
+ /*
+ * Scratch buffer is used for throwaway rx and tx data.
+ * It's coherent to minimize dcache pollution.
+ */
as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
&as->buffer_dma, GFP_KERNEL);
if (!as->buffer)
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index ae2b1af0dba4..c47a650183a1 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -280,6 +280,9 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
static int au1550_spi_setup(struct spi_device *spi)
{
struct au1550_spi *hw = spi_master_get_devdata(spi->master);
@@ -292,6 +295,12 @@ static int au1550_spi_setup(struct spi_device *spi)
return -EINVAL;
}
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (spi->max_speed_hz == 0)
spi->max_speed_hz = hw->freq_max;
if (spi->max_speed_hz > hw->freq_max
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 11f36bef3057..d2a4b2bdb07b 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -270,6 +270,9 @@ static void mpc52xx_psc_spi_work(struct work_struct *work)
spin_unlock_irq(&mps->lock);
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
static int mpc52xx_psc_spi_setup(struct spi_device *spi)
{
struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
@@ -279,6 +282,12 @@ static int mpc52xx_psc_spi_setup(struct spi_device *spi)
if (spi->bits_per_word%8)
return -EINVAL;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL);
if (!cs)
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
new file mode 100644
index 000000000000..6b357cdb9ea3
--- /dev/null
+++ b/drivers/spi/omap2_mcspi.c
@@ -0,0 +1,1081 @@
+/*
+ * OMAP2 McSPI controller driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and
+ * Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/spi/spi.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/clock.h>
+
+
+#define OMAP2_MCSPI_MAX_FREQ 48000000
+
+#define OMAP2_MCSPI_REVISION 0x00
+#define OMAP2_MCSPI_SYSCONFIG 0x10
+#define OMAP2_MCSPI_SYSSTATUS 0x14
+#define OMAP2_MCSPI_IRQSTATUS 0x18
+#define OMAP2_MCSPI_IRQENABLE 0x1c
+#define OMAP2_MCSPI_WAKEUPENABLE 0x20
+#define OMAP2_MCSPI_SYST 0x24
+#define OMAP2_MCSPI_MODULCTRL 0x28
+
+/* per-channel banks, 0x14 bytes each, first is: */
+#define OMAP2_MCSPI_CHCONF0 0x2c
+#define OMAP2_MCSPI_CHSTAT0 0x30
+#define OMAP2_MCSPI_CHCTRL0 0x34
+#define OMAP2_MCSPI_TX0 0x38
+#define OMAP2_MCSPI_RX0 0x3c
+
+/* per-register bitmasks: */
+
+#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0)
+#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET (1 << 1)
+
+#define OMAP2_MCSPI_SYSSTATUS_RESETDONE (1 << 0)
+
+#define OMAP2_MCSPI_MODULCTRL_SINGLE (1 << 0)
+#define OMAP2_MCSPI_MODULCTRL_MS (1 << 2)
+#define OMAP2_MCSPI_MODULCTRL_STEST (1 << 3)
+
+#define OMAP2_MCSPI_CHCONF_PHA (1 << 0)
+#define OMAP2_MCSPI_CHCONF_POL (1 << 1)
+#define OMAP2_MCSPI_CHCONF_CLKD_MASK (0x0f << 2)
+#define OMAP2_MCSPI_CHCONF_EPOL (1 << 6)
+#define OMAP2_MCSPI_CHCONF_WL_MASK (0x1f << 7)
+#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY (0x01 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY (0x02 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_MASK (0x03 << 12)
+#define OMAP2_MCSPI_CHCONF_DMAW (1 << 14)
+#define OMAP2_MCSPI_CHCONF_DMAR (1 << 15)
+#define OMAP2_MCSPI_CHCONF_DPE0 (1 << 16)
+#define OMAP2_MCSPI_CHCONF_DPE1 (1 << 17)
+#define OMAP2_MCSPI_CHCONF_IS (1 << 18)
+#define OMAP2_MCSPI_CHCONF_TURBO (1 << 19)
+#define OMAP2_MCSPI_CHCONF_FORCE (1 << 20)
+
+#define OMAP2_MCSPI_CHSTAT_RXS (1 << 0)
+#define OMAP2_MCSPI_CHSTAT_TXS (1 << 1)
+#define OMAP2_MCSPI_CHSTAT_EOT (1 << 2)
+
+#define OMAP2_MCSPI_CHCTRL_EN (1 << 0)
+
+
+/* We have 2 DMA channels per CS, one for RX and one for TX */
+struct omap2_mcspi_dma {
+ int dma_tx_channel;
+ int dma_rx_channel;
+
+ int dma_tx_sync_dev;
+ int dma_rx_sync_dev;
+
+ struct completion dma_tx_completion;
+ struct completion dma_rx_completion;
+};
+
+/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+ * cache operations; better heuristics consider wordsize and bitrate.
+ */
+#define DMA_MIN_BYTES 8
+
+
+struct omap2_mcspi {
+ struct work_struct work;
+ /* lock protects queue and registers */
+ spinlock_t lock;
+ struct list_head msg_queue;
+ struct spi_master *master;
+ struct clk *ick;
+ struct clk *fck;
+ /* Virtual base address of the controller */
+ void __iomem *base;
+ /* SPI1 has 4 channels, while SPI2 has 2 */
+ struct omap2_mcspi_dma *dma_channels;
+};
+
+struct omap2_mcspi_cs {
+ void __iomem *base;
+ int word_len;
+};
+
+static struct workqueue_struct *omap2_mcspi_wq;
+
+#define MOD_REG_BIT(val, mask, set) do { \
+ if (set) \
+ val |= mask; \
+ else \
+ val &= ~mask; \
+} while (0)
+
+static inline void mcspi_write_reg(struct spi_master *master,
+ int idx, u32 val)
+{
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ __raw_writel(val, mcspi->base + idx);
+}
+
+static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
+{
+ struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+ return __raw_readl(mcspi->base + idx);
+}
+
+static inline void mcspi_write_cs_reg(const struct spi_device *spi,
+ int idx, u32 val)
+{
+ struct omap2_mcspi_cs *cs = spi->controller_state;
+
+ __raw_writel(val, cs->base + idx);
+}
+
+static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
+{
+ struct omap2_mcspi_cs *cs = spi->controller_state;
+
+ return __raw_readl(cs->base + idx);
+}
+
+static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
+ int is_read, int enable)
+{
+ u32 l, rw;
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+
+ if (is_read) /* 1 is read, 0 write */
+ rw = OMAP2_MCSPI_CHCONF_DMAR;
+ else
+ rw = OMAP2_MCSPI_CHCONF_DMAW;
+
+ MOD_REG_BIT(l, rw, enable);
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+}
+
+static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
+{
+ u32 l;
+
+ l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+}
+
+static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
+{
+ u32 l;
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+ MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+}
+
+static void omap2_mcspi_set_master_mode(struct spi_master *master)
+{
+ u32 l;
+
+ /* setup when switching from (reset default) slave mode
+ * to single-channel master mode
+ */
+ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
+ MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+ mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
+}
+
+static unsigned
+omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
+{
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_cs *cs = spi->controller_state;
+ struct omap2_mcspi_dma *mcspi_dma;
+ unsigned int count, c;
+ unsigned long base, tx_reg, rx_reg;
+ int word_len, data_type, element_count;
+ u8 * rx;
+ const u8 * tx;
+
+ mcspi = spi_master_get_devdata(spi->master);
+ mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+ count = xfer->len;
+ c = count;
+ word_len = cs->word_len;
+
+ base = (unsigned long) io_v2p(cs->base);
+ tx_reg = base + OMAP2_MCSPI_TX0;
+ rx_reg = base + OMAP2_MCSPI_RX0;
+ rx = xfer->rx_buf;
+ tx = xfer->tx_buf;
+
+ if (word_len <= 8) {
+ data_type = OMAP_DMA_DATA_TYPE_S8;
+ element_count = count;
+ } else if (word_len <= 16) {
+ data_type = OMAP_DMA_DATA_TYPE_S16;
+ element_count = count >> 1;
+ } else /* word_len <= 32 */ {
+ data_type = OMAP_DMA_DATA_TYPE_S32;
+ element_count = count >> 2;
+ }
+
+ if (tx != NULL) {
+ omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
+ data_type, element_count, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ mcspi_dma->dma_tx_sync_dev, 0);
+
+ omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ tx_reg, 0, 0);
+
+ omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
+ OMAP_DMA_AMODE_POST_INC,
+ xfer->tx_dma, 0, 0);
+ }
+
+ if (rx != NULL) {
+ omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
+ data_type, element_count, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ mcspi_dma->dma_rx_sync_dev, 1);
+
+ omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ rx_reg, 0, 0);
+
+ omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
+ OMAP_DMA_AMODE_POST_INC,
+ xfer->rx_dma, 0, 0);
+ }
+
+ if (tx != NULL) {
+ omap_start_dma(mcspi_dma->dma_tx_channel);
+ omap2_mcspi_set_dma_req(spi, 0, 1);
+ }
+
+ if (rx != NULL) {
+ omap_start_dma(mcspi_dma->dma_rx_channel);
+ omap2_mcspi_set_dma_req(spi, 1, 1);
+ }
+
+ if (tx != NULL) {
+ wait_for_completion(&mcspi_dma->dma_tx_completion);
+ dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+ }
+
+ if (rx != NULL) {
+ wait_for_completion(&mcspi_dma->dma_rx_completion);
+ dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+ }
+ return count;
+}
+
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (!(__raw_readl(reg) & bit)) {
+ if (time_after(jiffies, timeout))
+ return -1;
+ cpu_relax();
+ }
+ return 0;
+}
+
+static unsigned
+omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
+{
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_cs *cs = spi->controller_state;
+ unsigned int count, c;
+ u32 l;
+ void __iomem *base = cs->base;
+ void __iomem *tx_reg;
+ void __iomem *rx_reg;
+ void __iomem *chstat_reg;
+ int word_len;
+
+ mcspi = spi_master_get_devdata(spi->master);
+ count = xfer->len;
+ c = count;
+ word_len = cs->word_len;
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+ l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+
+ /* We store the pre-calculated register addresses on stack to speed
+ * up the transfer loop. */
+ tx_reg = base + OMAP2_MCSPI_TX0;
+ rx_reg = base + OMAP2_MCSPI_RX0;
+ chstat_reg = base + OMAP2_MCSPI_CHSTAT0;
+
+ if (word_len <= 8) {
+ u8 *rx;
+ const u8 *tx;
+
+ rx = xfer->rx_buf;
+ tx = xfer->tx_buf;
+
+ do {
+ if (tx != NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
+#ifdef VERBOSE
+ dev_dbg(&spi->dev, "write-%d %02x\n",
+ word_len, *tx);
+#endif
+ __raw_writel(*tx++, tx_reg);
+ }
+ if (rx != NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+ dev_err(&spi->dev, "RXS timed out\n");
+ goto out;
+ }
+ /* prevent last RX_ONLY read from triggering
+ * more word i/o: switch to rx+tx
+ */
+ if (c == 0 && tx == NULL)
+ mcspi_write_cs_reg(spi,
+ OMAP2_MCSPI_CHCONF0, l);
+ *rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+ dev_dbg(&spi->dev, "read-%d %02x\n",
+ word_len, *(rx - 1));
+#endif
+ }
+ c -= 1;
+ } while (c);
+ } else if (word_len <= 16) {
+ u16 *rx;
+ const u16 *tx;
+
+ rx = xfer->rx_buf;
+ tx = xfer->tx_buf;
+ do {
+ if (tx != NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
+#ifdef VERBOSE
+ dev_dbg(&spi->dev, "write-%d %04x\n",
+ word_len, *tx);
+#endif
+ __raw_writel(*tx++, tx_reg);
+ }
+ if (rx != NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+ dev_err(&spi->dev, "RXS timed out\n");
+ goto out;
+ }
+ /* prevent last RX_ONLY read from triggering
+ * more word i/o: switch to rx+tx
+ */
+ if (c == 0 && tx == NULL)
+ mcspi_write_cs_reg(spi,
+ OMAP2_MCSPI_CHCONF0, l);
+ *rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+ dev_dbg(&spi->dev, "read-%d %04x\n",
+ word_len, *(rx - 1));
+#endif
+ }
+ c -= 2;
+ } while (c);
+ } else if (word_len <= 32) {
+ u32 *rx;
+ const u32 *tx;
+
+ rx = xfer->rx_buf;
+ tx = xfer->tx_buf;
+ do {
+ if (tx != NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
+#ifdef VERBOSE
+ dev_dbg(&spi->dev, "write-%d %04x\n",
+ word_len, *tx);
+#endif
+ __raw_writel(*tx++, tx_reg);
+ }
+ if (rx != NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+ dev_err(&spi->dev, "RXS timed out\n");
+ goto out;
+ }
+ /* prevent last RX_ONLY read from triggering
+ * more word i/o: switch to rx+tx
+ */
+ if (c == 0 && tx == NULL)
+ mcspi_write_cs_reg(spi,
+ OMAP2_MCSPI_CHCONF0, l);
+ *rx++ = __raw_readl(rx_reg);
+#ifdef VERBOSE
+ dev_dbg(&spi->dev, "read-%d %04x\n",
+ word_len, *(rx - 1));
+#endif
+ }
+ c -= 4;
+ } while (c);
+ }
+
+ /* for TX_ONLY mode, be sure all words have shifted out */
+ if (xfer->rx_buf == NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ } else if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_EOT) < 0)
+ dev_err(&spi->dev, "EOT timed out\n");
+ }
+out:
+ return count - c;
+}
+
+/* called only when no transfer is active to this device */
+static int omap2_mcspi_setup_transfer(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct omap2_mcspi_cs *cs = spi->controller_state;
+ struct omap2_mcspi *mcspi;
+ u32 l = 0, div = 0;
+ u8 word_len = spi->bits_per_word;
+
+ mcspi = spi_master_get_devdata(spi->master);
+
+ if (t != NULL && t->bits_per_word)
+ word_len = t->bits_per_word;
+
+ cs->word_len = word_len;
+
+ if (spi->max_speed_hz) {
+ while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div))
+ > spi->max_speed_hz)
+ div++;
+ } else
+ div = 15;
+
+ l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+
+ /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
+ * REVISIT: this controller could support SPI_3WIRE mode.
+ */
+ l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
+ l |= OMAP2_MCSPI_CHCONF_DPE0;
+
+ /* wordlength */
+ l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
+ l |= (word_len - 1) << 7;
+
+ /* set chipselect polarity; manage with FORCE */
+ if (!(spi->mode & SPI_CS_HIGH))
+ l |= OMAP2_MCSPI_CHCONF_EPOL; /* active-low; normal */
+ else
+ l &= ~OMAP2_MCSPI_CHCONF_EPOL;
+
+ /* set clock divisor */
+ l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
+ l |= div << 2;
+
+ /* set SPI mode 0..3 */
+ if (spi->mode & SPI_CPOL)
+ l |= OMAP2_MCSPI_CHCONF_POL;
+ else
+ l &= ~OMAP2_MCSPI_CHCONF_POL;
+ if (spi->mode & SPI_CPHA)
+ l |= OMAP2_MCSPI_CHCONF_PHA;
+ else
+ l &= ~OMAP2_MCSPI_CHCONF_PHA;
+
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+
+ dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
+ OMAP2_MCSPI_MAX_FREQ / (1 << div),
+ (spi->mode & SPI_CPHA) ? "trailing" : "leading",
+ (spi->mode & SPI_CPOL) ? "inverted" : "normal");
+
+ return 0;
+}
+
+static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
+{
+ struct spi_device *spi = data;
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_dma *mcspi_dma;
+
+ mcspi = spi_master_get_devdata(spi->master);
+ mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+ complete(&mcspi_dma->dma_rx_completion);
+
+ /* We must disable the DMA RX request */
+ omap2_mcspi_set_dma_req(spi, 1, 0);
+}
+
+static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+ struct spi_device *spi = data;
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_dma *mcspi_dma;
+
+ mcspi = spi_master_get_devdata(spi->master);
+ mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+ complete(&mcspi_dma->dma_tx_completion);
+
+ /* We must disable the DMA TX request */
+ omap2_mcspi_set_dma_req(spi, 0, 0);
+}
+
+static int omap2_mcspi_request_dma(struct spi_device *spi)
+{
+ struct spi_master *master = spi->master;
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_dma *mcspi_dma;
+
+ mcspi = spi_master_get_devdata(master);
+ mcspi_dma = mcspi->dma_channels + spi->chip_select;
+
+ if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX",
+ omap2_mcspi_dma_rx_callback, spi,
+ &mcspi_dma->dma_rx_channel)) {
+ dev_err(&spi->dev, "no RX DMA channel for McSPI\n");
+ return -EAGAIN;
+ }
+
+ if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX",
+ omap2_mcspi_dma_tx_callback, spi,
+ &mcspi_dma->dma_tx_channel)) {
+ omap_free_dma(mcspi_dma->dma_rx_channel);
+ mcspi_dma->dma_rx_channel = -1;
+ dev_err(&spi->dev, "no TX DMA channel for McSPI\n");
+ return -EAGAIN;
+ }
+
+ init_completion(&mcspi_dma->dma_rx_completion);
+ init_completion(&mcspi_dma->dma_tx_completion);
+
+ return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
+static int omap2_mcspi_setup(struct spi_device *spi)
+{
+ int ret;
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_dma *mcspi_dma;
+ struct omap2_mcspi_cs *cs = spi->controller_state;
+
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
+ if (spi->bits_per_word == 0)
+ spi->bits_per_word = 8;
+ else if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
+ dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
+ spi->bits_per_word);
+ return -EINVAL;
+ }
+
+ mcspi = spi_master_get_devdata(spi->master);
+ mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+ if (!cs) {
+ cs = kzalloc(sizeof *cs, GFP_KERNEL);
+ if (!cs)
+ return -ENOMEM;
+ cs->base = mcspi->base + spi->chip_select * 0x14;
+ spi->controller_state = cs;
+ }
+
+ if (mcspi_dma->dma_rx_channel == -1
+ || mcspi_dma->dma_tx_channel == -1) {
+ ret = omap2_mcspi_request_dma(spi);
+ if (ret < 0)
+ return ret;
+ }
+
+ clk_enable(mcspi->ick);
+ clk_enable(mcspi->fck);
+ ret = omap2_mcspi_setup_transfer(spi, NULL);
+ clk_disable(mcspi->fck);
+ clk_disable(mcspi->ick);
+
+ return ret;
+}
+
+static void omap2_mcspi_cleanup(struct spi_device *spi)
+{
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_dma *mcspi_dma;
+
+ mcspi = spi_master_get_devdata(spi->master);
+ mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+ kfree(spi->controller_state);
+
+ if (mcspi_dma->dma_rx_channel != -1) {
+ omap_free_dma(mcspi_dma->dma_rx_channel);
+ mcspi_dma->dma_rx_channel = -1;
+ }
+ if (mcspi_dma->dma_tx_channel != -1) {
+ omap_free_dma(mcspi_dma->dma_tx_channel);
+ mcspi_dma->dma_tx_channel = -1;
+ }
+}
+
+static void omap2_mcspi_work(struct work_struct *work)
+{
+ struct omap2_mcspi *mcspi;
+
+ mcspi = container_of(work, struct omap2_mcspi, work);
+ spin_lock_irq(&mcspi->lock);
+
+ clk_enable(mcspi->ick);
+ clk_enable(mcspi->fck);
+
+ /* We only enable one channel at a time -- the one whose message is
+ * at the head of the queue -- although this controller would gladly
+ * arbitrate among multiple channels. This corresponds to "single
+ * channel" master mode. As a side effect, we need to manage the
+ * chipselect with the FORCE bit ... CS != channel enable.
+ */
+ while (!list_empty(&mcspi->msg_queue)) {
+ struct spi_message *m;
+ struct spi_device *spi;
+ struct spi_transfer *t = NULL;
+ int cs_active = 0;
+ struct omap2_mcspi_device_config *conf;
+ struct omap2_mcspi_cs *cs;
+ int par_override = 0;
+ int status = 0;
+ u32 chconf;
+
+ m = container_of(mcspi->msg_queue.next, struct spi_message,
+ queue);
+
+ list_del_init(&m->queue);
+ spin_unlock_irq(&mcspi->lock);
+
+ spi = m->spi;
+ conf = spi->controller_data;
+ cs = spi->controller_state;
+
+ omap2_mcspi_set_enable(spi, 1);
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+ status = -EINVAL;
+ break;
+ }
+ if (par_override || t->speed_hz || t->bits_per_word) {
+ par_override = 1;
+ status = omap2_mcspi_setup_transfer(spi, t);
+ if (status < 0)
+ break;
+ if (!t->speed_hz && !t->bits_per_word)
+ par_override = 0;
+ }
+
+ if (!cs_active) {
+ omap2_mcspi_force_cs(spi, 1);
+ cs_active = 1;
+ }
+
+ chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+ chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+ if (t->tx_buf == NULL)
+ chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
+ else if (t->rx_buf == NULL)
+ chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
+ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf);
+
+ if (t->len) {
+ unsigned count;
+
+ /* RX_ONLY mode needs dummy data in TX reg */
+ if (t->tx_buf == NULL)
+ __raw_writel(0, cs->base
+ + OMAP2_MCSPI_TX0);
+
+ if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
+ count = omap2_mcspi_txrx_dma(spi, t);
+ else
+ count = omap2_mcspi_txrx_pio(spi, t);
+ m->actual_length += count;
+
+ if (count != t->len) {
+ status = -EIO;
+ break;
+ }
+ }
+
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
+
+ /* ignore the "leave it on after last xfer" hint */
+ if (t->cs_change) {
+ omap2_mcspi_force_cs(spi, 0);
+ cs_active = 0;
+ }
+ }
+
+ /* Restore defaults if they were overriden */
+ if (par_override) {
+ par_override = 0;
+ status = omap2_mcspi_setup_transfer(spi, NULL);
+ }
+
+ if (cs_active)
+ omap2_mcspi_force_cs(spi, 0);
+
+ omap2_mcspi_set_enable(spi, 0);
+
+ m->status = status;
+ m->complete(m->context);
+
+ spin_lock_irq(&mcspi->lock);
+ }
+
+ clk_disable(mcspi->fck);
+ clk_disable(mcspi->ick);
+
+ spin_unlock_irq(&mcspi->lock);
+}
+
+static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+ struct omap2_mcspi *mcspi;
+ unsigned long flags;
+ struct spi_transfer *t;
+
+ m->actual_length = 0;
+ m->status = 0;
+
+ /* reject invalid messages and transfers */
+ if (list_empty(&m->transfers) || !m->complete)
+ return -EINVAL;
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ const void *tx_buf = t->tx_buf;
+ void *rx_buf = t->rx_buf;
+ unsigned len = t->len;
+
+ if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
+ || (len && !(rx_buf || tx_buf))
+ || (t->bits_per_word &&
+ ( t->bits_per_word < 4
+ || t->bits_per_word > 32))) {
+ dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
+ t->speed_hz,
+ len,
+ tx_buf ? "tx" : "",
+ rx_buf ? "rx" : "",
+ t->bits_per_word);
+ return -EINVAL;
+ }
+ if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) {
+ dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
+ t->speed_hz,
+ OMAP2_MCSPI_MAX_FREQ/(1<<16));
+ return -EINVAL;
+ }
+
+ if (m->is_dma_mapped || len < DMA_MIN_BYTES)
+ continue;
+
+ /* Do DMA mapping "early" for better error reporting and
+ * dcache use. Note that if dma_unmap_single() ever starts
+ * to do real work on ARM, we'd need to clean up mappings
+ * for previous transfers on *ALL* exits of this loop...
+ */
+ if (tx_buf != NULL) {
+ t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
+ len, DMA_TO_DEVICE);
+ if (dma_mapping_error(t->tx_dma)) {
+ dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+ 'T', len);
+ return -EINVAL;
+ }
+ }
+ if (rx_buf != NULL) {
+ t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(t->rx_dma)) {
+ dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+ 'R', len);
+ if (tx_buf != NULL)
+ dma_unmap_single(NULL, t->tx_dma,
+ len, DMA_TO_DEVICE);
+ return -EINVAL;
+ }
+ }
+ }
+
+ mcspi = spi_master_get_devdata(spi->master);
+
+ spin_lock_irqsave(&mcspi->lock, flags);
+ list_add_tail(&m->queue, &mcspi->msg_queue);
+ queue_work(omap2_mcspi_wq, &mcspi->work);
+ spin_unlock_irqrestore(&mcspi->lock, flags);
+
+ return 0;
+}
+
+static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
+{
+ struct spi_master *master = mcspi->master;
+ u32 tmp;
+
+ clk_enable(mcspi->ick);
+ clk_enable(mcspi->fck);
+
+ mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
+ OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
+ do {
+ tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
+ } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
+
+ mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
+ /* (3 << 8) | (2 << 3) | */
+ OMAP2_MCSPI_SYSCONFIG_AUTOIDLE);
+
+ omap2_mcspi_set_master_mode(master);
+
+ clk_disable(mcspi->fck);
+ clk_disable(mcspi->ick);
+ return 0;
+}
+
+static u8 __initdata spi1_rxdma_id [] = {
+ OMAP24XX_DMA_SPI1_RX0,
+ OMAP24XX_DMA_SPI1_RX1,
+ OMAP24XX_DMA_SPI1_RX2,
+ OMAP24XX_DMA_SPI1_RX3,
+};
+
+static u8 __initdata spi1_txdma_id [] = {
+ OMAP24XX_DMA_SPI1_TX0,
+ OMAP24XX_DMA_SPI1_TX1,
+ OMAP24XX_DMA_SPI1_TX2,
+ OMAP24XX_DMA_SPI1_TX3,
+};
+
+static u8 __initdata spi2_rxdma_id[] = {
+ OMAP24XX_DMA_SPI2_RX0,
+ OMAP24XX_DMA_SPI2_RX1,
+};
+
+static u8 __initdata spi2_txdma_id[] = {
+ OMAP24XX_DMA_SPI2_TX0,
+ OMAP24XX_DMA_SPI2_TX1,
+};
+
+static int __init omap2_mcspi_probe(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct omap2_mcspi *mcspi;
+ struct resource *r;
+ int status = 0, i;
+ const u8 *rxdma_id, *txdma_id;
+ unsigned num_chipselect;
+
+ switch (pdev->id) {
+ case 1:
+ rxdma_id = spi1_rxdma_id;
+ txdma_id = spi1_txdma_id;
+ num_chipselect = 4;
+ break;
+ case 2:
+ rxdma_id = spi2_rxdma_id;
+ txdma_id = spi2_txdma_id;
+ num_chipselect = 2;
+ break;
+ /* REVISIT omap2430 has a third McSPI ... */
+ default:
+ return -EINVAL;
+ }
+
+ master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
+ if (master == NULL) {
+ dev_dbg(&pdev->dev, "master allocation failed\n");
+ return -ENOMEM;
+ }
+
+ if (pdev->id != -1)
+ master->bus_num = pdev->id;
+
+ master->setup = omap2_mcspi_setup;
+ master->transfer = omap2_mcspi_transfer;
+ master->cleanup = omap2_mcspi_cleanup;
+ master->num_chipselect = num_chipselect;
+
+ dev_set_drvdata(&pdev->dev, master);
+
+ mcspi = spi_master_get_devdata(master);
+ mcspi->master = master;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (r == NULL) {
+ status = -ENODEV;
+ goto err1;
+ }
+ if (!request_mem_region(r->start, (r->end - r->start) + 1,
+ pdev->dev.bus_id)) {
+ status = -EBUSY;
+ goto err1;
+ }
+
+ mcspi->base = (void __iomem *) io_p2v(r->start);
+
+ INIT_WORK(&mcspi->work, omap2_mcspi_work);
+
+ spin_lock_init(&mcspi->lock);
+ INIT_LIST_HEAD(&mcspi->msg_queue);
+
+ mcspi->ick = clk_get(&pdev->dev, "mcspi_ick");
+ if (IS_ERR(mcspi->ick)) {
+ dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
+ status = PTR_ERR(mcspi->ick);
+ goto err1a;
+ }
+ mcspi->fck = clk_get(&pdev->dev, "mcspi_fck");
+ if (IS_ERR(mcspi->fck)) {
+ dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
+ status = PTR_ERR(mcspi->fck);
+ goto err2;
+ }
+
+ mcspi->dma_channels = kcalloc(master->num_chipselect,
+ sizeof(struct omap2_mcspi_dma),
+ GFP_KERNEL);
+
+ if (mcspi->dma_channels == NULL)
+ goto err3;
+
+ for (i = 0; i < num_chipselect; i++) {
+ mcspi->dma_channels[i].dma_rx_channel = -1;
+ mcspi->dma_channels[i].dma_rx_sync_dev = rxdma_id[i];
+ mcspi->dma_channels[i].dma_tx_channel = -1;
+ mcspi->dma_channels[i].dma_tx_sync_dev = txdma_id[i];
+ }
+
+ if (omap2_mcspi_reset(mcspi) < 0)
+ goto err4;
+
+ status = spi_register_master(master);
+ if (status < 0)
+ goto err4;
+
+ return status;
+
+err4:
+ kfree(mcspi->dma_channels);
+err3:
+ clk_put(mcspi->fck);
+err2:
+ clk_put(mcspi->ick);
+err1a:
+ release_mem_region(r->start, (r->end - r->start) + 1);
+err1:
+ spi_master_put(master);
+ return status;
+}
+
+static int __exit omap2_mcspi_remove(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct omap2_mcspi *mcspi;
+ struct omap2_mcspi_dma *dma_channels;
+ struct resource *r;
+
+ master = dev_get_drvdata(&pdev->dev);
+ mcspi = spi_master_get_devdata(master);
+ dma_channels = mcspi->dma_channels;
+
+ clk_put(mcspi->fck);
+ clk_put(mcspi->ick);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(r->start, (r->end - r->start) + 1);
+
+ spi_unregister_master(master);
+ kfree(dma_channels);
+
+ return 0;
+}
+
+static struct platform_driver omap2_mcspi_driver = {
+ .driver = {
+ .name = "omap2_mcspi",
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(omap2_mcspi_remove),
+};
+
+
+static int __init omap2_mcspi_init(void)
+{
+ omap2_mcspi_wq = create_singlethread_workqueue(
+ omap2_mcspi_driver.driver.name);
+ if (omap2_mcspi_wq == NULL)
+ return -1;
+ return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
+}
+subsys_initcall(omap2_mcspi_init);
+
+static void __exit omap2_mcspi_exit(void)
+{
+ platform_driver_unregister(&omap2_mcspi_driver);
+
+ destroy_workqueue(omap2_mcspi_wq);
+}
+module_exit(omap2_mcspi_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 95183e1df525..d275c615a73e 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -445,10 +445,19 @@ done:
return status;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
static int uwire_setup(struct spi_device *spi)
{
struct uwire_state *ust = spi->controller_state;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (ust == NULL) {
ust = kzalloc(sizeof(*ust), GFP_KERNEL);
if (ust == NULL)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 9f2c887ffa04..e51311b2da0b 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1067,6 +1067,9 @@ static int transfer(struct spi_device *spi, struct spi_message *msg)
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
static int setup(struct spi_device *spi)
{
struct pxa2xx_spi_chip *chip_info = NULL;
@@ -1093,6 +1096,12 @@ static int setup(struct spi_device *spi)
return -EINVAL;
}
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
if (!chip) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 4831edbae2d5..018884d7a5fa 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -23,6 +23,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/cache.h>
+#include <linux/mutex.h>
#include <linux/spi/spi.h>
@@ -185,7 +186,7 @@ struct boardinfo {
};
static LIST_HEAD(board_list);
-static DECLARE_MUTEX(board_lock);
+static DEFINE_MUTEX(board_lock);
/**
@@ -292,9 +293,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
bi->n_board_info = n;
memcpy(bi->board_info, info, n * sizeof *info);
- down(&board_lock);
+ mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);
- up(&board_lock);
+ mutex_unlock(&board_lock);
return 0;
}
@@ -308,7 +309,7 @@ scan_boardinfo(struct spi_master *master)
struct boardinfo *bi;
struct device *dev = master->cdev.dev;
- down(&board_lock);
+ mutex_lock(&board_lock);
list_for_each_entry(bi, &board_list, list) {
struct spi_board_info *chip = bi->board_info;
unsigned n;
@@ -330,7 +331,7 @@ scan_boardinfo(struct spi_master *master)
(void) spi_new_device(master, chip);
}
}
- up(&board_lock);
+ mutex_unlock(&board_lock);
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 88425e1af4d3..0c85c984ccb4 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -187,12 +187,10 @@ int spi_bitbang_setup(struct spi_device *spi)
bitbang = spi_master_get_devdata(spi->master);
- /* REVISIT: some systems will want to support devices using lsb-first
- * bit encodings on the wire. In pure software that would be trivial,
- * just bitbang_txrx_le_cphaX() routines shifting the other way, and
- * some hardware controllers also have this support.
+ /* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on;
+ * add those to master->flags, and provide the other support.
*/
- if ((spi->mode & SPI_LSB_FIRST) != 0)
+ if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0)
return -EINVAL;
if (!cs) {
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 656be4a5094a..aee9ad6f633c 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -1163,6 +1163,9 @@ msg_rejected:
return -EINVAL;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
/* On first setup bad values must free chip_data memory since will cause
spi_new_device to fail. Bad value setup from protocol driver are simply not
applied and notified to the calling driver. */
@@ -1174,6 +1177,12 @@ static int setup(struct spi_device *spi)
u32 tmp;
int status = 0;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
/* Get controller data */
chip_info = spi->controller_data;
@@ -1245,21 +1254,6 @@ static int setup(struct spi_device *spi)
/* SPI mode */
tmp = spi->mode;
- if (tmp & SPI_LSB_FIRST) {
- status = -EINVAL;
- if (first_setup) {
- dev_err(&spi->dev,
- "setup - "
- "HW doesn't support LSB first transfer\n");
- goto err_first_setup;
- } else {
- dev_err(&spi->dev,
- "setup - "
- "HW doesn't support LSB first transfer, "
- "default to MSB first\n");
- spi->mode &= ~SPI_LSB_FIRST;
- }
- }
if (tmp & SPI_CS_HIGH) {
u32_EDIT(chip->control,
SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH);
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
new file mode 100644
index 000000000000..4ea68ac16115
--- /dev/null
+++ b/drivers/spi/spi_lm70llp.c
@@ -0,0 +1,361 @@
+/*
+ * spi_lm70llp.c - driver for lm70llp eval board for the LM70 sensor
+ *
+ * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/parport.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*
+ * The LM70 communicates with a host processor using a 3-wire variant of
+ * the SPI/Microwire bus interface. This driver specifically supports an
+ * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
+ * port to bitbang an SPI-parport bridge. Accordingly, this is an SPI
+ * master controller driver. The hwmon/lm70 driver is a "SPI protocol
+ * driver", layered on top of this one and usable without the lm70llp.
+ *
+ * The LM70 is a temperature sensor chip from National Semiconductor; its
+ * datasheet is available at http://www.national.com/pf/LM/LM70.html
+ *
+ * Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is
+ * (heavily) based on spi-butterfly by David Brownell.
+ *
+ * The LM70 LLP connects to the PC parallel port in the following manner:
+ *
+ * Parallel LM70 LLP
+ * Port Direction JP2 Header
+ * ----------- --------- ------------
+ * D0 2 - -
+ * D1 3 --> V+ 5
+ * D2 4 --> V+ 5
+ * D3 5 --> V+ 5
+ * D4 6 --> V+ 5
+ * D5 7 --> nCS 8
+ * D6 8 --> SCLK 3
+ * D7 9 --> SI/O 5
+ * GND 25 - GND 7
+ * Select 13 <-- SI/O 1
+ *
+ * Note that parport pin 13 actually gets inverted by the transistor
+ * arrangement which lets either the parport or the LM70 drive the
+ * SI/SO signal.
+ */
+
+#define DRVNAME "spi-lm70llp"
+
+#define lm70_INIT 0xBE
+#define SIO 0x10
+#define nCS 0x20
+#define SCLK 0x40
+
+/*-------------------------------------------------------------------------*/
+
+struct spi_lm70llp {
+ struct spi_bitbang bitbang;
+ struct parport *port;
+ struct pardevice *pd;
+ struct spi_device *spidev_lm70;
+ struct spi_board_info info;
+ struct class_device *cdev;
+};
+
+/* REVISIT : ugly global ; provides "exclusive open" facility */
+static struct spi_lm70llp *lm70llp;
+
+
+/*-------------------------------------------------------------------*/
+
+static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
+{
+ return spi->controller_data;
+}
+
+/*---------------------- LM70 LLP eval board-specific inlines follow */
+
+/* NOTE: we don't actually need to reread the output values, since they'll
+ * still be what we wrote before. Plus, going through parport builds in
+ * a ~1ms/operation delay; these SPI transfers could easily be faster.
+ */
+
+static inline void deassertCS(struct spi_lm70llp *pp)
+{
+ u8 data = parport_read_data(pp->port);
+ parport_write_data(pp->port, data | nCS);
+}
+
+static inline void assertCS(struct spi_lm70llp *pp)
+{
+ u8 data = parport_read_data(pp->port);
+ parport_write_data(pp->port, data & ~nCS);
+}
+
+static inline void clkHigh(struct spi_lm70llp *pp)
+{
+ u8 data = parport_read_data(pp->port);
+ parport_write_data(pp->port, data | SCLK);
+}
+
+static inline void clkLow(struct spi_lm70llp *pp)
+{
+ u8 data = parport_read_data(pp->port);
+ parport_write_data(pp->port, data & ~SCLK);
+}
+
+/*------------------------- SPI-LM70-specific inlines ----------------------*/
+
+static inline void spidelay(unsigned d)
+{
+ udelay(d);
+}
+
+static inline void setsck(struct spi_device *s, int is_on)
+{
+ struct spi_lm70llp *pp = spidev_to_pp(s);
+
+ if (is_on)
+ clkHigh(pp);
+ else
+ clkLow(pp);
+}
+
+static inline void setmosi(struct spi_device *s, int is_on)
+{
+ /* FIXME update D7 ... this way we can put the chip
+ * into shutdown mode and read the manufacturer ID,
+ * but we can't put it back into operational mode.
+ */
+}
+
+/*
+ * getmiso:
+ * Why do we return 0 when the SIO line is high and vice-versa?
+ * The fact is, the lm70 eval board from NS (which this driver drives),
+ * is wired in just such a way : when the lm70's SIO goes high, a transistor
+ * switches it to low reflecting this on the parport (pin 13), and vice-versa.
+ */
+static inline int getmiso(struct spi_device *s)
+{
+ struct spi_lm70llp *pp = spidev_to_pp(s);
+ return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 );
+}
+/*--------------------------------------------------------------------*/
+
+#define EXPAND_BITBANG_TXRX 1
+#include <linux/spi/spi_bitbang.h>
+
+static void lm70_chipselect(struct spi_device *spi, int value)
+{
+ struct spi_lm70llp *pp = spidev_to_pp(spi);
+
+ if (value)
+ assertCS(pp);
+ else
+ deassertCS(pp);
+}
+
+/*
+ * Our actual bitbanger routine.
+ */
+static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
+{
+ static u32 sio=0;
+ static int first_time=1;
+
+ /* First time: perform SPI bitbang and return the LSB of
+ * the result of the SPI call.
+ */
+ if (first_time) {
+ sio = bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+ first_time=0;
+ return (sio & 0x00ff);
+ }
+ /* Return the MSB of the result of the SPI call */
+ else {
+ first_time=1;
+ return (sio >> 8);
+ }
+}
+
+static void spi_lm70llp_attach(struct parport *p)
+{
+ struct pardevice *pd;
+ struct spi_lm70llp *pp;
+ struct spi_master *master;
+ int status;
+
+ if (lm70llp) {
+ printk(KERN_WARNING
+ "%s: spi_lm70llp instance already loaded. Aborting.\n",
+ DRVNAME);
+ return;
+ }
+
+ /* TODO: this just _assumes_ a lm70 is there ... no probe;
+ * the lm70 driver could verify it, reading the manf ID.
+ */
+
+ master = spi_alloc_master(p->physport->dev, sizeof *pp);
+ if (!master) {
+ status = -ENOMEM;
+ goto out_fail;
+ }
+ pp = spi_master_get_devdata(master);
+
+ master->bus_num = -1; /* dynamic alloc of a bus number */
+ master->num_chipselect = 1;
+
+ /*
+ * SPI and bitbang hookup.
+ */
+ pp->bitbang.master = spi_master_get(master);
+ pp->bitbang.chipselect = lm70_chipselect;
+ pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
+ pp->bitbang.flags = SPI_3WIRE;
+
+ /*
+ * Parport hookup
+ */
+ pp->port = p;
+ pd = parport_register_device(p, DRVNAME,
+ NULL, NULL, NULL,
+ PARPORT_FLAG_EXCL, pp);
+ if (!pd) {
+ status = -ENOMEM;
+ goto out_free_master;
+ }
+ pp->pd = pd;
+
+ status = parport_claim(pd);
+ if (status < 0)
+ goto out_parport_unreg;
+
+ /*
+ * Start SPI ...
+ */
+ status = spi_bitbang_start(&pp->bitbang);
+ if (status < 0) {
+ printk(KERN_WARNING
+ "%s: spi_bitbang_start failed with status %d\n",
+ DRVNAME, status);
+ goto out_off_and_release;
+ }
+
+ /*
+ * The modalias name MUST match the device_driver name
+ * for the bus glue code to match and subsequently bind them.
+ * We are binding to the generic drivers/hwmon/lm70.c device
+ * driver.
+ */
+ strcpy(pp->info.modalias, "lm70");
+ pp->info.max_speed_hz = 6 * 1000 * 1000;
+ pp->info.chip_select = 0;
+ pp->info.mode = SPI_3WIRE | SPI_MODE_0;
+
+ /* power up the chip, and let the LM70 control SI/SO */
+ parport_write_data(pp->port, lm70_INIT);
+
+ /* Enable access to our primary data structure via
+ * the board info's (void *)controller_data.
+ */
+ pp->info.controller_data = pp;
+ pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
+ if (pp->spidev_lm70)
+ dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
+ pp->spidev_lm70->dev.bus_id);
+ else {
+ printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
+ status = -ENODEV;
+ goto out_bitbang_stop;
+ }
+ pp->spidev_lm70->bits_per_word = 16;
+
+ lm70llp = pp;
+
+ return;
+
+out_bitbang_stop:
+ spi_bitbang_stop(&pp->bitbang);
+out_off_and_release:
+ /* power down */
+ parport_write_data(pp->port, 0);
+ mdelay(10);
+ parport_release(pp->pd);
+out_parport_unreg:
+ parport_unregister_device(pd);
+out_free_master:
+ (void) spi_master_put(master);
+out_fail:
+ pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status);
+}
+
+static void spi_lm70llp_detach(struct parport *p)
+{
+ struct spi_lm70llp *pp;
+
+ if (!lm70llp || lm70llp->port != p)
+ return;
+
+ pp = lm70llp;
+ spi_bitbang_stop(&pp->bitbang);
+
+ /* power down */
+ parport_write_data(pp->port, 0);
+ msleep(10);
+
+ parport_release(pp->pd);
+ parport_unregister_device(pp->pd);
+
+ (void) spi_master_put(pp->bitbang.master);
+
+ lm70llp = NULL;
+}
+
+
+static struct parport_driver spi_lm70llp_drv = {
+ .name = DRVNAME,
+ .attach = spi_lm70llp_attach,
+ .detach = spi_lm70llp_detach,
+};
+
+static int __init init_spi_lm70llp(void)
+{
+ return parport_register_driver(&spi_lm70llp_drv);
+}
+module_init(init_spi_lm70llp);
+
+static void __exit cleanup_spi_lm70llp(void)
+{
+ parport_unregister_driver(&spi_lm70llp_drv);
+}
+module_exit(cleanup_spi_lm70llp);
+
+MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
+MODULE_DESCRIPTION(
+ "Parport adapter for the National Semiconductor LM70 LLP eval board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index e9798bf7b8c6..3295cfcc9f20 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -47,6 +47,7 @@ struct mpc83xx_spi_reg {
#define SPMODE_ENABLE (1 << 24)
#define SPMODE_LEN(x) ((x) << 20)
#define SPMODE_PM(x) ((x) << 16)
+#define SPMODE_OP (1 << 14)
/*
* Default for SPI Mode:
@@ -85,6 +86,11 @@ struct mpc83xx_spi {
unsigned nsecs; /* (clock cycle time)/2 */
u32 sysclk;
+ u32 rx_shift; /* RX data reg shift when in qe mode */
+ u32 tx_shift; /* TX data reg shift when in qe mode */
+
+ bool qe_mode;
+
void (*activate_cs) (u8 cs, u8 polarity);
void (*deactivate_cs) (u8 cs, u8 polarity);
};
@@ -103,7 +109,7 @@ static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg)
void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \
{ \
type * rx = mpc83xx_spi->rx; \
- *rx++ = (type)data; \
+ *rx++ = (type)(data >> mpc83xx_spi->rx_shift); \
mpc83xx_spi->rx = rx; \
}
@@ -114,7 +120,7 @@ u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \
const type * tx = mpc83xx_spi->tx; \
if (!tx) \
return 0; \
- data = *tx++; \
+ data = *tx++ << mpc83xx_spi->tx_shift; \
mpc83xx_spi->tx = tx; \
return data; \
}
@@ -158,6 +164,12 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value)
if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) {
u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64);
+ if (pm > 0x0f) {
+ printk(KERN_WARNING "MPC83xx SPI: SPICLK can't be less then a SYSCLK/1024!\n"
+ "Requested SPICLK is %d Hz. Will use %d Hz instead.\n",
+ spi->max_speed_hz, mpc83xx_spi->sysclk / 1024);
+ pm = 0x0f;
+ }
regval |= SPMODE_PM(pm) | SPMODE_DIV16;
} else {
u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4);
@@ -197,12 +209,22 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|| ((bits_per_word > 16) && (bits_per_word != 32)))
return -EINVAL;
+ mpc83xx_spi->rx_shift = 0;
+ mpc83xx_spi->tx_shift = 0;
if (bits_per_word <= 8) {
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+ if (mpc83xx_spi->qe_mode) {
+ mpc83xx_spi->rx_shift = 16;
+ mpc83xx_spi->tx_shift = 24;
+ }
} else if (bits_per_word <= 16) {
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16;
+ if (mpc83xx_spi->qe_mode) {
+ mpc83xx_spi->rx_shift = 16;
+ mpc83xx_spi->tx_shift = 16;
+ }
} else if (bits_per_word <= 32) {
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32;
@@ -232,12 +254,21 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
static int mpc83xx_spi_setup(struct spi_device *spi)
{
struct spi_bitbang *bitbang;
struct mpc83xx_spi *mpc83xx_spi;
int retval;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (!spi->max_speed_hz)
return -EINVAL;
@@ -371,7 +402,6 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev)
ret = -ENODEV;
goto free_master;
}
-
mpc83xx_spi = spi_master_get_devdata(master);
mpc83xx_spi->bitbang.master = spi_master_get(master);
mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect;
@@ -380,9 +410,17 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev)
mpc83xx_spi->sysclk = pdata->sysclk;
mpc83xx_spi->activate_cs = pdata->activate_cs;
mpc83xx_spi->deactivate_cs = pdata->deactivate_cs;
+ mpc83xx_spi->qe_mode = pdata->qe_mode;
mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+ mpc83xx_spi->rx_shift = 0;
+ mpc83xx_spi->tx_shift = 0;
+ if (mpc83xx_spi->qe_mode) {
+ mpc83xx_spi->rx_shift = 16;
+ mpc83xx_spi->tx_shift = 24;
+ }
+
mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
init_completion(&mpc83xx_spi->done);
@@ -417,6 +455,9 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev)
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+ if (pdata->qe_mode)
+ regval |= SPMODE_OP;
+
mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
ret = spi_bitbang_start(&mpc83xx_spi->bitbang);
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index d5a710f6e445..7071ff8da63e 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -146,6 +146,9 @@ static int s3c24xx_spi_setupxfer(struct spi_device *spi,
return 0;
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
static int s3c24xx_spi_setup(struct spi_device *spi)
{
int ret;
@@ -153,8 +156,11 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
if (!spi->bits_per_word)
spi->bits_per_word = 8;
- if ((spi->mode & SPI_LSB_FIRST) != 0)
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
return -EINVAL;
+ }
ret = s3c24xx_spi_setupxfer(spi, NULL);
if (ret < 0) {
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
new file mode 100644
index 000000000000..08e981c40646
--- /dev/null
+++ b/drivers/spi/spi_txx9.c
@@ -0,0 +1,474 @@
+/*
+ * spi_txx9.c - TXx9 SPI controller driver.
+ *
+ * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ *
+ * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <asm/gpio.h>
+
+
+#define SPI_FIFO_SIZE 4
+
+#define TXx9_SPMCR 0x00
+#define TXx9_SPCR0 0x04
+#define TXx9_SPCR1 0x08
+#define TXx9_SPFS 0x0c
+#define TXx9_SPSR 0x14
+#define TXx9_SPDR 0x18
+
+/* SPMCR : SPI Master Control */
+#define TXx9_SPMCR_OPMODE 0xc0
+#define TXx9_SPMCR_CONFIG 0x40
+#define TXx9_SPMCR_ACTIVE 0x80
+#define TXx9_SPMCR_SPSTP 0x02
+#define TXx9_SPMCR_BCLR 0x01
+
+/* SPCR0 : SPI Control 0 */
+#define TXx9_SPCR0_TXIFL_MASK 0xc000
+#define TXx9_SPCR0_RXIFL_MASK 0x3000
+#define TXx9_SPCR0_SIDIE 0x0800
+#define TXx9_SPCR0_SOEIE 0x0400
+#define TXx9_SPCR0_RBSIE 0x0200
+#define TXx9_SPCR0_TBSIE 0x0100
+#define TXx9_SPCR0_IFSPSE 0x0010
+#define TXx9_SPCR0_SBOS 0x0004
+#define TXx9_SPCR0_SPHA 0x0002
+#define TXx9_SPCR0_SPOL 0x0001
+
+/* SPSR : SPI Status */
+#define TXx9_SPSR_TBSI 0x8000
+#define TXx9_SPSR_RBSI 0x4000
+#define TXx9_SPSR_TBS_MASK 0x3800
+#define TXx9_SPSR_RBS_MASK 0x0700
+#define TXx9_SPSR_SPOE 0x0080
+#define TXx9_SPSR_IFSD 0x0008
+#define TXx9_SPSR_SIDLE 0x0004
+#define TXx9_SPSR_STRDY 0x0002
+#define TXx9_SPSR_SRRDY 0x0001
+
+
+struct txx9spi {
+ struct workqueue_struct *workqueue;
+ struct work_struct work;
+ spinlock_t lock; /* protect 'queue' */
+ struct list_head queue;
+ wait_queue_head_t waitq;
+ void __iomem *membase;
+ int irq;
+ int baseclk;
+ struct clk *clk;
+ u32 max_speed_hz, min_speed_hz;
+ int last_chipselect;
+ int last_chipselect_val;
+};
+
+static u32 txx9spi_rd(struct txx9spi *c, int reg)
+{
+ return __raw_readl(c->membase + reg);
+}
+static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
+{
+ __raw_writel(val, c->membase + reg);
+}
+
+static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
+ int on, unsigned int cs_delay)
+{
+ int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
+ if (on) {
+ /* deselect the chip with cs_change hint in last transfer */
+ if (c->last_chipselect >= 0)
+ gpio_set_value(c->last_chipselect,
+ !c->last_chipselect_val);
+ c->last_chipselect = spi->chip_select;
+ c->last_chipselect_val = val;
+ } else {
+ c->last_chipselect = -1;
+ ndelay(cs_delay); /* CS Hold Time */
+ }
+ gpio_set_value(spi->chip_select, val);
+ ndelay(cs_delay); /* CS Setup Time / CS Recovery Time */
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CS_HIGH|SPI_CPOL|SPI_CPHA)
+
+static int txx9spi_setup(struct spi_device *spi)
+{
+ struct txx9spi *c = spi_master_get_devdata(spi->master);
+ u8 bits_per_word;
+
+ if (spi->mode & ~MODEBITS)
+ return -EINVAL;
+
+ if (!spi->max_speed_hz
+ || spi->max_speed_hz > c->max_speed_hz
+ || spi->max_speed_hz < c->min_speed_hz)
+ return -EINVAL;
+
+ bits_per_word = spi->bits_per_word ? : 8;
+ if (bits_per_word != 8 && bits_per_word != 16)
+ return -EINVAL;
+
+ if (gpio_direction_output(spi->chip_select,
+ !(spi->mode & SPI_CS_HIGH))) {
+ dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
+ return -EINVAL;
+ }
+
+ /* deselect chip */
+ spin_lock(&c->lock);
+ txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
+ spin_unlock(&c->lock);
+
+ return 0;
+}
+
+static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
+{
+ struct txx9spi *c = dev_id;
+
+ /* disable rx intr */
+ txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
+ TXx9_SPCR0);
+ wake_up(&c->waitq);
+ return IRQ_HANDLED;
+}
+
+static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
+{
+ struct spi_device *spi = m->spi;
+ struct spi_transfer *t;
+ unsigned int cs_delay;
+ unsigned int cs_change = 1;
+ int status = 0;
+ u32 mcr;
+ u32 prev_speed_hz = 0;
+ u8 prev_bits_per_word = 0;
+
+ /* CS setup/hold/recovery time in nsec */
+ cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
+
+ mcr = txx9spi_rd(c, TXx9_SPMCR);
+ if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
+ dev_err(&spi->dev, "Bad mode.\n");
+ status = -EIO;
+ goto exit;
+ }
+ mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+
+ /* enter config mode */
+ txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+ txx9spi_wr(c, TXx9_SPCR0_SBOS
+ | ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
+ | ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
+ | 0x08,
+ TXx9_SPCR0);
+
+ list_for_each_entry (t, &m->transfers, transfer_list) {
+ const void *txbuf = t->tx_buf;
+ void *rxbuf = t->rx_buf;
+ u32 data;
+ unsigned int len = t->len;
+ unsigned int wsize;
+ u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+ u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+ bits_per_word = bits_per_word ? : 8;
+ wsize = bits_per_word >> 3; /* in bytes */
+
+ if (prev_speed_hz != speed_hz
+ || prev_bits_per_word != bits_per_word) {
+ u32 n = (c->baseclk + speed_hz - 1) / speed_hz;
+ if (n < 1)
+ n = 1;
+ else if (n > 0xff)
+ n = 0xff;
+ /* enter config mode */
+ txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
+ TXx9_SPMCR);
+ txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
+ /* enter active mode */
+ txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
+
+ prev_speed_hz = speed_hz;
+ prev_bits_per_word = bits_per_word;
+ }
+
+ if (cs_change)
+ txx9spi_cs_func(spi, c, 1, cs_delay);
+ cs_change = t->cs_change;
+ while (len) {
+ unsigned int count = SPI_FIFO_SIZE;
+ int i;
+ u32 cr0;
+
+ if (len < count * wsize)
+ count = len / wsize;
+ /* now tx must be idle... */
+ while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
+ cpu_relax();
+ cr0 = txx9spi_rd(c, TXx9_SPCR0);
+ cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
+ cr0 |= (count - 1) << 12;
+ /* enable rx intr */
+ cr0 |= TXx9_SPCR0_RBSIE;
+ txx9spi_wr(c, cr0, TXx9_SPCR0);
+ /* send */
+ for (i = 0; i < count; i++) {
+ if (txbuf) {
+ data = (wsize == 1)
+ ? *(const u8 *)txbuf
+ : *(const u16 *)txbuf;
+ txx9spi_wr(c, data, TXx9_SPDR);
+ txbuf += wsize;
+ } else
+ txx9spi_wr(c, 0, TXx9_SPDR);
+ }
+ /* wait all rx data */
+ wait_event(c->waitq,
+ txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
+ /* receive */
+ for (i = 0; i < count; i++) {
+ data = txx9spi_rd(c, TXx9_SPDR);
+ if (rxbuf) {
+ if (wsize == 1)
+ *(u8 *)rxbuf = data;
+ else
+ *(u16 *)rxbuf = data;
+ rxbuf += wsize;
+ }
+ }
+ len -= count * wsize;
+ }
+ m->actual_length += t->len;
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
+
+ if (!cs_change)
+ continue;
+ if (t->transfer_list.next == &m->transfers)
+ break;
+ /* sometimes a short mid-message deselect of the chip
+ * may be needed to terminate a mode or command
+ */
+ txx9spi_cs_func(spi, c, 0, cs_delay);
+ }
+
+exit:
+ m->status = status;
+ m->complete(m->context);
+
+ /* normally deactivate chipselect ... unless no error and
+ * cs_change has hinted that the next message will probably
+ * be for this chip too.
+ */
+ if (!(status == 0 && cs_change))
+ txx9spi_cs_func(spi, c, 0, cs_delay);
+
+ /* enter config mode */
+ txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+}
+
+static void txx9spi_work(struct work_struct *work)
+{
+ struct txx9spi *c = container_of(work, struct txx9spi, work);
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->lock, flags);
+ while (!list_empty(&c->queue)) {
+ struct spi_message *m;
+
+ m = container_of(c->queue.next, struct spi_message, queue);
+ list_del_init(&m->queue);
+ spin_unlock_irqrestore(&c->lock, flags);
+
+ txx9spi_work_one(c, m);
+
+ spin_lock_irqsave(&c->lock, flags);
+ }
+ spin_unlock_irqrestore(&c->lock, flags);
+}
+
+static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+ struct spi_master *master = spi->master;
+ struct txx9spi *c = spi_master_get_devdata(master);
+ struct spi_transfer *t;
+ unsigned long flags;
+
+ m->actual_length = 0;
+
+ /* check each transfer's parameters */
+ list_for_each_entry (t, &m->transfers, transfer_list) {
+ u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+ u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+ bits_per_word = bits_per_word ? : 8;
+ if (!t->tx_buf && !t->rx_buf && t->len)
+ return -EINVAL;
+ if (bits_per_word != 8 && bits_per_word != 16)
+ return -EINVAL;
+ if (t->len & ((bits_per_word >> 3) - 1))
+ return -EINVAL;
+ if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&c->lock, flags);
+ list_add_tail(&m->queue, &c->queue);
+ queue_work(c->workqueue, &c->work);
+ spin_unlock_irqrestore(&c->lock, flags);
+
+ return 0;
+}
+
+static int __init txx9spi_probe(struct platform_device *dev)
+{
+ struct spi_master *master;
+ struct txx9spi *c;
+ struct resource *res;
+ int ret = -ENODEV;
+ u32 mcr;
+
+ master = spi_alloc_master(&dev->dev, sizeof(*c));
+ if (!master)
+ return ret;
+ c = spi_master_get_devdata(master);
+ c->irq = -1;
+ platform_set_drvdata(dev, master);
+
+ INIT_WORK(&c->work, txx9spi_work);
+ spin_lock_init(&c->lock);
+ INIT_LIST_HEAD(&c->queue);
+ init_waitqueue_head(&c->waitq);
+
+ c->clk = clk_get(&dev->dev, "spi-baseclk");
+ if (IS_ERR(c->clk)) {
+ ret = PTR_ERR(c->clk);
+ c->clk = NULL;
+ goto exit;
+ }
+ ret = clk_enable(c->clk);
+ if (ret) {
+ clk_put(c->clk);
+ c->clk = NULL;
+ goto exit;
+ }
+ c->baseclk = clk_get_rate(c->clk);
+ c->min_speed_hz = (c->baseclk + 0xff - 1) / 0xff;
+ c->max_speed_hz = c->baseclk;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto exit;
+ c->membase = ioremap(res->start, res->end - res->start + 1);
+ if (!c->membase)
+ goto exit;
+
+ /* enter config mode */
+ mcr = txx9spi_rd(c, TXx9_SPMCR);
+ mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+ txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+
+ c->irq = platform_get_irq(dev, 0);
+ if (c->irq < 0)
+ goto exit;
+ ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
+ if (ret) {
+ c->irq = -1;
+ goto exit;
+ }
+
+ c->workqueue = create_singlethread_workqueue(master->cdev.dev->bus_id);
+ if (!c->workqueue)
+ goto exit;
+ c->last_chipselect = -1;
+
+ dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
+ (unsigned long long)res->start, c->irq,
+ (c->baseclk + 500000) / 1000000);
+
+ master->bus_num = dev->id;
+ master->setup = txx9spi_setup;
+ master->transfer = txx9spi_transfer;
+ master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
+
+ ret = spi_register_master(master);
+ if (ret)
+ goto exit;
+ return 0;
+exit:
+ if (c->workqueue)
+ destroy_workqueue(c->workqueue);
+ if (c->irq >= 0)
+ free_irq(c->irq, c);
+ if (c->membase)
+ iounmap(c->membase);
+ if (c->clk) {
+ clk_disable(c->clk);
+ clk_put(c->clk);
+ }
+ platform_set_drvdata(dev, NULL);
+ spi_master_put(master);
+ return ret;
+}
+
+static int __exit txx9spi_remove(struct platform_device *dev)
+{
+ struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+ struct txx9spi *c = spi_master_get_devdata(master);
+
+ spi_unregister_master(master);
+ platform_set_drvdata(dev, NULL);
+ destroy_workqueue(c->workqueue);
+ free_irq(c->irq, c);
+ iounmap(c->membase);
+ clk_disable(c->clk);
+ clk_put(c->clk);
+ spi_master_put(master);
+ return 0;
+}
+
+static struct platform_driver txx9spi_driver = {
+ .remove = __exit_p(txx9spi_remove),
+ .driver = {
+ .name = "txx9spi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init txx9spi_init(void)
+{
+ return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
+}
+subsys_initcall(txx9spi_init);
+
+static void __exit txx9spi_exit(void)
+{
+ platform_driver_unregister(&txx9spi_driver);
+}
+module_exit(txx9spi_exit);
+
+MODULE_DESCRIPTION("TXx9 SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d04242aee40d..38b60ad0eda0 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -181,7 +181,8 @@ static int spidev_message(struct spidev_data *spidev,
}
if (u_tmp->tx_buf) {
k_tmp->tx_buf = buf;
- if (copy_from_user(buf, (const u8 __user *)u_tmp->tx_buf,
+ if (copy_from_user(buf, (const u8 __user *)
+ (ptrdiff_t) u_tmp->tx_buf,
u_tmp->len))
goto done;
}
@@ -213,7 +214,8 @@ static int spidev_message(struct spidev_data *spidev,
buf = spidev->buffer;
for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
if (u_tmp->rx_buf) {
- if (__copy_to_user((u8 __user *)u_tmp->rx_buf, buf,
+ if (__copy_to_user((u8 __user *)
+ (ptrdiff_t) u_tmp->rx_buf, buf,
u_tmp->len)) {
status = -EFAULT;
goto done;
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
new file mode 100644
index 000000000000..6da58ca48b33
--- /dev/null
+++ b/drivers/spi/tle62x0.c
@@ -0,0 +1,328 @@
+/*
+ * tle62x0.c -- support Infineon TLE62x0 driver chips
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/tle62x0.h>
+
+
+#define CMD_READ 0x00
+#define CMD_SET 0xff
+
+#define DIAG_NORMAL 0x03
+#define DIAG_OVERLOAD 0x02
+#define DIAG_OPEN 0x01
+#define DIAG_SHORTGND 0x00
+
+struct tle62x0_state {
+ struct spi_device *us;
+ struct mutex lock;
+ unsigned int nr_gpio;
+ unsigned int gpio_state;
+
+ unsigned char tx_buff[4];
+ unsigned char rx_buff[4];
+};
+
+static int to_gpio_num(struct device_attribute *attr);
+
+static inline int tle62x0_write(struct tle62x0_state *st)
+{
+ unsigned char *buff = st->tx_buff;
+ unsigned int gpio_state = st->gpio_state;
+
+ buff[0] = CMD_SET;
+
+ if (st->nr_gpio == 16) {
+ buff[1] = gpio_state >> 8;
+ buff[2] = gpio_state;
+ } else {
+ buff[1] = gpio_state;
+ }
+
+ dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
+ buff[0], buff[1], buff[2]);
+
+ return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
+}
+
+static inline int tle62x0_read(struct tle62x0_state *st)
+{
+ unsigned char *txbuff = st->tx_buff;
+ struct spi_transfer xfer = {
+ .tx_buf = txbuff,
+ .rx_buf = st->rx_buff,
+ .len = (st->nr_gpio * 2) / 8,
+ };
+ struct spi_message msg;
+
+ txbuff[0] = CMD_READ;
+ txbuff[1] = 0x00;
+ txbuff[2] = 0x00;
+ txbuff[3] = 0x00;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(st->us, &msg);
+}
+
+static unsigned char *decode_fault(unsigned int fault_code)
+{
+ fault_code &= 3;
+
+ switch (fault_code) {
+ case DIAG_NORMAL:
+ return "N";
+ case DIAG_OVERLOAD:
+ return "V";
+ case DIAG_OPEN:
+ return "O";
+ case DIAG_SHORTGND:
+ return "G";
+ }
+
+ return "?";
+}
+
+static ssize_t tle62x0_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tle62x0_state *st = dev_get_drvdata(dev);
+ char *bp = buf;
+ unsigned char *buff = st->rx_buff;
+ unsigned long fault = 0;
+ int ptr;
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = tle62x0_read(st);
+
+ dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+
+ for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
+ fault <<= 8;
+ fault |= ((unsigned long)buff[ptr]);
+
+ dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
+ }
+
+ for (ptr = 0; ptr < st->nr_gpio; ptr++) {
+ bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
+ }
+
+ *bp++ = '\n';
+
+ mutex_unlock(&st->lock);
+ return bp - buf;
+}
+
+static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
+
+static ssize_t tle62x0_gpio_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tle62x0_state *st = dev_get_drvdata(dev);
+ int gpio_num = to_gpio_num(attr);
+ int value;
+
+ mutex_lock(&st->lock);
+ value = (st->gpio_state >> gpio_num) & 1;
+ mutex_unlock(&st->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d", value);
+}
+
+static ssize_t tle62x0_gpio_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct tle62x0_state *st = dev_get_drvdata(dev);
+ int gpio_num = to_gpio_num(attr);
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (buf == endp)
+ return -EINVAL;
+
+ dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
+
+ mutex_lock(&st->lock);
+
+ if (val)
+ st->gpio_state |= 1 << gpio_num;
+ else
+ st->gpio_state &= ~(1 << gpio_num);
+
+ tle62x0_write(st);
+ mutex_unlock(&st->lock);
+
+ return len;
+}
+
+static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
+ tle62x0_gpio_show, tle62x0_gpio_store);
+
+static struct device_attribute *gpio_attrs[] = {
+ [0] = &dev_attr_gpio1,
+ [1] = &dev_attr_gpio2,
+ [2] = &dev_attr_gpio3,
+ [3] = &dev_attr_gpio4,
+ [4] = &dev_attr_gpio5,
+ [5] = &dev_attr_gpio6,
+ [6] = &dev_attr_gpio7,
+ [7] = &dev_attr_gpio8,
+ [8] = &dev_attr_gpio9,
+ [9] = &dev_attr_gpio10,
+ [10] = &dev_attr_gpio11,
+ [11] = &dev_attr_gpio12,
+ [12] = &dev_attr_gpio13,
+ [13] = &dev_attr_gpio14,
+ [14] = &dev_attr_gpio15,
+ [15] = &dev_attr_gpio16
+};
+
+static int to_gpio_num(struct device_attribute *attr)
+{
+ int ptr;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
+ if (gpio_attrs[ptr] == attr)
+ return ptr;
+ }
+
+ return -1;
+}
+
+static int __devinit tle62x0_probe(struct spi_device *spi)
+{
+ struct tle62x0_state *st;
+ struct tle62x0_pdata *pdata;
+ int ptr;
+ int ret;
+
+ pdata = spi->dev.platform_data;
+ if (pdata == NULL) {
+ dev_err(&spi->dev, "no device data specified\n");
+ return -EINVAL;
+ }
+
+ st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
+ if (st == NULL) {
+ dev_err(&spi->dev, "no memory for device state\n");
+ return -ENOMEM;
+ }
+
+ st->us = spi;
+ st->nr_gpio = pdata->gpio_count;
+ st->gpio_state = pdata->init_state;
+
+ mutex_init(&st->lock);
+
+ ret = device_create_file(&spi->dev, &dev_attr_status_show);
+ if (ret) {
+ dev_err(&spi->dev, "cannot create status attribute\n");
+ goto err_status;
+ }
+
+ for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
+ ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
+ if (ret) {
+ dev_err(&spi->dev, "cannot create gpio attribute\n");
+ goto err_gpios;
+ }
+ }
+
+ /* tle62x0_write(st); */
+ spi_set_drvdata(spi, st);
+ return 0;
+
+ err_gpios:
+ for (; ptr > 0; ptr--)
+ device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+ device_remove_file(&spi->dev, &dev_attr_status_show);
+
+ err_status:
+ kfree(st);
+ return ret;
+}
+
+static int __devexit tle62x0_remove(struct spi_device *spi)
+{
+ struct tle62x0_state *st = spi_get_drvdata(spi);
+ int ptr;
+
+ for (ptr = 0; ptr < st->nr_gpio; ptr++)
+ device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+ kfree(st);
+ return 0;
+}
+
+static struct spi_driver tle62x0_driver = {
+ .driver = {
+ .name = "tle62x0",
+ .owner = THIS_MODULE,
+ },
+ .probe = tle62x0_probe,
+ .remove = __devexit_p(tle62x0_remove),
+};
+
+static __init int tle62x0_init(void)
+{
+ return spi_register_driver(&tle62x0_driver);
+}
+
+static __exit void tle62x0_exit(void)
+{
+ spi_unregister_driver(&tle62x0_driver);
+}
+
+module_init(tle62x0_init);
+module_exit(tle62x0_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("TLE62x0 SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
new file mode 100644
index 000000000000..f0bf9a68e96b
--- /dev/null
+++ b/drivers/spi/xilinx_spi.c
@@ -0,0 +1,434 @@
+/*
+ * xilinx_spi.c
+ *
+ * Xilinx SPI controller driver (master mode only)
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/io.h>
+
+#include <syslib/virtex_devices.h>
+
+#define XILINX_SPI_NAME "xspi"
+
+/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
+ * Product Specification", DS464
+ */
+#define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */
+
+#define XSPI_CR_ENABLE 0x02
+#define XSPI_CR_MASTER_MODE 0x04
+#define XSPI_CR_CPOL 0x08
+#define XSPI_CR_CPHA 0x10
+#define XSPI_CR_MODE_MASK (XSPI_CR_CPHA | XSPI_CR_CPOL)
+#define XSPI_CR_TXFIFO_RESET 0x20
+#define XSPI_CR_RXFIFO_RESET 0x40
+#define XSPI_CR_MANUAL_SSELECT 0x80
+#define XSPI_CR_TRANS_INHIBIT 0x100
+
+#define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */
+
+#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
+#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
+#define XSPI_SR_TX_EMPTY_MASK 0x04 /* Transmit FIFO is empty */
+#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
+#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
+
+#define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */
+#define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */
+
+#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
+
+/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
+ * IPIF registers are 32 bit
+ */
+#define XIPIF_V123B_DGIER_OFFSET 0x1c /* IPIF global int enable reg */
+#define XIPIF_V123B_GINTR_ENABLE 0x80000000
+
+#define XIPIF_V123B_IISR_OFFSET 0x20 /* IPIF interrupt status reg */
+#define XIPIF_V123B_IIER_OFFSET 0x28 /* IPIF interrupt enable reg */
+
+#define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */
+#define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while
+ * disabled */
+#define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */
+#define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */
+#define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */
+#define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */
+
+#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */
+#define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
+
+struct xilinx_spi {
+ /* bitbang has to be first */
+ struct spi_bitbang bitbang;
+ struct completion done;
+
+ void __iomem *regs; /* virt. address of the control registers */
+
+ u32 irq;
+
+ u32 speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
+
+ u8 *rx_ptr; /* pointer in the Tx buffer */
+ const u8 *tx_ptr; /* pointer in the Rx buffer */
+ int remaining_bytes; /* the number of bytes left to transfer */
+};
+
+static void xspi_init_hw(void __iomem *regs_base)
+{
+ /* Reset the SPI device */
+ out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET,
+ XIPIF_V123B_RESET_MASK);
+ /* Disable all the interrupts just in case */
+ out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0);
+ /* Enable the global IPIF interrupt */
+ out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET,
+ XIPIF_V123B_GINTR_ENABLE);
+ /* Deselect the slave on the SPI bus */
+ out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff);
+ /* Disable the transmitter, enable Manual Slave Select Assertion,
+ * put SPI controller into master mode, and enable it */
+ out_be16(regs_base + XSPI_CR_OFFSET,
+ XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT
+ | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE);
+}
+
+static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
+{
+ struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+ if (is_on == BITBANG_CS_INACTIVE) {
+ /* Deselect the slave on the SPI bus */
+ out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff);
+ } else if (is_on == BITBANG_CS_ACTIVE) {
+ /* Set the SPI clock phase and polarity */
+ u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET)
+ & ~XSPI_CR_MODE_MASK;
+ if (spi->mode & SPI_CPHA)
+ cr |= XSPI_CR_CPHA;
+ if (spi->mode & SPI_CPOL)
+ cr |= XSPI_CR_CPOL;
+ out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+
+ /* We do not check spi->max_speed_hz here as the SPI clock
+ * frequency is not software programmable (the IP block design
+ * parameter)
+ */
+
+ /* Activate the chip select */
+ out_be32(xspi->regs + XSPI_SSR_OFFSET,
+ ~(0x0001 << spi->chip_select));
+ }
+}
+
+/* spi_bitbang requires custom setup_transfer() to be defined if there is a
+ * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
+ * supports just 8 bits per word, and SPI clock can't be changed in software.
+ * Check for 8 bits per word. Chip select delay calculations could be
+ * added here as soon as bitbang_work() can be made aware of the delay value.
+ */
+static int xilinx_spi_setup_transfer(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ u8 bits_per_word;
+ u32 hz;
+ struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
+ hz = (t) ? t->speed_hz : spi->max_speed_hz;
+ if (bits_per_word != 8) {
+ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+ __FUNCTION__, bits_per_word);
+ return -EINVAL;
+ }
+
+ if (hz && xspi->speed_hz > hz) {
+ dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
+ __FUNCTION__, hz);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA)
+
+static int xilinx_spi_setup(struct spi_device *spi)
+{
+ struct spi_bitbang *bitbang;
+ struct xilinx_spi *xspi;
+ int retval;
+
+ xspi = spi_master_get_devdata(spi->master);
+ bitbang = &xspi->bitbang;
+
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+ if (spi->mode & ~MODEBITS) {
+ dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
+ __FUNCTION__, spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
+ retval = xilinx_spi_setup_transfer(spi, NULL);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
+ __FUNCTION__, spi->mode & MODEBITS, spi->bits_per_word, 0);
+
+ return 0;
+}
+
+static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
+{
+ u8 sr;
+
+ /* Fill the Tx FIFO with as many bytes as possible */
+ sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
+ if (xspi->tx_ptr) {
+ out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++);
+ } else {
+ out_8(xspi->regs + XSPI_TXD_OFFSET, 0);
+ }
+ xspi->remaining_bytes--;
+ sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ }
+}
+
+static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+ u32 ipif_ier;
+ u16 cr;
+
+ /* We get here with transmitter inhibited */
+
+ xspi->tx_ptr = t->tx_buf;
+ xspi->rx_ptr = t->rx_buf;
+ xspi->remaining_bytes = t->len;
+ INIT_COMPLETION(xspi->done);
+
+ xilinx_spi_fill_tx_fifo(xspi);
+
+ /* Enable the transmit empty interrupt, which we use to determine
+ * progress on the transmission.
+ */
+ ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET);
+ out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET,
+ ipif_ier | XSPI_INTR_TX_EMPTY);
+
+ /* Start the transfer by not inhibiting the transmitter any longer */
+ cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT;
+ out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+
+ wait_for_completion(&xspi->done);
+
+ /* Disable the transmit empty interrupt */
+ out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier);
+
+ return t->len - xspi->remaining_bytes;
+}
+
+
+/* This driver supports single master mode only. Hence Tx FIFO Empty
+ * is the only interrupt we care about.
+ * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
+ * Fault are not to happen.
+ */
+static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+{
+ struct xilinx_spi *xspi = dev_id;
+ u32 ipif_isr;
+
+ /* Get the IPIF interrupts, and clear them immediately */
+ ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+ out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr);
+
+ if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */
+ u16 cr;
+ u8 sr;
+
+ /* A transmit has just completed. Process received data and
+ * check for more data to transmit. Always inhibit the
+ * transmitter while the Isr refills the transmit register/FIFO,
+ * or make sure it is stopped if we're done.
+ */
+ cr = in_be16(xspi->regs + XSPI_CR_OFFSET);
+ out_be16(xspi->regs + XSPI_CR_OFFSET,
+ cr | XSPI_CR_TRANS_INHIBIT);
+
+ /* Read out all the data from the Rx FIFO */
+ sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
+ u8 data;
+
+ data = in_8(xspi->regs + XSPI_RXD_OFFSET);
+ if (xspi->rx_ptr) {
+ *xspi->rx_ptr++ = data;
+ }
+ sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ }
+
+ /* See if there is more data to send */
+ if (xspi->remaining_bytes > 0) {
+ xilinx_spi_fill_tx_fifo(xspi);
+ /* Start the transfer by not inhibiting the
+ * transmitter any longer
+ */
+ out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+ } else {
+ /* No more data to send.
+ * Indicate the transfer is completed.
+ */
+ complete(&xspi->done);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __init xilinx_spi_probe(struct platform_device *dev)
+{
+ int ret = 0;
+ struct spi_master *master;
+ struct xilinx_spi *xspi;
+ struct xspi_platform_data *pdata;
+ struct resource *r;
+
+ /* Get resources(memory, IRQ) associated with the device */
+ master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
+
+ if (master == NULL) {
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(dev, master);
+ pdata = dev->dev.platform_data;
+
+ if (pdata == NULL) {
+ ret = -ENODEV;
+ goto put_master;
+ }
+
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (r == NULL) {
+ ret = -ENODEV;
+ goto put_master;
+ }
+
+ xspi = spi_master_get_devdata(master);
+ xspi->bitbang.master = spi_master_get(master);
+ xspi->bitbang.chipselect = xilinx_spi_chipselect;
+ xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
+ xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
+ xspi->bitbang.master->setup = xilinx_spi_setup;
+ init_completion(&xspi->done);
+
+ if (!request_mem_region(r->start,
+ r->end - r->start + 1, XILINX_SPI_NAME)) {
+ ret = -ENXIO;
+ goto put_master;
+ }
+
+ xspi->regs = ioremap(r->start, r->end - r->start + 1);
+ if (xspi->regs == NULL) {
+ ret = -ENOMEM;
+ goto put_master;
+ }
+
+ xspi->irq = platform_get_irq(dev, 0);
+ if (xspi->irq < 0) {
+ ret = -ENXIO;
+ goto unmap_io;
+ }
+
+ master->bus_num = pdata->bus_num;
+ master->num_chipselect = pdata->num_chipselect;
+ xspi->speed_hz = pdata->speed_hz;
+
+ /* SPI controller initializations */
+ xspi_init_hw(xspi->regs);
+
+ /* Register for SPI Interrupt */
+ ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+ if (ret != 0)
+ goto unmap_io;
+
+ ret = spi_bitbang_start(&xspi->bitbang);
+ if (ret != 0) {
+ dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
+ goto free_irq;
+ }
+
+ dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+ r->start, (u32)xspi->regs, xspi->irq);
+
+ return ret;
+
+free_irq:
+ free_irq(xspi->irq, xspi);
+unmap_io:
+ iounmap(xspi->regs);
+put_master:
+ spi_master_put(master);
+ return ret;
+}
+
+static int __devexit xilinx_spi_remove(struct platform_device *dev)
+{
+ struct xilinx_spi *xspi;
+ struct spi_master *master;
+
+ master = platform_get_drvdata(dev);
+ xspi = spi_master_get_devdata(master);
+
+ spi_bitbang_stop(&xspi->bitbang);
+ free_irq(xspi->irq, xspi);
+ iounmap(xspi->regs);
+ platform_set_drvdata(dev, 0);
+ spi_master_put(xspi->bitbang.master);
+
+ return 0;
+}
+
+static struct platform_driver xilinx_spi_driver = {
+ .probe = xilinx_spi_probe,
+ .remove = __devexit_p(xilinx_spi_remove),
+ .driver = {
+ .name = XILINX_SPI_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init xilinx_spi_init(void)
+{
+ return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_init);
+
+static void __exit xilinx_spi_exit(void)
+{
+ platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_exit);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("Xilinx SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
index dd1d6a53f3c0..5f98f673f1b6 100644
--- a/drivers/telephony/Kconfig
+++ b/drivers/telephony/Kconfig
@@ -2,11 +2,9 @@
# Telephony device configuration
#
-menu "Telephony Support"
+menuconfig PHONE
+ tristate "Telephony support"
depends on HAS_IOMEM
-
-config PHONE
- tristate "Linux telephony support"
---help---
Say Y here if you have a telephony card, which for example allows
you to use a regular phone for voice-over-IP applications.
@@ -17,9 +15,11 @@ config PHONE
To compile this driver as a module, choose M here: the
module will be called phonedev.
+if PHONE
+
config PHONE_IXJ
tristate "QuickNet Internet LineJack/PhoneJack support"
- depends on PHONE
+ depends ISA || PCI
---help---
Say M if you have a telephony card manufactured by Quicknet
Technologies, Inc. These include the Internet PhoneJACK and
@@ -44,5 +44,4 @@ config PHONE_IXJ_PCMCIA
cards manufactured by Quicknet Technologies, Inc. This changes the
card initialization code to work with the card manager daemon.
-endmenu
-
+endif # PHONE
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index c7b0a357b04a..49cd9793404f 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -3453,7 +3453,6 @@ static void ixj_write_frame(IXJ *j)
{
int cnt, frame_count, dly;
IXJ_WORD dat;
- BYTES blankword;
frame_count = 0;
if(j->flags.cidplay) {
@@ -3501,6 +3500,8 @@ static void ixj_write_frame(IXJ *j)
}
if (frame_count >= 1) {
if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) {
+ BYTES blankword;
+
switch (j->play_mode) {
case PLAYBACK_MODE_ULAW:
case PLAYBACK_MODE_ALAW:
@@ -3508,6 +3509,7 @@ static void ixj_write_frame(IXJ *j)
break;
case PLAYBACK_MODE_8LINEAR:
case PLAYBACK_MODE_16LINEAR:
+ default:
blankword.low = blankword.high = 0x00;
break;
case PLAYBACK_MODE_8LINEAR_WSS:
@@ -3531,6 +3533,8 @@ static void ixj_write_frame(IXJ *j)
j->flags.play_first_frame = 0;
} else if (j->play_codec == G723_63 && j->flags.play_first_frame) {
for (cnt = 0; cnt < 24; cnt++) {
+ BYTES blankword;
+
if(cnt == 12) {
blankword.low = 0x02;
blankword.high = 0x00;
@@ -4868,6 +4872,7 @@ static char daa_CR_read(IXJ *j, int cr)
bytes.high = 0xB0 + cr;
break;
case SOP_PU_PULSEDIALING:
+ default:
bytes.high = 0xF0 + cr;
break;
}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 071b9675a781..7dd73546bf43 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -16,7 +16,7 @@ config USB_ARCH_HAS_HCD
boolean
default y if USB_ARCH_HAS_OHCI
default y if USB_ARCH_HAS_EHCI
- default y if PCMCIA # sl811_cs
+ default y if PCMCIA && !M32R # sl811_cs
default y if ARM # SL-811
default PCI
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 4973e147bc79..8f046659b4e9 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -1168,6 +1168,7 @@ static int uea_kthread(void *data)
struct uea_softc *sc = data;
int ret = -EAGAIN;
+ set_freezable();
uea_enters(INS_TO_USBDEV(sc));
while (!kthread_should_stop()) {
if (ret < 0 || sc->reset)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 50e79010401c..fd74c50b1804 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2728,6 +2728,7 @@ loop:
static int hub_thread(void *__unused)
{
+ set_freezable();
do {
hub_events();
wait_event_interruptible(khubd_wait,
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 8712ef987179..be7a1bd2823b 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3434,6 +3434,9 @@ static int fsg_main_thread(void *fsg_)
allow_signal(SIGKILL);
allow_signal(SIGUSR1);
+ /* Allow the thread to be frozen */
+ set_freezable();
+
/* Arrange for userspace references to be interpreted as kernel
* pointers. That way we can pass a kernel pointer to a routine
* that expects a __user pointer and it will work okay. */
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 1fd5fc220cd7..42d4e6454a77 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -630,7 +630,7 @@ static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int time
} else
status = urb->status;
- if (actual_length)
+ if (status >= 0)
*actual_length = urb->actual_length;
return status;
@@ -664,7 +664,7 @@ static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsi
int ret;
struct usb_ctrlrequest *dr;
struct urb *urb;
- int length;
+ int uninitialized_var(length);
dbg ("auerchain_control_msg");
dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index bef8bcd9bd98..28842d208bb0 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -311,8 +311,6 @@ static int usb_stor_control_thread(void * __us)
struct Scsi_Host *host = us_to_host(us);
int autopm_rc;
- current->flags |= PF_NOFREEZE;
-
for(;;) {
US_DEBUGP("*** thread sleeping.\n");
if(down_interruptible(&us->sema))
@@ -920,6 +918,7 @@ static int usb_stor_scan_thread(void * __us)
printk(KERN_DEBUG
"usb-storage: device found at %d\n", us->pusb_dev->devnum);
+ set_freezable();
/* Wait for the timeout to expire or for a disconnect */
if (delay_use > 0) {
printk(KERN_DEBUG "usb-storage: waiting for device "
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 0dda73da8628..7f907fb23b8a 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -60,7 +60,7 @@ static u_long videomemory;
static u_long videomemorysize;
static struct fb_info fb_info;
-static u32 mc68x328fb_pseudo_palette[17];
+static u32 mc68x328fb_pseudo_palette[16];
static struct fb_var_screeninfo mc68x328fb_default __initdata = {
.red = { 0, 8, 0 },
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 403dac787ebf..0c5644bb59af 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -812,7 +812,7 @@ config FB_PVR2
config FB_EPSON1355
bool "Epson 1355 framebuffer support"
- depends on (FB = y) && (SUPERH || ARCH_CEIVA)
+ depends on (FB = y) && ARCH_CEIVA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1790,8 +1790,8 @@ config FB_IBM_GXT4500
adaptor, found on some IBM System P (pSeries) machines.
config FB_PS3
- bool "PS3 GPU framebuffer driver"
- depends on (FB = y) && PS3_PS3AV
+ tristate "PS3 GPU framebuffer driver"
+ depends on FB && PS3_PS3AV
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
@@ -1820,6 +1820,10 @@ config FB_XILINX
framebuffer. ML300 carries a 640*480 LCD display on the board,
ML403 uses a standard DB15 VGA connector.
+if ARCH_OMAP
+ source "drivers/video/omap/Kconfig"
+endif
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bd8b05229500..a562f9d69d2c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
obj-$(CONFIG_FB_PS3) += ps3fb.o
obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+obj-$(CONFIG_FB_OMAP) += omap/
# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
index 90e7df22f508..685a754991c6 100644
--- a/drivers/video/aty/ati_ids.h
+++ b/drivers/video/aty/ati_ids.h
@@ -204,6 +204,7 @@
#define PCI_CHIP_RV280_5961 0x5961
#define PCI_CHIP_RV280_5962 0x5962
#define PCI_CHIP_RV280_5964 0x5964
+#define PCI_CHIP_RS485_5975 0x5975
#define PCI_CHIP_RV280_5C61 0x5C61
#define PCI_CHIP_RV280_5C63 0x5C63
#define PCI_CHIP_R423_5D57 0x5D57
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 2fbff6317433..ef330e34d031 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -541,7 +541,7 @@ static char ram_off[] __devinitdata = "OFF";
#endif /* CONFIG_FB_ATY_CT */
-static u32 pseudo_palette[17];
+static u32 pseudo_palette[16];
#ifdef CONFIG_FB_ATY_GX
static char *aty_gx_ram[8] __devinitdata = {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 2349e71b0083..47ca62fe7c3e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -153,6 +153,8 @@ static struct pci_device_id radeonfb_pci_table[] = {
/* Mobility 9200 (M9+) */
CHIP_DEF(PCI_CHIP_RV280_5C61, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
CHIP_DEF(PCI_CHIP_RV280_5C63, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /*Mobility Xpress 200 */
+ CHIP_DEF(PCI_CHIP_RS485_5975, R300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
/* 9200 */
CHIP_DEF(PCI_CHIP_RV280_5960, RV280, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV280_5961, RV280, CHIP_HAS_CRTC2),
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 7ebffcdfd1e3..7c922c7b460b 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -301,7 +301,7 @@ struct radeonfb_info {
void __iomem *bios_seg;
int fp_bios_start;
- u32 pseudo_palette[17];
+ u32 pseudo_palette[16];
struct { u8 red, green, blue, pad; }
palette[256];
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index d3b8a6be2916..49643969f9f8 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -118,6 +118,22 @@ config FRAMEBUFFER_CONSOLE
help
Low-level framebuffer-based console driver.
+config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
+ bool "Map the console to the primary display device"
+ depends on FRAMEBUFFER_CONSOLE
+ default n
+ ---help---
+ If this option is selected, the framebuffer console will
+ automatically select the primary display device (if the architecture
+ supports this feature). Otherwise, the framebuffer console will
+ always select the first framebuffer driver that is loaded. The latter
+ is the default behavior.
+
+ You can always override the automatic selection of the primary device
+ by using the fbcon=map: boot option.
+
+ If unsure, select n.
+
config FRAMEBUFFER_CONSOLE_ROTATION
bool "Framebuffer Console Rotation"
depends on FRAMEBUFFER_CONSOLE
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 73813c60d03a..decfdc8eb9cc 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -75,6 +75,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
+#include <asm/fb.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -125,6 +126,8 @@ static int first_fb_vc;
static int last_fb_vc = MAX_NR_CONSOLES - 1;
static int fbcon_is_default = 1;
static int fbcon_has_exited;
+static int primary_device = -1;
+static int map_override;
/* font data */
static char fontname[40];
@@ -152,6 +155,7 @@ static int fbcon_set_origin(struct vc_data *);
#define DEFAULT_CURSOR_BLINK_RATE (20)
static int vbl_cursor_cnt;
+static int fbcon_cursor_noblink;
#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1)
@@ -188,16 +192,14 @@ static __inline__ void ypan_down(struct vc_data *vc, int count);
static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
int dy, int dx, int height, int width, u_int y_break);
static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
- struct vc_data *vc);
-static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
- int unit);
+ int unit);
static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
int line, int count, int dy);
static void fbcon_modechanged(struct fb_info *info);
static void fbcon_set_all_vcs(struct fb_info *info);
static void fbcon_start(void);
static void fbcon_exit(void);
-static struct class_device *fbcon_class_device;
+static struct device *fbcon_device;
#ifdef CONFIG_MAC
/*
@@ -441,7 +443,8 @@ static void fbcon_add_cursor_timer(struct fb_info *info)
struct fbcon_ops *ops = info->fbcon_par;
if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
- !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
+ !(ops->flags & FBCON_FLAGS_CURSOR_TIMER) &&
+ !fbcon_cursor_noblink) {
if (!info->queue.func)
INIT_WORK(&info->queue, fb_flashcursor);
@@ -495,13 +498,17 @@ static int __init fb_console_setup(char *this_opt)
if (!strncmp(options, "map:", 4)) {
options += 4;
- if (*options)
+ if (*options) {
for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
if (!options[j])
j = 0;
con2fb_map_boot[i] =
(options[j++]-'0') % FB_MAX;
}
+
+ map_override = 1;
+ }
+
return 1;
}
@@ -736,7 +743,9 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
if (!err) {
info->fbcon_par = ops;
- set_blitting_type(vc, info);
+
+ if (vc)
+ set_blitting_type(vc, info);
}
if (err) {
@@ -798,11 +807,7 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
ops->flags |= FBCON_FLAGS_INIT;
ops->graphics = 0;
-
- if (vc)
- fbcon_set_disp(info, &info->var, vc);
- else
- fbcon_preset_disp(info, &info->var, unit);
+ fbcon_set_disp(info, &info->var, unit);
if (show_logo) {
struct vc_data *fg_vc = vc_cons[fg_console].d;
@@ -1107,6 +1112,9 @@ static void fbcon_init(struct vc_data *vc, int init)
if (var_to_display(p, &info->var, info))
return;
+ if (!info->fbcon_par)
+ con2fb_acquire_newinfo(vc, info, vc->vc_num, -1);
+
/* If we are not the first console on this
fb, copy the font from that console */
t = &fb_display[fg_console];
@@ -1349,6 +1357,11 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
return;
+ if (vc->vc_cursor_type & 0x10)
+ fbcon_del_cursor_timer(info);
+ else
+ fbcon_add_cursor_timer(info);
+
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
if (mode & CM_SOFTBACK) {
mode &= ~CM_SOFTBACK;
@@ -1368,36 +1381,29 @@ static int scrollback_phys_max = 0;
static int scrollback_max = 0;
static int scrollback_current = 0;
-/*
- * If no vc is existent yet, just set struct display
- */
-static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
- int unit)
-{
- struct display *p = &fb_display[unit];
- struct display *t = &fb_display[fg_console];
-
- if (var_to_display(p, var, info))
- return;
-
- p->fontdata = t->fontdata;
- p->userfont = t->userfont;
- if (p->userfont)
- REFCOUNT(p->fontdata)++;
-}
-
static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
- struct vc_data *vc)
+ int unit)
{
- struct display *p = &fb_display[vc->vc_num], *t;
- struct vc_data **default_mode = vc->vc_display_fg;
- struct vc_data *svc = *default_mode;
+ struct display *p, *t;
+ struct vc_data **default_mode, *vc;
+ struct vc_data *svc;
struct fbcon_ops *ops = info->fbcon_par;
int rows, cols, charcnt = 256;
+ p = &fb_display[unit];
+
if (var_to_display(p, var, info))
return;
+
+ vc = vc_cons[unit].d;
+
+ if (!vc)
+ return;
+
+ default_mode = vc->vc_display_fg;
+ svc = *default_mode;
t = &fb_display[svc->vc_num];
+
if (!vc->vc_font.data) {
vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -1704,6 +1710,56 @@ static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
}
}
+static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
+ struct display *p, int line, int count, int ycount)
+{
+ int offset = ycount * vc->vc_cols;
+ unsigned short *d = (unsigned short *)
+ (vc->vc_origin + vc->vc_size_row * line);
+ unsigned short *s = d + offset;
+ struct fbcon_ops *ops = info->fbcon_par;
+
+ while (count--) {
+ unsigned short *start = s;
+ unsigned short *le = advance_row(s, 1);
+ unsigned short c;
+ int x = 0;
+
+ do {
+ c = scr_readw(s);
+
+ if (c == scr_readw(d)) {
+ if (s > start) {
+ ops->bmove(vc, info, line + ycount, x,
+ line, x, 1, s-start);
+ x += s - start + 1;
+ start = s + 1;
+ } else {
+ x++;
+ start++;
+ }
+ }
+
+ scr_writew(c, d);
+ console_conditional_schedule();
+ s++;
+ d++;
+ } while (s < le);
+ if (s > start)
+ ops->bmove(vc, info, line + ycount, x, line, x, 1,
+ s-start);
+ console_conditional_schedule();
+ if (ycount > 0)
+ line++;
+ else {
+ line--;
+ /* NOTE: We subtract two lines from these pointers */
+ s -= vc->vc_size_row;
+ d -= vc->vc_size_row;
+ }
+ }
+}
+
static void fbcon_redraw(struct vc_data *vc, struct display *p,
int line, int count, int offset)
{
@@ -1789,7 +1845,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
- struct fbcon_ops *ops = info->fbcon_par;
int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
if (fbcon_is_inactive(vc, info))
@@ -1813,10 +1868,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
goto redraw_up;
switch (p->scrollmode) {
case SCROLL_MOVE:
- ops->bmove(vc, info, t + count, 0, t, 0,
- b - t - count, vc->vc_cols);
- ops->clear(vc, info, b - count, 0, count,
- vc->vc_cols);
+ fbcon_redraw_blit(vc, info, p, t, b - t - count,
+ count);
+ fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+ scr_memsetw((unsigned short *) (vc->vc_origin +
+ vc->vc_size_row *
+ (b - count)),
+ vc->vc_video_erase_char,
+ vc->vc_size_row * count);
+ return 1;
break;
case SCROLL_WRAP_MOVE:
@@ -1899,9 +1959,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
goto redraw_down;
switch (p->scrollmode) {
case SCROLL_MOVE:
- ops->bmove(vc, info, t, 0, t + count, 0,
- b - t - count, vc->vc_cols);
- ops->clear(vc, info, t, 0, count, vc->vc_cols);
+ fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+ -count);
+ fbcon_clear(vc, t, 0, count, vc->vc_cols);
+ scr_memsetw((unsigned short *) (vc->vc_origin +
+ vc->vc_size_row *
+ t),
+ vc->vc_video_erase_char,
+ vc->vc_size_row * count);
+ return 1;
break;
case SCROLL_WRAP_MOVE:
@@ -2937,9 +3003,48 @@ static int fbcon_mode_deleted(struct fb_info *info,
return found;
}
-static int fbcon_fb_unregistered(int idx)
+#ifdef CONFIG_VT_HW_CONSOLE_BINDING
+static int fbcon_unbind(void)
{
- int i;
+ int ret;
+
+ ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
+ fbcon_is_default);
+ return ret;
+}
+#else
+static inline int fbcon_unbind(void)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
+
+static int fbcon_fb_unbind(int idx)
+{
+ int i, new_idx = -1, ret = 0;
+
+ for (i = first_fb_vc; i <= last_fb_vc; i++) {
+ if (con2fb_map[i] != idx &&
+ con2fb_map[i] != -1) {
+ new_idx = i;
+ break;
+ }
+ }
+
+ if (new_idx != -1) {
+ for (i = first_fb_vc; i <= last_fb_vc; i++) {
+ if (con2fb_map[i] == idx)
+ set_con2fb_map(i, new_idx, 0);
+ }
+ } else
+ ret = fbcon_unbind();
+
+ return ret;
+}
+
+static int fbcon_fb_unregistered(struct fb_info *info)
+{
+ int i, idx = info->node;
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map[i] == idx)
@@ -2967,12 +3072,48 @@ static int fbcon_fb_unregistered(int idx)
if (!num_registered_fb)
unregister_con_driver(&fb_con);
+
+ if (primary_device == idx)
+ primary_device = -1;
+
return 0;
}
-static int fbcon_fb_registered(int idx)
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
+static void fbcon_select_primary(struct fb_info *info)
{
- int ret = 0, i;
+ if (!map_override && primary_device == -1 &&
+ fb_is_primary_device(info)) {
+ int i;
+
+ printk(KERN_INFO "fbcon: %s (fb%i) is primary device\n",
+ info->fix.id, info->node);
+ primary_device = info->node;
+
+ for (i = first_fb_vc; i <= last_fb_vc; i++)
+ con2fb_map_boot[i] = primary_device;
+
+ if (con_is_bound(&fb_con)) {
+ printk(KERN_INFO "fbcon: Remapping primary device, "
+ "fb%i, to tty %i-%i\n", info->node,
+ first_fb_vc + 1, last_fb_vc + 1);
+ info_idx = primary_device;
+ }
+ }
+
+}
+#else
+static inline void fbcon_select_primary(struct fb_info *info)
+{
+ return;
+}
+#endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
+
+static int fbcon_fb_registered(struct fb_info *info)
+{
+ int ret = 0, i, idx = info->node;
+
+ fbcon_select_primary(info);
if (info_idx == -1) {
for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -2986,8 +3127,7 @@ static int fbcon_fb_registered(int idx)
ret = fbcon_takeover(1);
} else {
for (i = first_fb_vc; i <= last_fb_vc; i++) {
- if (con2fb_map_boot[i] == idx &&
- con2fb_map[i] == -1)
+ if (con2fb_map_boot[i] == idx)
set_con2fb_map(i, idx, 0);
}
}
@@ -3034,12 +3174,7 @@ static void fbcon_new_modelist(struct fb_info *info)
mode = fb_find_nearest_mode(fb_display[i].mode,
&info->modelist);
fb_videomode_to_var(&var, mode);
-
- if (vc)
- fbcon_set_disp(info, &var, vc);
- else
- fbcon_preset_disp(info, &var, i);
-
+ fbcon_set_disp(info, &var, vc->vc_num);
}
}
@@ -3114,11 +3249,14 @@ static int fbcon_event_notify(struct notifier_block *self,
mode = event->data;
ret = fbcon_mode_deleted(info, mode);
break;
+ case FB_EVENT_FB_UNBIND:
+ ret = fbcon_fb_unbind(info->node);
+ break;
case FB_EVENT_FB_REGISTERED:
- ret = fbcon_fb_registered(info->node);
+ ret = fbcon_fb_registered(info);
break;
case FB_EVENT_FB_UNREGISTERED:
- ret = fbcon_fb_unregistered(info->node);
+ ret = fbcon_fb_unregistered(info);
break;
case FB_EVENT_SET_CONSOLE_MAP:
con2fb = event->data;
@@ -3179,8 +3317,9 @@ static struct notifier_block fbcon_event_notifier = {
.notifier_call = fbcon_event_notify,
};
-static ssize_t store_rotate(struct class_device *class_device,
- const char *buf, size_t count)
+static ssize_t store_rotate(struct device *device,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct fb_info *info;
int rotate, idx;
@@ -3203,8 +3342,9 @@ err:
return count;
}
-static ssize_t store_rotate_all(struct class_device *class_device,
- const char *buf, size_t count)
+static ssize_t store_rotate_all(struct device *device,
+ struct device_attribute *attr,const char *buf,
+ size_t count)
{
struct fb_info *info;
int rotate, idx;
@@ -3227,7 +3367,8 @@ err:
return count;
}
-static ssize_t show_rotate(struct class_device *class_device, char *buf)
+static ssize_t show_rotate(struct device *device,
+ struct device_attribute *attr,char *buf)
{
struct fb_info *info;
int rotate = 0, idx;
@@ -3248,20 +3389,86 @@ err:
return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
}
-static struct class_device_attribute class_device_attrs[] = {
+static ssize_t show_cursor_blink(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info;
+ struct fbcon_ops *ops;
+ int idx, blink = -1;
+
+ if (fbcon_has_exited)
+ return 0;
+
+ acquire_console_sem();
+ idx = con2fb_map[fg_console];
+
+ if (idx == -1 || registered_fb[idx] == NULL)
+ goto err;
+
+ info = registered_fb[idx];
+ ops = info->fbcon_par;
+
+ if (!ops)
+ goto err;
+
+ blink = (ops->flags & FBCON_FLAGS_CURSOR_TIMER) ? 1 : 0;
+err:
+ release_console_sem();
+ return snprintf(buf, PAGE_SIZE, "%d\n", blink);
+}
+
+static ssize_t store_cursor_blink(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *info;
+ int blink, idx;
+ char **last = NULL;
+
+ if (fbcon_has_exited)
+ return count;
+
+ acquire_console_sem();
+ idx = con2fb_map[fg_console];
+
+ if (idx == -1 || registered_fb[idx] == NULL)
+ goto err;
+
+ info = registered_fb[idx];
+
+ if (!info->fbcon_par)
+ goto err;
+
+ blink = simple_strtoul(buf, last, 0);
+
+ if (blink) {
+ fbcon_cursor_noblink = 0;
+ fbcon_add_cursor_timer(info);
+ } else {
+ fbcon_cursor_noblink = 1;
+ fbcon_del_cursor_timer(info);
+ }
+
+err:
+ release_console_sem();
+ return count;
+}
+
+static struct device_attribute device_attrs[] = {
__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
__ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all),
+ __ATTR(cursor_blink, S_IRUGO|S_IWUSR, show_cursor_blink,
+ store_cursor_blink),
};
-static int fbcon_init_class_device(void)
+static int fbcon_init_device(void)
{
int i, error = 0;
fbcon_has_sysfs = 1;
- for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
- error = class_device_create_file(fbcon_class_device,
- &class_device_attrs[i]);
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+ error = device_create_file(fbcon_device, &device_attrs[i]);
if (error)
break;
@@ -3269,8 +3476,7 @@ static int fbcon_init_class_device(void)
if (error) {
while (--i >= 0)
- class_device_remove_file(fbcon_class_device,
- &class_device_attrs[i]);
+ device_remove_file(fbcon_device, &device_attrs[i]);
fbcon_has_sysfs = 0;
}
@@ -3356,16 +3562,15 @@ static int __init fb_console_init(void)
acquire_console_sem();
fb_register_client(&fbcon_event_notifier);
- fbcon_class_device =
- class_device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon");
+ fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon");
- if (IS_ERR(fbcon_class_device)) {
- printk(KERN_WARNING "Unable to create class_device "
+ if (IS_ERR(fbcon_device)) {
+ printk(KERN_WARNING "Unable to create device "
"for fbcon; errno = %ld\n",
- PTR_ERR(fbcon_class_device));
- fbcon_class_device = NULL;
+ PTR_ERR(fbcon_device));
+ fbcon_device = NULL;
} else
- fbcon_init_class_device();
+ fbcon_init_device();
for (i = 0; i < MAX_NR_CONSOLES; i++)
con2fb_map[i] = -1;
@@ -3379,14 +3584,13 @@ module_init(fb_console_init);
#ifdef MODULE
-static void __exit fbcon_deinit_class_device(void)
+static void __exit fbcon_deinit_device(void)
{
int i;
if (fbcon_has_sysfs) {
- for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
- class_device_remove_file(fbcon_class_device,
- &class_device_attrs[i]);
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+ device_remove_file(fbcon_device, &device_attrs[i]);
fbcon_has_sysfs = 0;
}
@@ -3396,8 +3600,8 @@ static void __exit fb_console_exit(void)
{
acquire_console_sem();
fb_unregister_client(&fbcon_event_notifier);
- fbcon_deinit_class_device();
- class_device_destroy(fb_class, MKDEV(0, 0));
+ fbcon_deinit_device();
+ device_destroy(fb_class, MKDEV(0, 0));
fbcon_exit();
release_console_sem();
unregister_con_driver(&fb_con);
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 8b762739b1e0..b0be7eac32d8 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -94,7 +94,7 @@ static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninf
struct fb_info_control {
struct fb_info info;
struct fb_par_control par;
- u32 pseudo_palette[17];
+ u32 pseudo_palette[16];
struct cmap_regs __iomem *cmap_regs;
unsigned long cmap_regs_phys;
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 94a66c2d2cf5..e23324d10be2 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -1068,15 +1068,18 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
out8(0x3C9, green >> 10);
out8(0x3C9, blue >> 10);
- } else if (bpp == 16) // RGB 565
- ((u32 *) info->pseudo_palette)[regno] =
- (red & 0xF800) |
- ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
- else if (bpp == 32) // ARGB 8888
- ((u32 *) info->pseudo_palette)[regno] =
- ((transp & 0xFF00) << 16) |
- ((red & 0xFF00) << 8) |
- ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+ } else if (regno < 16) {
+ if (bpp == 16) // RGB 565
+ ((u32 *) info->pseudo_palette)[regno] =
+ (red & 0xF800) |
+ ((green & 0xFC00) >> 5) |
+ ((blue & 0xF800) >> 11);
+ else if (bpp == 32) // ARGB 8888
+ ((u32 *) info->pseudo_palette)[regno] =
+ ((transp & 0xFF00) << 16) |
+ ((red & 0xFF00) << 8) |
+ ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+ }
return 0;
}
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index ca2c54ce508e..33be46ccb54f 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -63,23 +63,12 @@
struct epson1355_par {
unsigned long reg_addr;
+ u32 pseudo_palette[16];
};
/* ------------------------------------------------------------------------- */
-#ifdef CONFIG_SUPERH
-
-static inline u8 epson1355_read_reg(int index)
-{
- return ctrl_inb(par.reg_addr + index);
-}
-
-static inline void epson1355_write_reg(u8 data, int index)
-{
- ctrl_outb(data, par.reg_addr + index);
-}
-
-#elif defined(CONFIG_ARM)
+#if defined(CONFIG_ARM)
# ifdef CONFIG_ARCH_CEIVA
# include <asm/arch/hardware.h>
@@ -289,7 +278,7 @@ static int epson1355fb_blank(int blank_mode, struct fb_info *info)
struct epson1355_par *par = info->par;
switch (blank_mode) {
- case FB_BLANK_UNBLANKING:
+ case FB_BLANK_UNBLANK:
case FB_BLANK_NORMAL:
lcd_enable(par, 1);
backlight_enable(1);
@@ -635,7 +624,7 @@ int __init epson1355fb_probe(struct platform_device *dev)
goto bail;
}
- info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
+ info = framebuffer_alloc(sizeof(struct epson1355_par), &dev->dev);
if (!info) {
rc = -ENOMEM;
goto bail;
@@ -648,7 +637,7 @@ int __init epson1355fb_probe(struct platform_device *dev)
rc = -ENOMEM;
goto bail;
}
- info->pseudo_palette = (void *)(default_par + 1);
+ info->pseudo_palette = default_par->pseudo_palette;
info->screen_base = ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
if (!info->screen_base) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 38c2e2558f5e..215ac579f901 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -33,17 +33,10 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/efi.h>
+#include <linux/fb.h>
-#if defined(__mc68000__) || defined(CONFIG_APUS)
-#include <asm/setup.h>
-#endif
+#include <asm/fb.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-#include <linux/fb.h>
/*
* Frame buffer device initialization and setup routines
@@ -411,10 +404,146 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
}
}
+static int fb_show_logo_line(struct fb_info *info, int rotate,
+ const struct linux_logo *logo, int y,
+ unsigned int n)
+{
+ u32 *palette = NULL, *saved_pseudo_palette = NULL;
+ unsigned char *logo_new = NULL, *logo_rotate = NULL;
+ struct fb_image image;
+
+ /* Return if the frame buffer is not mapped or suspended */
+ if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
+ info->flags & FBINFO_MODULE)
+ return 0;
+
+ image.depth = 8;
+ image.data = logo->data;
+
+ if (fb_logo.needs_cmapreset)
+ fb_set_logocmap(info, logo);
+
+ if (fb_logo.needs_truepalette ||
+ fb_logo.needs_directpalette) {
+ palette = kmalloc(256 * 4, GFP_KERNEL);
+ if (palette == NULL)
+ return 0;
+
+ if (fb_logo.needs_truepalette)
+ fb_set_logo_truepalette(info, logo, palette);
+ else
+ fb_set_logo_directpalette(info, logo, palette);
+
+ saved_pseudo_palette = info->pseudo_palette;
+ info->pseudo_palette = palette;
+ }
+
+ if (fb_logo.depth <= 4) {
+ logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
+ if (logo_new == NULL) {
+ kfree(palette);
+ if (saved_pseudo_palette)
+ info->pseudo_palette = saved_pseudo_palette;
+ return 0;
+ }
+ image.data = logo_new;
+ fb_set_logo(info, logo, logo_new, fb_logo.depth);
+ }
+
+ image.dx = 0;
+ image.dy = y;
+ image.width = logo->width;
+ image.height = logo->height;
+
+ if (rotate) {
+ logo_rotate = kmalloc(logo->width *
+ logo->height, GFP_KERNEL);
+ if (logo_rotate)
+ fb_rotate_logo(info, logo_rotate, &image, rotate);
+ }
+
+ fb_do_show_logo(info, &image, rotate, n);
+
+ kfree(palette);
+ if (saved_pseudo_palette != NULL)
+ info->pseudo_palette = saved_pseudo_palette;
+ kfree(logo_new);
+ kfree(logo_rotate);
+ return logo->height;
+}
+
+
+#ifdef CONFIG_FB_LOGO_EXTRA
+
+#define FB_LOGO_EX_NUM_MAX 10
+static struct logo_data_extra {
+ const struct linux_logo *logo;
+ unsigned int n;
+} fb_logo_ex[FB_LOGO_EX_NUM_MAX];
+static unsigned int fb_logo_ex_num;
+
+void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
+{
+ if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
+ return;
+
+ fb_logo_ex[fb_logo_ex_num].logo = logo;
+ fb_logo_ex[fb_logo_ex_num].n = n;
+ fb_logo_ex_num++;
+}
+
+static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
+ unsigned int yres)
+{
+ unsigned int i;
+
+ /* FIXME: logo_ex supports only truecolor fb. */
+ if (info->fix.visual != FB_VISUAL_TRUECOLOR)
+ fb_logo_ex_num = 0;
+
+ for (i = 0; i < fb_logo_ex_num; i++) {
+ height += fb_logo_ex[i].logo->height;
+ if (height > yres) {
+ height -= fb_logo_ex[i].logo->height;
+ fb_logo_ex_num = i;
+ break;
+ }
+ }
+ return height;
+}
+
+static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+ unsigned int i;
+
+ for (i = 0; i < fb_logo_ex_num; i++)
+ y += fb_show_logo_line(info, rotate,
+ fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
+
+ return y;
+}
+
+#else /* !CONFIG_FB_LOGO_EXTRA */
+
+static inline int fb_prepare_extra_logos(struct fb_info *info,
+ unsigned int height,
+ unsigned int yres)
+{
+ return height;
+}
+
+static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
+{
+ return y;
+}
+
+#endif /* CONFIG_FB_LOGO_EXTRA */
+
+
int fb_prepare_logo(struct fb_info *info, int rotate)
{
int depth = fb_get_color_depth(&info->var, &info->fix);
- int yres;
+ unsigned int yres;
memset(&fb_logo, 0, sizeof(struct logo_data));
@@ -456,7 +585,7 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
if (!fb_logo.logo) {
return 0;
}
-
+
if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
yres = info->var.yres;
else
@@ -473,75 +602,20 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
fb_logo.depth = 4;
else
- fb_logo.depth = 1;
- return fb_logo.logo->height;
+ fb_logo.depth = 1;
+
+ return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
}
int fb_show_logo(struct fb_info *info, int rotate)
{
- u32 *palette = NULL, *saved_pseudo_palette = NULL;
- unsigned char *logo_new = NULL, *logo_rotate = NULL;
- struct fb_image image;
-
- /* Return if the frame buffer is not mapped or suspended */
- if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING ||
- info->flags & FBINFO_MODULE)
- return 0;
-
- image.depth = 8;
- image.data = fb_logo.logo->data;
-
- if (fb_logo.needs_cmapreset)
- fb_set_logocmap(info, fb_logo.logo);
-
- if (fb_logo.needs_truepalette ||
- fb_logo.needs_directpalette) {
- palette = kmalloc(256 * 4, GFP_KERNEL);
- if (palette == NULL)
- return 0;
-
- if (fb_logo.needs_truepalette)
- fb_set_logo_truepalette(info, fb_logo.logo, palette);
- else
- fb_set_logo_directpalette(info, fb_logo.logo, palette);
-
- saved_pseudo_palette = info->pseudo_palette;
- info->pseudo_palette = palette;
- }
-
- if (fb_logo.depth <= 4) {
- logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
- GFP_KERNEL);
- if (logo_new == NULL) {
- kfree(palette);
- if (saved_pseudo_palette)
- info->pseudo_palette = saved_pseudo_palette;
- return 0;
- }
- image.data = logo_new;
- fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
- }
+ int y;
- image.dx = 0;
- image.dy = 0;
- image.width = fb_logo.logo->width;
- image.height = fb_logo.logo->height;
+ y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
+ num_online_cpus());
+ y = fb_show_extra_logos(info, y, rotate);
- if (rotate) {
- logo_rotate = kmalloc(fb_logo.logo->width *
- fb_logo.logo->height, GFP_KERNEL);
- if (logo_rotate)
- fb_rotate_logo(info, logo_rotate, &image, rotate);
- }
-
- fb_do_show_logo(info, &image, rotate, num_online_cpus());
-
- kfree(palette);
- if (saved_pseudo_palette != NULL)
- info->pseudo_palette = saved_pseudo_palette;
- kfree(logo_new);
- kfree(logo_rotate);
- return fb_logo.logo->height;
+ return y;
}
#else
int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
@@ -1155,17 +1229,15 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#endif
-static int
+static int
fb_mmap(struct file *file, struct vm_area_struct * vma)
{
int fbidx = iminor(file->f_path.dentry->d_inode);
struct fb_info *info = registered_fb[fbidx];
struct fb_ops *fb = info->fbops;
unsigned long off;
-#if !defined(__sparc__) || defined(__sparc_v9__)
unsigned long start;
u32 len;
-#endif
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
@@ -1180,12 +1252,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
return res;
}
-#if defined(__sparc__) && !defined(__sparc_v9__)
- /* Should never get here, all fb drivers should have their own
- mmap routines */
- return -EINVAL;
-#else
- /* !sparc32... */
lock_kernel();
/* frame buffer memory */
@@ -1209,50 +1275,11 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
vma->vm_pgoff = off >> PAGE_SHIFT;
/* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO | VM_RESERVED;
-#if defined(__mc68000__)
-#if defined(CONFIG_SUN3)
- pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
-#elif defined(CONFIG_MMU)
- if (CPU_IS_020_OR_030)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
- if (CPU_IS_040_OR_060) {
- pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
- /* Use no-cache mode, serialized */
- pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
- }
-#endif
-#elif defined(__powerpc__)
- vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-#elif defined(__alpha__)
- /* Caching is off in the I/O space quadrant by design. */
-#elif defined(__i386__) || defined(__x86_64__)
- if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#elif defined(__mips__) || defined(__sparc_v9__)
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#elif defined(__hppa__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-#elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-#elif defined(__avr32__)
- vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
- & ~_PAGE_CACHABLE)
- | (_PAGE_BUFFER | _PAGE_DIRTY));
-#elif defined(__ia64__)
- if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- else
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#else
-#warning What do we have to do here??
-#endif
+ fb_pgprotect(file, vma, off);
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
return 0;
-#endif /* !sparc32 */
}
static int
@@ -1388,17 +1415,34 @@ register_framebuffer(struct fb_info *fb_info)
*
* Returns negative errno on error, or zero for success.
*
+ * This function will also notify the framebuffer console
+ * to release the driver.
+ *
+ * This is meant to be called within a driver's module_exit()
+ * function. If this is called outside module_exit(), ensure
+ * that the driver implements fb_open() and fb_release() to
+ * check that no processes are using the device.
*/
int
unregister_framebuffer(struct fb_info *fb_info)
{
struct fb_event event;
- int i;
+ int i, ret = 0;
i = fb_info->node;
- if (!registered_fb[i])
- return -EINVAL;
+ if (!registered_fb[i]) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ event.info = fb_info;
+ ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+
+ if (ret) {
+ ret = -EINVAL;
+ goto done;
+ }
if (fb_info->pixmap.addr &&
(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
@@ -1410,7 +1454,8 @@ unregister_framebuffer(struct fb_info *fb_info)
device_destroy(fb_class, MKDEV(FB_MAJOR, i));
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
- return 0;
+done:
+ return ret;
}
/**
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 70ff55b14596..6c91c61cdb63 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -195,13 +195,15 @@ static int fm2fb_blank(int blank, struct fb_info *info)
static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- if (regno > info->cmap.len)
- return 1;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
+ if (regno < 16) {
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ ((u32*)(info->pseudo_palette))[regno] = (red << 16) |
+ (green << 8) | blue;
+ }
- ((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
return 0;
}
@@ -237,7 +239,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
if (!zorro_request_device(z,"fm2fb"))
return -ENXIO;
- info = framebuffer_alloc(256 * sizeof(u32), &z->dev);
+ info = framebuffer_alloc(16 * sizeof(u32), &z->dev);
if (!info) {
zorro_release_device(z);
return -ENOMEM;
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index bf0e60b5a3b6..b9b572b293d4 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -86,7 +86,7 @@ static int gbe_revision;
static int ypan, ywrap;
-static uint32_t pseudo_palette[256];
+static uint32_t pseudo_palette[16];
static char *mode_option __initdata = NULL;
@@ -854,8 +854,7 @@ static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
green >>= 8;
blue >>= 8;
- switch (info->var.bits_per_pixel) {
- case 8:
+ if (info->var.bits_per_pixel <= 8) {
/* wait for the color map FIFO to have a free entry */
for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
udelay(10);
@@ -864,23 +863,25 @@ static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 1;
}
gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
- break;
- case 15:
- case 16:
- red >>= 3;
- green >>= 3;
- blue >>= 3;
- pseudo_palette[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- break;
- case 32:
- pseudo_palette[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- break;
+ } else if (regno < 16) {
+ switch (info->var.bits_per_pixel) {
+ case 15:
+ case 16:
+ red >>= 3;
+ green >>= 3;
+ blue >>= 3;
+ pseudo_palette[regno] =
+ (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ break;
+ case 32:
+ pseudo_palette[regno] =
+ (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ break;
+ }
}
return 0;
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 889e4ea5edc1..328ae6c673ec 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -266,7 +266,7 @@ struct i810fb_par {
struct i810fb_i2c_chan chan[3];
struct mutex open_lock;
unsigned int use_count;
- u32 pseudo_palette[17];
+ u32 pseudo_palette[16];
unsigned long mmio_start_phys;
u8 __iomem *mmio_start_virtual;
u8 *edid;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 80b94c19a9fa..6148300fadd6 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -302,7 +302,7 @@ struct intelfb_info {
u32 ring_lockup;
/* palette */
- u32 pseudo_palette[17];
+ u32 pseudo_palette[16];
/* chip info */
int pci_chipset;
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 9397bcef3018..da219c043c99 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -10,6 +10,11 @@ menuconfig LOGO
if LOGO
+config FB_LOGO_EXTRA
+ bool
+ depends on FB
+ default y if SPU_BASE
+
config LOGO_LINUX_MONO
bool "Standard black and white Linux logo"
default y
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index b985dfad6c63..a5fc4edf84e6 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -14,6 +14,8 @@ obj-$(CONFIG_LOGO_SUPERH_VGA16) += logo_superh_vga16.o
obj-$(CONFIG_LOGO_SUPERH_CLUT224) += logo_superh_clut224.o
obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o
+obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o
+
# How to generate logo's
# Use logo-cfiles to retrieve list of .c files to be built
diff --git a/drivers/video/logo/logo_spe_clut224.ppm b/drivers/video/logo/logo_spe_clut224.ppm
new file mode 100644
index 000000000000..d36ad624a79c
--- /dev/null
+++ b/drivers/video/logo/logo_spe_clut224.ppm
@@ -0,0 +1,283 @@
+P3
+40 40
+255
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 6 6 6
+15 15 15 21 21 21 19 19 19 14 14 14 6 6 6 2 2 2
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 2 2 2 21 21 21 55 55 55
+56 56 56 54 54 54 53 53 53 60 60 60 56 56 56 25 25 25
+6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 2 2 2 27 27 27 62 62 62 17 17 19
+2 2 6 2 2 6 2 2 6 2 2 6 16 16 18 57 57 57
+45 45 45 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 16 16 16 62 62 62 8 8 10 2 2 6
+2 2 6 2 2 6 2 2 6 12 12 14 67 67 67 16 16 17
+45 45 45 41 41 41 4 4 4 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 2 2 2 35 35 35 40 40 40 2 2 6 2 2 6
+2 2 6 2 2 6 2 2 6 15 15 17 70 70 70 27 27 27
+3 3 6 62 62 62 20 20 20 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 4 4 4 58 58 58 12 12 14 2 2 6 2 2 6
+2 2 6 2 2 6 2 2 6 4 4 7 4 4 7 2 2 6
+2 2 6 34 34 36 40 40 40 3 3 3 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7 7 7 64 64 64 2 2 6 5 5 5 17 17 17
+3 3 6 2 2 6 2 2 6 15 15 15 21 21 21 7 7 10
+2 2 6 8 8 10 62 62 62 6 6 6 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7 7 7 66 66 66 5 5 8 122 122 122 122 122 122
+9 9 11 3 3 6 104 96 81 179 179 179 122 122 122 13 13 13
+2 2 6 2 2 6 67 67 67 10 10 10 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7 7 7 65 65 65 41 41 43 152 149 142 192 191 189
+48 48 49 23 23 24 228 210 210 86 86 86 192 191 189 59 59 61
+2 2 6 2 2 6 64 64 64 14 14 14 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7 7 7 66 66 66 59 59 59 59 59 61 86 86 86
+99 84 50 78 66 28 152 149 142 5 5 8 122 122 122 104 96 81
+2 2 6 2 2 6 67 67 67 14 14 14 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 5 5 5 63 63 63 24 24 24 152 149 142 175 122 13
+238 184 12 220 170 13 226 181 52 112 86 32 194 165 151 46 46 47
+2 2 6 2 2 6 65 65 65 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 5 5 5 59 59 59 21 21 21 175 122 13 231 174 11
+240 192 13 237 183 61 240 192 13 240 192 13 234 179 16 81 64 9
+2 2 6 2 2 6 63 63 63 25 25 25 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 5 5 5 54 54 54 51 48 39 189 138 9 238 184 12
+240 192 13 240 192 13 240 192 13 215 161 11 207 152 19 81 64 9
+16 16 18 5 5 8 40 40 40 44 44 44 4 4 4 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 5 5 5 59 59 59 27 27 27 126 107 64 187 136 12
+220 170 13 201 147 20 189 138 9 198 154 46 199 182 125 70 70 70
+27 27 27 104 96 81 12 12 14 70 70 70 16 16 16 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 17 17 17 70 70 70 12 12 12 168 168 168 174 135 135
+175 122 13 175 122 13 178 151 83 192 191 189 233 233 233 179 179 179
+3 3 6 29 29 31 3 3 6 41 41 41 44 44 44 5 5 5
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+8 8 8 53 53 53 44 44 44 59 59 59 238 238 238 192 191 189
+192 191 189 192 191 189 221 205 205 240 240 240 253 253 253 253 253 253
+70 70 70 2 2 6 2 2 6 5 5 8 67 67 67 22 22 22
+2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 5
+38 38 38 56 56 56 7 7 9 221 205 205 253 253 253 233 233 233
+221 205 205 233 233 233 251 251 251 253 253 253 253 253 253 253 253 253
+192 191 189 2 2 6 2 2 6 2 2 6 25 25 25 64 64 64
+15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 27 27 27
+66 66 66 7 7 9 86 86 86 252 252 252 253 253 253 253 253 253
+252 252 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+244 244 244 19 19 21 2 2 6 2 2 6 2 2 6 38 38 38
+54 54 54 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 62 62 62
+10 10 12 3 3 6 122 122 122 235 235 235 251 251 251 248 248 248
+235 235 235 248 248 248 252 252 252 246 246 246 233 233 233 237 228 228
+223 207 207 70 70 70 2 2 6 2 2 6 2 2 6 2 2 6
+46 46 47 38 38 38 4 4 4 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 2 2 2 33 33 33 44 44 44
+4 4 7 9 9 11 168 168 168 240 240 240 252 252 252 252 252 252
+246 246 246 253 253 253 253 253 253 251 251 251 245 241 241 233 233 233
+221 205 205 192 191 189 29 29 31 27 27 27 9 9 12 2 2 6
+3 3 6 65 65 65 15 15 15 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 6 6 6 59 59 59 19 19 21
+24 24 24 86 86 86 249 249 249 253 253 253 253 253 253 253 253 253
+253 253 253 228 210 210 241 230 230 253 253 253 253 253 253 253 253 253
+251 251 251 228 210 210 152 149 142 5 5 8 27 27 27 4 4 7
+2 2 6 46 46 47 34 34 34 2 2 2 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 16 16 16 67 67 67 19 19 21
+12 12 14 223 207 207 254 20 20 254 20 20 253 127 127 242 223 223
+254 20 20 253 127 127 254 48 48 242 223 223 254 86 86 254 20 20
+254 20 20 253 137 137 233 233 233 32 32 32 35 35 35 23 23 24
+2 2 6 15 15 15 60 60 60 6 6 6 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 4 4 4 38 38 38 48 48 49 22 22 22
+86 86 86 253 253 253 254 20 20 241 230 230 227 216 186 253 137 137
+253 137 137 253 253 253 253 137 137 253 137 137 254 48 48 253 253 253
+253 253 253 253 253 253 253 253 253 62 62 62 2 2 6 23 23 24
+2 2 6 2 2 6 62 62 62 17 17 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 14 14 14 70 70 70 14 14 14 16 16 18
+179 179 179 253 253 253 227 216 186 254 48 48 240 219 160 253 127 127
+254 20 20 253 137 137 254 86 86 231 203 141 254 20 20 254 20 20
+253 137 137 253 253 253 253 253 253 104 96 81 2 2 6 23 23 24
+2 2 6 2 2 6 46 46 47 27 27 27 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 4 4 4 39 39 39 42 42 43 19 19 21 13 13 13
+228 210 210 242 223 223 253 253 253 242 223 223 253 127 127 253 127 127
+253 127 127 253 127 127 253 137 137 253 253 253 254 48 48 253 253 253
+228 210 210 253 253 253 253 253 253 122 122 122 2 2 6 19 19 19
+2 2 6 2 2 6 39 39 39 38 38 38 3 3 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 8 8 8 60 60 60 3 3 6 33 33 33 38 38 38
+253 137 137 254 86 86 253 137 137 254 86 86 253 137 137 209 197 168
+253 127 127 253 253 253 253 253 253 253 253 253 253 127 127 254 86 86
+254 86 86 253 137 137 253 253 253 122 122 122 2 2 6 17 17 17
+2 2 6 2 2 6 34 34 36 42 42 43 3 3 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 13 13 13 59 59 59 2 2 6 9 9 12 56 56 56
+252 252 252 240 219 160 253 137 137 240 219 160 253 253 253 237 228 228
+254 86 86 253 253 253 253 253 253 253 253 253 253 253 253 242 223 223
+227 216 186 249 249 249 253 253 253 122 122 122 16 16 17 17 17 17
+12 12 14 3 3 6 39 39 39 38 38 38 3 3 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2
+5 5 5 22 22 22 104 96 81 187 136 12 207 152 19 51 48 39
+221 205 205 253 253 253 253 253 253 253 253 253 253 253 253 240 240 240
+250 247 243 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 250 247 243 240 219 160 99 84 50 5 5 8 2 2 6
+7 7 9 46 46 47 58 58 58 35 35 35 3 3 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 33 33 33
+58 58 58 86 86 86 170 136 53 239 182 13 246 190 14 220 170 13
+44 38 29 179 179 179 253 253 253 253 253 253 253 253 253 240 240 240
+253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+253 253 253 240 219 160 240 192 13 112 86 32 2 2 6 2 2 6
+3 3 6 41 33 20 220 170 13 53 53 53 4 4 4 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 2 2 2 32 32 32 150 116 44
+215 161 11 215 161 11 228 170 11 245 188 14 246 190 14 246 190 14
+187 136 12 9 9 11 122 122 122 251 251 251 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+248 248 248 211 196 135 239 182 13 175 122 13 6 5 6 2 2 6
+16 14 12 187 136 12 238 184 12 84 78 65 10 10 10 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 4 4 4 53 53 53 207 152 19
+242 185 13 245 188 14 246 190 14 246 190 14 246 190 14 246 190 14
+240 192 13 81 64 9 2 2 6 86 86 86 244 244 244 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+233 233 233 199 182 125 231 174 11 207 152 19 175 122 13 175 122 13
+201 147 20 239 182 13 244 187 14 150 116 44 35 35 35 6 6 6
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 5 5 5 53 53 53 201 147 20
+242 185 13 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 220 170 13 13 11 10 2 2 6 152 149 142 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+235 235 235 199 182 125 228 170 11 234 177 12 226 168 11 226 168 11
+234 177 12 246 190 14 246 190 14 234 179 16 126 107 64 36 36 36
+6 6 6 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 3 3 3 48 48 49 189 142 35
+242 185 13 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 140 112 39 36 36 36 192 191 189 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253
+192 191 189 112 86 32 226 168 11 244 187 14 244 187 14 244 187 14
+245 188 14 246 190 14 246 190 14 246 190 14 242 185 13 150 116 44
+27 27 27 2 2 2 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 6 6 6 58 58 58 189 142 35
+239 182 13 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 239 188 14 209 197 168 253 253 253 253 253 253
+253 253 253 253 253 253 253 253 253 253 253 253 252 252 252 168 168 168
+16 16 18 97 67 8 228 170 11 245 188 14 246 190 14 246 190 14
+246 190 14 246 190 14 246 190 14 246 190 14 244 187 14 198 154 46
+35 35 35 3 3 3 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 13 13 13 84 78 65 215 161 11
+244 187 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 238 184 12 187 136 12 168 168 168 244 244 244
+253 253 253 252 252 252 240 240 240 179 179 179 67 67 67 2 2 6
+2 2 6 97 67 8 228 170 11 246 190 14 246 190 14 246 190 14
+246 190 14 246 190 14 245 188 14 234 177 12 189 142 35 86 77 61
+16 16 16 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 13 13 13 103 92 56 207 152 19
+228 170 11 234 177 12 239 182 13 242 186 14 245 188 14 246 190 14
+246 190 14 246 190 14 239 182 13 189 138 9 41 33 20 10 10 12
+30 30 31 23 23 24 5 5 8 2 2 6 2 2 6 2 2 6
+4 4 6 112 86 32 215 161 11 245 188 14 246 190 14 245 188 14
+239 182 13 228 170 11 189 142 35 104 96 81 48 48 49 17 17 17
+2 2 2 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 5 5 5 39 39 39 103 92 56
+141 109 44 175 122 13 187 136 12 189 138 9 207 152 19 228 170 11
+239 182 13 239 182 13 215 161 11 175 122 13 41 33 20 2 2 6
+15 15 17 20 20 22 20 20 22 20 20 22 20 20 22 8 8 10
+4 4 6 97 67 8 189 138 9 231 174 11 239 182 13 226 168 11
+189 138 9 126 107 64 59 59 59 21 21 21 5 5 5 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 5 5 5 17 17 17
+34 34 34 57 57 57 84 78 65 103 92 56 125 101 41 140 112 39
+175 122 13 175 122 13 175 122 13 97 67 8 72 67 58 84 78 65
+60 60 60 56 56 56 56 56 56 56 56 56 57 57 57 65 65 65
+86 86 86 95 73 34 175 122 13 187 136 12 187 136 12 175 122 13
+103 92 56 41 41 41 10 10 10 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+2 2 2 4 4 4 12 12 12 24 24 24 40 40 40 70 70 70
+86 77 61 95 73 34 88 72 41 72 67 58 36 36 36 10 10 10
+5 5 5 5 5 5 5 5 5 4 4 4 5 5 5 6 6 6
+22 22 22 61 61 59 88 72 41 112 86 32 112 86 32 84 78 65
+32 32 32 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 10 10 10
+21 21 21 33 33 33 31 31 31 16 16 16 2 2 2 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+2 2 2 12 12 12 30 30 31 40 40 40 32 32 32 16 16 16
+2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index f7d647dda978..aa8c714d6245 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -170,7 +170,7 @@ static struct fb_fix_screeninfo macfb_fix = {
};
static struct fb_info fb_info;
-static u32 pseudo_palette[17];
+static u32 pseudo_palette[16];
static int inverse = 0;
static int vidtest = 0;
@@ -529,56 +529,63 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (regno >= fb_info->cmap.len)
return 1;
- switch (fb_info->var.bits_per_pixel) {
- case 1:
- /* We shouldn't get here */
- break;
- case 2:
- case 4:
- case 8:
- if (macfb_setpalette)
- macfb_setpalette(regno, red, green, blue, fb_info);
- else
- return 1;
- break;
- case 16:
- if (fb_info->var.red.offset == 10) {
- /* 1:5:5:5 */
- ((u32*) (fb_info->pseudo_palette))[regno] =
+ if (fb_info->var.bits_per_pixel <= 8) {
+ switch (fb_info->var.bits_per_pixel) {
+ case 1:
+ /* We shouldn't get here */
+ break;
+ case 2:
+ case 4:
+ case 8:
+ if (macfb_setpalette)
+ macfb_setpalette(regno, red, green, blue,
+ fb_info);
+ else
+ return 1;
+ break;
+ }
+ } else if (regno < 16) {
+ switch (fb_info->var.bits_per_pixel) {
+ case 16:
+ if (fb_info->var.red.offset == 10) {
+ /* 1:5:5:5 */
+ ((u32*) (fb_info->pseudo_palette))[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) |
((blue & 0xf800) >> 11) |
((transp != 0) << 15);
- } else {
- /* 0:5:6:5 */
- ((u32*) (fb_info->pseudo_palette))[regno] =
+ } else {
+ /* 0:5:6:5 */
+ ((u32*) (fb_info->pseudo_palette))[regno] =
((red & 0xf800) ) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
+ }
+ break;
+ /* I'm pretty sure that one or the other of these
+ doesn't exist on 68k Macs */
+ case 24:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ ((u32 *)(fb_info->pseudo_palette))[regno] =
+ (red << fb_info->var.red.offset) |
+ (green << fb_info->var.green.offset) |
+ (blue << fb_info->var.blue.offset);
+ break;
+ case 32:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ ((u32 *)(fb_info->pseudo_palette))[regno] =
+ (red << fb_info->var.red.offset) |
+ (green << fb_info->var.green.offset) |
+ (blue << fb_info->var.blue.offset);
+ break;
}
- break;
- /* I'm pretty sure that one or the other of these
- doesn't exist on 68k Macs */
- case 24:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(fb_info->pseudo_palette))[regno] =
- (red << fb_info->var.red.offset) |
- (green << fb_info->var.green.offset) |
- (blue << fb_info->var.blue.offset);
- break;
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(fb_info->pseudo_palette))[regno] =
- (red << fb_info->var.red.offset) |
- (green << fb_info->var.green.offset) |
- (blue << fb_info->var.blue.offset);
- break;
- }
- return 0;
+ }
+
+ return 0;
}
static struct fb_ops macfb_ops = {
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index ab2149531a04..083f60321ed8 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -369,9 +369,8 @@ EXPORT_SYMBOL(mac_map_monitor_sense);
*
*/
-int __devinit mac_find_mode(struct fb_var_screeninfo *var,
- struct fb_info *info, const char *mode_option,
- unsigned int default_bpp)
+int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const char *mode_option, unsigned int default_bpp)
{
const struct fb_videomode *db = NULL;
unsigned int dbsize = 0;
diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h
index babeb81f467d..b86ba08aac9e 100644
--- a/drivers/video/macmodes.h
+++ b/drivers/video/macmodes.h
@@ -55,10 +55,10 @@ extern int mac_vmode_to_var(int vmode, int cmode,
extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
int *cmode);
extern int mac_map_monitor_sense(int sense);
-extern int __devinit mac_find_mode(struct fb_var_screeninfo *var,
- struct fb_info *info,
- const char *mode_option,
- unsigned int default_bpp);
+extern int mac_find_mode(struct fb_var_screeninfo *var,
+ struct fb_info *info,
+ const char *mode_option,
+ unsigned int default_bpp);
/*
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index c57aaadf410c..3660d2673bdc 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -91,7 +91,6 @@ static inline void matrox_cfb4_pal(u_int32_t* pal) {
for (i = 0; i < 16; i++) {
pal[i] = i * 0x11111111U;
}
- pal[i] = 0xFFFFFFFF;
}
static inline void matrox_cfb8_pal(u_int32_t* pal) {
@@ -100,7 +99,6 @@ static inline void matrox_cfb8_pal(u_int32_t* pal) {
for (i = 0; i < 16; i++) {
pal[i] = i * 0x01010101U;
}
- pal[i] = 0x0F0F0F0F;
}
static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
@@ -145,13 +143,10 @@ void matrox_cfbX_init(WPMINFO2) {
ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit;
}
break;
- case 16: if (ACCESS_FBINFO(fbcon).var.green.length == 5) {
+ case 16: if (ACCESS_FBINFO(fbcon).var.green.length == 5)
maccess = 0xC0000001;
- ACCESS_FBINFO(cmap[16]) = 0x7FFF7FFF;
- } else {
+ else
maccess = 0x40000001;
- ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
- }
mopmode = M_OPMODE_16BPP;
if (accel) {
ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
@@ -161,7 +156,6 @@ void matrox_cfbX_init(WPMINFO2) {
break;
case 24: maccess = 0x00000003;
mopmode = M_OPMODE_24BPP;
- ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
if (accel) {
ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect;
@@ -170,7 +164,6 @@ void matrox_cfbX_init(WPMINFO2) {
break;
case 32: maccess = 0x00000002;
mopmode = M_OPMODE_32BPP;
- ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF;
if (accel) {
ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea;
ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 886e475f22f2..86ca7b179000 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -679,6 +679,8 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
mga_outb(M_DAC_VAL, blue);
break;
case 16:
+ if (regno >= 16)
+ break;
{
u_int16_t col =
(red << ACCESS_FBINFO(fbcon).var.red.offset) |
@@ -690,6 +692,8 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
break;
case 24:
case 32:
+ if (regno >= 16)
+ break;
ACCESS_FBINFO(cmap[regno]) =
(red << ACCESS_FBINFO(fbcon).var.red.offset) |
(green << ACCESS_FBINFO(fbcon).var.green.offset) |
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 9c25c2f7966b..d59577c8de86 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -518,7 +518,7 @@ struct matrox_fb_info {
dll:1;
} memory;
} values;
- u_int32_t cmap[17];
+ u_int32_t cmap[16];
};
#define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 03ae55b168ff..4b3344e03695 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -163,11 +163,6 @@ static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004;
}
-static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info) {
- /* no acceleration for secondary head... */
- m2info->cmap[16] = 0xFFFFFFFF;
-}
-
static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
struct fb_var_screeninfo* var) {
unsigned int pos;
@@ -385,7 +380,6 @@ static int matroxfb_dh_set_par(struct fb_info* info) {
}
}
up_read(&ACCESS_FBINFO(altout).lock);
- matroxfb_dh_cfbX_init(m2info);
}
m2info->initialized = 1;
return 0;
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
index 177177609be7..1005582e843e 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/matrox/matroxfb_crtc2.h
@@ -28,7 +28,7 @@ struct matroxfb_dh_fb_info {
unsigned int interlaced:1;
- u_int32_t cmap[17];
+ u_int32_t cmap[16];
};
#endif /* __MATROXFB_CRTC2_H__ */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 5d29a26b8cdf..de0d755f9019 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -273,8 +273,11 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
}
}
}
+
+ /* if h2/post/in/feed have not been assigned, return zero (error) */
if (besth2 < 2)
return 0;
+
dprintk(KERN_ERR "clk: %02X %02X %02X %d %d\n", *in, *feed, *post, fxtal, fwant);
return fxtal * (*feed) / (*in) * ctl->den;
}
@@ -284,7 +287,7 @@ static unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl,
unsigned int* in, unsigned int* feed, unsigned int* post,
unsigned int* htotal2) {
unsigned int fvco;
- unsigned int p;
+ unsigned int uninitialized_var(p);
fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
if (!fvco)
@@ -715,7 +718,9 @@ static int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
m->regs[0x82] = 0x81;
for (x = 0; x < 8; x++) {
- unsigned int a, b, c, h2;
+ unsigned int c;
+ unsigned int uninitialized_var(a), uninitialized_var(b),
+ uninitialized_var(h2);
unsigned int h = ht + 2 + x;
if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index aff11bbf59a7..d1a10549f543 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -150,8 +150,7 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
M = pll & 0xFF;
N = (pll >> 8) & 0xFF;
if (((par->Chipset & 0xfff0) == 0x0290) ||
- ((par->Chipset & 0xfff0) == 0x0390) ||
- ((par->Chipset & 0xfff0) == 0x02E0)) {
+ ((par->Chipset & 0xfff0) == 0x0390)) {
MB = 1;
NB = 1;
} else {
@@ -161,7 +160,7 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
pll = NV_RD32(par->PMC, 0x4000);
- P = (pll >> 16) & 0x03;
+ P = (pll >> 16) & 0x07;
pll = NV_RD32(par->PMC, 0x4004);
M = pll & 0xFF;
N = (pll >> 8) & 0xFF;
@@ -892,11 +891,17 @@ void NVCalcStateExt(struct nvidia_par *par,
state->general = bpp == 16 ? 0x00101100 : 0x00100100;
state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
break;
+ case NV_ARCH_40:
+ if (!par->FlatPanel)
+ state->control = NV_RD32(par->PRAMDAC0, 0x0580) &
+ 0xeffffeff;
+ /* fallthrough */
case NV_ARCH_10:
case NV_ARCH_20:
case NV_ARCH_30:
default:
- if ((par->Chipset & 0xfff0) == 0x0240) {
+ if ((par->Chipset & 0xfff0) == 0x0240 ||
+ (par->Chipset & 0xfff0) == 0x03d0) {
state->arbitration0 = 256;
state->arbitration1 = 0x0480;
} else if (((par->Chipset & 0xffff) == 0x01A0) ||
@@ -939,7 +944,7 @@ void NVCalcStateExt(struct nvidia_par *par,
void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
{
- int i;
+ int i, j;
NV_WR32(par->PMC, 0x0140, 0x00000000);
NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
@@ -951,7 +956,8 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
if (par->Architecture == NV_ARCH_04) {
- NV_WR32(par->PFB, 0x0200, state->config);
+ if (state)
+ NV_WR32(par->PFB, 0x0200, state->config);
} else if ((par->Architecture < NV_ARCH_40) ||
(par->Chipset & 0xfff0) == 0x0040) {
for (i = 0; i < 8; i++) {
@@ -964,8 +970,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
if (((par->Chipset & 0xfff0) == 0x0090) ||
((par->Chipset & 0xfff0) == 0x01D0) ||
- ((par->Chipset & 0xfff0) == 0x02E0) ||
- ((par->Chipset & 0xfff0) == 0x0290))
+ ((par->Chipset & 0xfff0) == 0x0290) ||
+ ((par->Chipset & 0xfff0) == 0x0390) ||
+ ((par->Chipset & 0xfff0) == 0x03D0))
regions = 15;
for(i = 0; i < regions; i++) {
NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
@@ -1206,16 +1213,20 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
} else {
if (par->Architecture >= NV_ARCH_40) {
- u32 tmp;
-
NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+ NV_WR32(par->PGRAPH, 0x0bc4,
+ NV_RD32(par->PGRAPH, 0x0bc4) |
+ 0x00008000);
- tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
- for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
- NV_WR32(par->PGRAPH, 0x5000, i);
+ j = NV_RD32(par->REGS, 0x1540) & 0xff;
+
+ if (j) {
+ for (i = 0; !(j & 1); j >>= 1, i++);
+ NV_WR32(par->PGRAPH, 0x5000, i);
+ }
if ((par->Chipset & 0xfff0) == 0x0040) {
NV_WR32(par->PGRAPH, 0x09b0,
@@ -1250,6 +1261,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
case 0x0160:
case 0x01D0:
case 0x0240:
+ case 0x03D0:
NV_WR32(par->PMC, 0x1700,
NV_RD32(par->PFB, 0x020C));
NV_WR32(par->PMC, 0x1704, 0);
@@ -1269,7 +1281,6 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
0x00000108);
break;
case 0x0220:
- case 0x0230:
NV_WR32(par->PGRAPH, 0x0860, 0);
NV_WR32(par->PGRAPH, 0x0864, 0);
NV_WR32(par->PRAMDAC, 0x0608,
@@ -1277,8 +1288,8 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
0x00100000);
break;
case 0x0090:
- case 0x02E0:
case 0x0290:
+ case 0x0390:
NV_WR32(par->PRAMDAC, 0x0608,
NV_RD32(par->PRAMDAC, 0x0608) |
0x00100000);
@@ -1355,8 +1366,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
} else {
if (((par->Chipset & 0xfff0) == 0x0090) ||
((par->Chipset & 0xfff0) == 0x01D0) ||
- ((par->Chipset & 0xfff0) == 0x02E0) ||
- ((par->Chipset & 0xfff0) == 0x0290)) {
+ ((par->Chipset & 0xfff0) == 0x0290) ||
+ ((par->Chipset & 0xfff0) == 0x0390) ||
+ ((par->Chipset & 0xfff0) == 0x03D0)) {
for (i = 0; i < 60; i++) {
NV_WR32(par->PGRAPH,
0x0D00 + i*4,
@@ -1407,8 +1419,8 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
} else {
if ((par->Chipset & 0xfff0) == 0x0090 ||
(par->Chipset & 0xfff0) == 0x01D0 ||
- (par->Chipset & 0xfff0) == 0x02E0 ||
- (par->Chipset & 0xfff0) == 0x0290) {
+ (par->Chipset & 0xfff0) == 0x0290 ||
+ (par->Chipset & 0xfff0) == 0x0390) {
NV_WR32(par->PGRAPH, 0x0DF0,
NV_RD32(par->PFB, 0x0200));
NV_WR32(par->PGRAPH, 0x0DF4,
@@ -1495,6 +1507,12 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+
+ if (!state) {
+ par->CurrentState = NULL;
+ return;
+ }
+
if (par->Architecture >= NV_ARCH_10) {
if (par->twoHeads) {
NV_WR32(par->PCRTC0, 0x0860, state->head);
@@ -1566,6 +1584,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
VGA_WR08(par->PCIO, 0x03D5, state->interlace);
if (!par->FlatPanel) {
+ if (par->Architecture >= NV_ARCH_40)
+ NV_WR32(par->PRAMDAC0, 0x0580, state->control);
+
NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
if (par->twoHeads)
@@ -1631,6 +1652,9 @@ void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) {
state->scale = NV_RD32(par->PRAMDAC, 0x0848);
state->config = NV_RD32(par->PFB, 0x0200);
+ if (par->Architecture >= NV_ARCH_40 && !par->FlatPanel)
+ state->control = NV_RD32(par->PRAMDAC0, 0x0580);
+
if (par->Architecture >= NV_ARCH_10) {
if (par->twoHeads) {
state->head = NV_RD32(par->PCRTC0, 0x0860);
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 707e2c8a13ed..82579d3a9970 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -166,11 +166,13 @@ u8 NVReadDacData(struct nvidia_par *par)
static int NVIsConnected(struct nvidia_par *par, int output)
{
volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
- u32 reg52C, reg608;
+ u32 reg52C, reg608, dac0_reg608 = 0;
int present;
- if (output)
- PRAMDAC += 0x800;
+ if (output) {
+ dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
+ PRAMDAC += 0x800;
+ }
reg52C = NV_RD32(PRAMDAC, 0x052C);
reg608 = NV_RD32(PRAMDAC, 0x0608);
@@ -194,8 +196,8 @@ static int NVIsConnected(struct nvidia_par *par, int output)
else
printk("nvidiafb: CRTC%i analog not found\n", output);
- NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
- 0x0000EFFF);
+ if (output)
+ NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
NV_WR32(PRAMDAC, 0x052C, reg52C);
NV_WR32(PRAMDAC, 0x0608, reg608);
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index 38f7cc0a2331..2fdf77ec39fc 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -86,6 +86,7 @@ typedef struct _riva_hw_state {
u32 timingV;
u32 displayV;
u32 crtcSync;
+ u32 control;
} RIVA_HW_STATE;
struct riva_regs {
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 41f63658572f..a7fe214f0f77 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -674,6 +674,7 @@ static int nvidiafb_set_par(struct fb_info *info)
info->fbops->fb_sync = nvidiafb_sync;
info->pixmap.scan_align = 4;
info->flags &= ~FBINFO_HWACCEL_DISABLED;
+ info->flags |= FBINFO_READS_FAST;
NVResetGraphics(info);
} else {
info->fbops->fb_imageblit = cfb_imageblit;
@@ -682,6 +683,7 @@ static int nvidiafb_set_par(struct fb_info *info)
info->fbops->fb_sync = NULL;
info->pixmap.scan_align = 1;
info->flags |= FBINFO_HWACCEL_DISABLED;
+ info->flags &= ~FBINFO_READS_FAST;
}
par->cursor_reset = 1;
@@ -1193,7 +1195,8 @@ static u32 __devinit nvidia_get_chipset(struct fb_info *info)
printk(KERN_INFO PFX "Device ID: %x \n", id);
- if ((id & 0xfff0) == 0x00f0) {
+ if ((id & 0xfff0) == 0x00f0 ||
+ (id & 0xfff0) == 0x02e0) {
/* pci-e */
id = NV_RD32(par->REGS, 0x1800);
@@ -1238,18 +1241,16 @@ static u32 __devinit nvidia_get_arch(struct fb_info *info)
case 0x0040: /* GeForce 6800 */
case 0x00C0: /* GeForce 6800 */
case 0x0120: /* GeForce 6800 */
- case 0x0130:
case 0x0140: /* GeForce 6600 */
case 0x0160: /* GeForce 6200 */
case 0x01D0: /* GeForce 7200, 7300, 7400 */
- case 0x02E0: /* GeForce 7300 GT */
case 0x0090: /* GeForce 7800 */
case 0x0210: /* GeForce 6800 */
case 0x0220: /* GeForce 6200 */
- case 0x0230:
case 0x0240: /* GeForce 6100 */
case 0x0290: /* GeForce 7900 */
case 0x0390: /* GeForce 7600 */
+ case 0x03D0:
arch = NV_ARCH_40;
break;
case 0x0020: /* TNT, TNT2 */
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 885b42836cbb..452433d46973 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -271,7 +271,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
return;
}
- size = sizeof(struct fb_info) + sizeof(u32) * 17;
+ size = sizeof(struct fb_info) + sizeof(u32) * 16;
info = kmalloc(size, GFP_ATOMIC);
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
new file mode 100644
index 000000000000..7f4d25b8a184
--- /dev/null
+++ b/drivers/video/omap/Kconfig
@@ -0,0 +1,58 @@
+config FB_OMAP
+ tristate "OMAP frame buffer support (EXPERIMENTAL)"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Frame buffer driver for OMAP based boards.
+
+config FB_OMAP_BOOTLOADER_INIT
+ bool "Check bootloader initializaion"
+ depends on FB_OMAP
+ help
+ Say Y here if you want to enable checking if the bootloader has
+ already initialized the display controller. In this case the
+ driver will skip the initialization.
+
+config FB_OMAP_CONSISTENT_DMA_SIZE
+ int "Consistent DMA memory size (MB)"
+ depends on FB_OMAP
+ range 1 14
+ default 2
+ help
+ Increase the DMA consistent memory size according to your video
+ memory needs, for example if you want to use multiple planes.
+ The size must be 2MB aligned.
+ If unsure say 1.
+
+config FB_OMAP_DMA_TUNE
+ bool "Set DMA SDRAM access priority high"
+ depends on FB_OMAP && ARCH_OMAP1
+ help
+ On systems in which video memory is in system memory
+ (SDRAM) this will speed up graphics DMA operations.
+ If you have such a system and want to use rotation
+ answer yes. Answer no if you have a dedicated video
+ memory, or don't use any of the accelerated features.
+
+config FB_OMAP_LCDC_EXTERNAL
+ bool "External LCD controller support"
+ depends on FB_OMAP
+ help
+ Say Y here, if you want to have support for boards with an
+ external LCD controller connected to the SoSSI/RFBI interface.
+
+config FB_OMAP_LCDC_HWA742
+ bool "Epson HWA742 LCD controller support"
+ depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+ help
+ Say Y here if you want to have support for the external
+ Epson HWA742 LCD controller.
+
+config FB_OMAP_LCDC_BLIZZARD
+ bool "Epson Blizzard LCD controller support"
+ depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+ help
+ Say Y here if you want to have support for the external
+ Epson Blizzard LCD controller.
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
new file mode 100644
index 000000000000..99da8b6d2c36
--- /dev/null
+++ b/drivers/video/omap/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for the new OMAP framebuffer device driver
+#
+
+obj-$(CONFIG_FB_OMAP) += omapfb.o
+
+objs-yy := omapfb_main.o
+
+objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o
+objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
+
+objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
+objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
+
+objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
+objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
+
+objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
+objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
+objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
+objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
+objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
+objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o
+
+omapfb-objs := $(objs-yy)
+
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
new file mode 100644
index 000000000000..e682940a97a4
--- /dev/null
+++ b/drivers/video/omap/blizzard.c
@@ -0,0 +1,1568 @@
+/*
+ * Epson Blizzard LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors: Juha Yrjola <juha.yrjola@nokia.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * YUV support: Jussi Laako <jussi.laako@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/blizzard.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME "blizzard"
+
+#define BLIZZARD_REV_CODE 0x00
+#define BLIZZARD_CONFIG 0x02
+#define BLIZZARD_PLL_DIV 0x04
+#define BLIZZARD_PLL_LOCK_RANGE 0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
+#define BLIZZARD_PLL_MODE 0x0c
+#define BLIZZARD_CLK_SRC 0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
+#define BLIZZARD_MEM_BANK0_STATUS 0x14
+#define BLIZZARD_HDISP 0x2a
+#define BLIZZARD_HNDP 0x2c
+#define BLIZZARD_VDISP0 0x2e
+#define BLIZZARD_VDISP1 0x30
+#define BLIZZARD_VNDP 0x32
+#define BLIZZARD_HSW 0x34
+#define BLIZZARD_VSW 0x38
+#define BLIZZARD_DISPLAY_MODE 0x68
+#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
+#define BLIZZARD_POWER_SAVE 0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD 0x00
+#define BLIZZARD_SRC_BLT_LCD 0x06
+
+#define BLIZZARD_COLOR_RGB565 0x01
+#define BLIZZARD_COLOR_YUV420 0x09
+
+#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
+
+#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE 24
+#define IRQ_REQ_POOL_SIZE 4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE 0
+#define REQ_PENDING 1
+
+struct blizzard_reg_list {
+ int start;
+ int end;
+};
+
+/* These need to be saved / restored separately from the rest. */
+static struct blizzard_reg_list blizzard_pll_regs[] = {
+ {
+ .start = 0x04, /* Don't save PLL ctrl (0x0C) */
+ .end = 0x0a,
+ },
+ {
+ .start = 0x0e, /* Clock configuration */
+ .end = 0x0e,
+ },
+};
+
+static struct blizzard_reg_list blizzard_gen_regs[] = {
+ {
+ .start = 0x18, /* SDRAM control */
+ .end = 0x20,
+ },
+ {
+ .start = 0x28, /* LCD Panel configuration */
+ .end = 0x5a, /* HSSI interface, TV configuration */
+ },
+};
+
+static u8 blizzard_reg_cache[0x5a / 2];
+
+struct update_param {
+ int plane;
+ int x, y, width, height;
+ int out_x, out_y;
+ int out_width, out_height;
+ int color_mode;
+ int bpp;
+ int flags;
+};
+
+struct blizzard_request {
+ struct list_head entry;
+ unsigned int flags;
+
+ int (*handler)(struct blizzard_request *req);
+ void (*complete)(void *data);
+ void *complete_data;
+
+ union {
+ struct update_param update;
+ struct completion *sync;
+ } par;
+};
+
+struct plane_info {
+ unsigned long offset;
+ int pos_x, pos_y;
+ int width, height;
+ int out_width, out_height;
+ int scr_width;
+ int color_mode;
+ int bpp;
+};
+
+struct blizzard_struct {
+ enum omapfb_update_mode update_mode;
+ enum omapfb_update_mode update_mode_before_suspend;
+
+ struct timer_list auto_update_timer;
+ int stop_auto_update;
+ struct omapfb_update_window auto_update_window;
+ int enabled_planes;
+ int vid_nonstd_color;
+ int vid_scaled;
+ int last_color_mode;
+ int zoom_on;
+ int screen_width;
+ int screen_height;
+ unsigned te_connected:1;
+ unsigned vsync_only:1;
+
+ struct plane_info plane[OMAPFB_PLANE_NUM];
+
+ struct blizzard_request req_pool[REQ_POOL_SIZE];
+ struct list_head pending_req_list;
+ struct list_head free_req_list;
+ struct semaphore req_sema;
+ spinlock_t req_lock;
+
+ unsigned long sys_ck_rate;
+ struct extif_timings reg_timings, lut_timings;
+
+ u32 max_transmit_size;
+ u32 extif_clk_period;
+ int extif_clk_div;
+ unsigned long pix_tx_time;
+ unsigned long line_upd_time;
+
+ struct omapfb_device *fbdev;
+ struct lcd_ctrl_extif *extif;
+ struct lcd_ctrl *int_ctrl;
+
+ void (*power_up)(struct device *dev);
+ void (*power_down)(struct device *dev);
+
+ int version;
+} blizzard;
+
+struct lcd_ctrl blizzard_ctrl;
+
+static u8 blizzard_read_reg(u8 reg)
+{
+ u8 data;
+
+ blizzard.extif->set_bits_per_cycle(8);
+ blizzard.extif->write_command(&reg, 1);
+ blizzard.extif->read_data(&data, 1);
+
+ return data;
+}
+
+static void blizzard_write_reg(u8 reg, u8 val)
+{
+ blizzard.extif->set_bits_per_cycle(8);
+ blizzard.extif->write_command(&reg, 1);
+ blizzard.extif->write_data(&val, 1);
+}
+
+static void blizzard_restart_sdram(void)
+{
+ unsigned long tmo;
+
+ blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
+ udelay(50);
+ blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);
+ tmo = jiffies + msecs_to_jiffies(200);
+ while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
+ if (time_after(jiffies, tmo)) {
+ dev_err(blizzard.fbdev->dev,
+ "s1d1374x: SDRAM not ready");
+ break;
+ }
+ msleep(1);
+ }
+}
+
+static void blizzard_stop_sdram(void)
+{
+ blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
+}
+
+/* Wait until the last window was completely written into the controllers
+ * SDRAM and we can start transferring the next window.
+ */
+static void blizzard_wait_line_buffer(void)
+{
+ unsigned long tmo = jiffies + msecs_to_jiffies(30);
+
+ while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {
+ if (time_after(jiffies, tmo)) {
+ if (printk_ratelimit())
+ dev_err(blizzard.fbdev->dev,
+ "s1d1374x: line buffer not ready\n");
+ break;
+ }
+ }
+}
+
+/* Wait until the YYC color space converter is idle. */
+static void blizzard_wait_yyc(void)
+{
+ unsigned long tmo = jiffies + msecs_to_jiffies(30);
+
+ while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {
+ if (time_after(jiffies, tmo)) {
+ if (printk_ratelimit())
+ dev_err(blizzard.fbdev->dev,
+ "s1d1374x: YYC not ready\n");
+ break;
+ }
+ }
+}
+
+static void disable_overlay(void)
+{
+ blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,
+ BLIZZARD_SRC_DISABLE_OVERLAY);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end,
+ int x_out_start, int y_out_start,
+ int x_out_end, int y_out_end, int color_mode,
+ int zoom_off, int flags)
+{
+ u8 tmp[18];
+ u8 cmd;
+
+ x_end--;
+ y_end--;
+ tmp[0] = x_start;
+ tmp[1] = x_start >> 8;
+ tmp[2] = y_start;
+ tmp[3] = y_start >> 8;
+ tmp[4] = x_end;
+ tmp[5] = x_end >> 8;
+ tmp[6] = y_end;
+ tmp[7] = y_end >> 8;
+
+ x_out_end--;
+ y_out_end--;
+ tmp[8] = x_out_start;
+ tmp[9] = x_out_start >> 8;
+ tmp[10] = y_out_start;
+ tmp[11] = y_out_start >> 8;
+ tmp[12] = x_out_end;
+ tmp[13] = x_out_end >> 8;
+ tmp[14] = y_out_end;
+ tmp[15] = y_out_end >> 8;
+
+ tmp[16] = color_mode;
+ if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)
+ tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+ else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)
+ tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;
+ else
+ tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
+ BLIZZARD_SRC_WRITE_LCD :
+ BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+ blizzard.extif->set_bits_per_cycle(8);
+ cmd = BLIZZARD_INPUT_WIN_X_START_0;
+ blizzard.extif->write_command(&cmd, 1);
+ blizzard.extif->write_data(tmp, 18);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+ int out_height, int force_vsync)
+{
+ u8 b;
+
+ b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+ b |= 1 << 3;
+ blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+
+ if (likely(blizzard.vsync_only || force_vsync)) {
+ blizzard.extif->enable_tearsync(1, 0);
+ return;
+ }
+
+ if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {
+ blizzard.extif->enable_tearsync(1, 0);
+ return;
+ }
+
+ if ((width * blizzard.pix_tx_time / 1000) * height <
+ (y + out_height) * (blizzard.line_upd_time / 1000)) {
+ blizzard.extif->enable_tearsync(1, 0);
+ return;
+ }
+
+ blizzard.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+ u8 b;
+
+ blizzard.extif->enable_tearsync(0, 0);
+ b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+ b &= ~(1 << 3);
+ blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+ b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+}
+
+static inline void set_extif_timings(const struct extif_timings *t);
+
+static inline struct blizzard_request *alloc_req(void)
+{
+ unsigned long flags;
+ struct blizzard_request *req;
+ int req_flags = 0;
+
+ if (!in_interrupt())
+ down(&blizzard.req_sema);
+ else
+ req_flags = REQ_FROM_IRQ_POOL;
+
+ spin_lock_irqsave(&blizzard.req_lock, flags);
+ BUG_ON(list_empty(&blizzard.free_req_list));
+ req = list_entry(blizzard.free_req_list.next,
+ struct blizzard_request, entry);
+ list_del(&req->entry);
+ spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+ INIT_LIST_HEAD(&req->entry);
+ req->flags = req_flags;
+
+ return req;
+}
+
+static inline void free_req(struct blizzard_request *req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&blizzard.req_lock, flags);
+
+ list_del(&req->entry);
+ list_add(&req->entry, &blizzard.free_req_list);
+ if (!(req->flags & REQ_FROM_IRQ_POOL))
+ up(&blizzard.req_sema);
+
+ spin_unlock_irqrestore(&blizzard.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&blizzard.req_lock, flags);
+
+ while (!list_empty(&blizzard.pending_req_list)) {
+ struct blizzard_request *req;
+ void (*complete)(void *);
+ void *complete_data;
+
+ req = list_entry(blizzard.pending_req_list.next,
+ struct blizzard_request, entry);
+ spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+ if (req->handler(req) == REQ_PENDING)
+ return;
+
+ complete = req->complete;
+ complete_data = req->complete_data;
+ free_req(req);
+
+ if (complete)
+ complete(complete_data);
+
+ spin_lock_irqsave(&blizzard.req_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&blizzard.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+ unsigned long flags;
+ int process = 1;
+
+ spin_lock_irqsave(&blizzard.req_lock, flags);
+ if (likely(!list_empty(&blizzard.pending_req_list)))
+ process = 0;
+ list_splice_init(head, blizzard.pending_req_list.prev);
+ spin_unlock_irqrestore(&blizzard.req_lock, flags);
+
+ if (process)
+ process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+ struct blizzard_request *req = (struct blizzard_request *)data;
+ void (*complete)(void *);
+ void *complete_data;
+
+ complete = req->complete;
+ complete_data = req->complete_data;
+
+ free_req(req);
+
+ if (complete)
+ complete(complete_data);
+
+ process_pending_requests();
+}
+
+
+static int do_full_screen_update(struct blizzard_request *req)
+{
+ int i;
+ int flags;
+
+ for (i = 0; i < 3; i++) {
+ struct plane_info *p = &blizzard.plane[i];
+ if (!(blizzard.enabled_planes & (1 << i))) {
+ blizzard.int_ctrl->enable_plane(i, 0);
+ continue;
+ }
+ dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",
+ p->width, p->height);
+ blizzard.int_ctrl->setup_plane(i,
+ OMAPFB_CHANNEL_OUT_LCD, p->offset,
+ p->scr_width, p->pos_x, p->pos_y,
+ p->width, p->height,
+ p->color_mode);
+ blizzard.int_ctrl->enable_plane(i, 1);
+ }
+
+ dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",
+ blizzard.screen_width, blizzard.screen_height);
+ blizzard_wait_line_buffer();
+ flags = req->par.update.flags;
+ if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+ enable_tearsync(0, blizzard.screen_width,
+ blizzard.screen_height,
+ blizzard.screen_height,
+ blizzard.screen_height,
+ flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+ else
+ disable_tearsync();
+
+ set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,
+ 0, 0, blizzard.screen_width, blizzard.screen_height,
+ BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);
+ blizzard.zoom_on = 0;
+
+ blizzard.extif->set_bits_per_cycle(16);
+ /* set_window_regs has left the register index at the right
+ * place, so no need to set it here.
+ */
+ blizzard.extif->transfer_area(blizzard.screen_width,
+ blizzard.screen_height,
+ request_complete, req);
+ return REQ_PENDING;
+}
+
+/* Setup all planes with an overlapping area with the update window. */
+static int do_partial_update(struct blizzard_request *req, int plane,
+ int x, int y, int w, int h,
+ int x_out, int y_out, int w_out, int h_out,
+ int wnd_color_mode, int bpp)
+{
+ int i;
+ int gx1, gy1, gx2, gy2;
+ int gx1_out, gy1_out, gx2_out, gy2_out;
+ int color_mode;
+ int flags;
+ int zoom_off;
+
+ /* Global coordinates, relative to pixel 0,0 of the LCD */
+ gx1 = x + blizzard.plane[plane].pos_x;
+ gy1 = y + blizzard.plane[plane].pos_y;
+ gx2 = gx1 + w;
+ gy2 = gy1 + h;
+
+ flags = req->par.update.flags;
+ if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+ gx1_out = gx1;
+ gy1_out = gy1;
+ gx2_out = gx1 + w * 2;
+ gy2_out = gy1 + h * 2;
+ } else {
+ gx1_out = x_out + blizzard.plane[plane].pos_x;
+ gy1_out = y_out + blizzard.plane[plane].pos_y;
+ gx2_out = gx1_out + w_out;
+ gy2_out = gy1_out + h_out;
+ }
+ zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 &&
+ w == blizzard.screen_width && h == blizzard.screen_height;
+ blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) ||
+ (w < w_out || h < h_out);
+
+ for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
+ struct plane_info *p = &blizzard.plane[i];
+ int px1, py1;
+ int px2, py2;
+ int pw, ph;
+ int pposx, pposy;
+ unsigned long offset;
+
+ if (!(blizzard.enabled_planes & (1 << i)) ||
+ (wnd_color_mode && i != plane)) {
+ blizzard.int_ctrl->enable_plane(i, 0);
+ continue;
+ }
+ /* Plane coordinates */
+ if (i == plane) {
+ /* Plane in which we are doing the update.
+ * Local coordinates are the one in the update
+ * request.
+ */
+ px1 = x;
+ py1 = y;
+ px2 = x + w;
+ py2 = y + h;
+ pposx = 0;
+ pposy = 0;
+ } else {
+ /* Check if this plane has an overlapping part */
+ px1 = gx1 - p->pos_x;
+ py1 = gy1 - p->pos_y;
+ px2 = gx2 - p->pos_x;
+ py2 = gy2 - p->pos_y;
+ if (px1 >= p->width || py1 >= p->height ||
+ px2 <= 0 || py2 <= 0) {
+ blizzard.int_ctrl->enable_plane(i, 0);
+ continue;
+ }
+ /* Calculate the coordinates for the overlapping
+ * part in the plane's local coordinates.
+ */
+ pposx = -px1;
+ pposy = -py1;
+ if (px1 < 0)
+ px1 = 0;
+ if (py1 < 0)
+ py1 = 0;
+ if (px2 > p->width)
+ px2 = p->width;
+ if (py2 > p->height)
+ py2 = p->height;
+ if (pposx < 0)
+ pposx = 0;
+ if (pposy < 0)
+ pposy = 0;
+ }
+ pw = px2 - px1;
+ ph = py2 - py1;
+ offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8;
+ if (wnd_color_mode)
+ /* Window embedded in the plane with a differing
+ * color mode / bpp. Calculate the number of DMA
+ * transfer elements in terms of the plane's bpp.
+ */
+ pw = (pw + 1) * bpp / p->bpp;
+#ifdef VERBOSE
+ dev_dbg(blizzard.fbdev->dev,
+ "plane %d offset %#08lx pposx %d pposy %d "
+ "px1 %d py1 %d pw %d ph %d\n",
+ i, offset, pposx, pposy, px1, py1, pw, ph);
+#endif
+ blizzard.int_ctrl->setup_plane(i,
+ OMAPFB_CHANNEL_OUT_LCD, offset,
+ p->scr_width,
+ pposx, pposy, pw, ph,
+ p->color_mode);
+
+ blizzard.int_ctrl->enable_plane(i, 1);
+ }
+
+ switch (wnd_color_mode) {
+ case OMAPFB_COLOR_YUV420:
+ color_mode = BLIZZARD_COLOR_YUV420;
+ /* Currently only the 16 bits/pixel cycle format is
+ * supported on the external interface. Adjust the number
+ * of transfer elements per line for 12bpp format.
+ */
+ w = (w + 1) * 3 / 4;
+ break;
+ default:
+ color_mode = BLIZZARD_COLOR_RGB565;
+ break;
+ }
+
+ blizzard_wait_line_buffer();
+ if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420)
+ blizzard_wait_yyc();
+ blizzard.last_color_mode = color_mode;
+ if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+ enable_tearsync(gy1, w, h,
+ blizzard.screen_height,
+ h_out,
+ flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+ else
+ disable_tearsync();
+
+ set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
+ color_mode, zoom_off, flags);
+
+ blizzard.extif->set_bits_per_cycle(16);
+ /* set_window_regs has left the register index at the right
+ * place, so no need to set it here.
+ */
+ blizzard.extif->transfer_area(w, h, request_complete, req);
+
+ return REQ_PENDING;
+}
+
+static int send_frame_handler(struct blizzard_request *req)
+{
+ struct update_param *par = &req->par.update;
+ int plane = par->plane;
+
+#ifdef VERBOSE
+ dev_dbg(blizzard.fbdev->dev,
+ "send_frame: x %d y %d w %d h %d "
+ "x_out %d y_out %d w_out %d h_out %d "
+ "color_mode %04x flags %04x planes %01x\n",
+ par->x, par->y, par->width, par->height,
+ par->out_x, par->out_y, par->out_width, par->out_height,
+ par->color_mode, par->flags, blizzard.enabled_planes);
+#endif
+ if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY)
+ disable_overlay();
+
+ if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) ||
+ (blizzard.enabled_planes & blizzard.vid_scaled))
+ return do_full_screen_update(req);
+
+ return do_partial_update(req, plane, par->x, par->y,
+ par->width, par->height,
+ par->out_x, par->out_y,
+ par->out_width, par->out_height,
+ par->color_mode, par->bpp);
+}
+
+static void send_frame_complete(void *data)
+{
+}
+
+#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \
+ req = alloc_req(); \
+ req->handler = send_frame_handler; \
+ req->complete = send_frame_complete; \
+ req->par.update.plane = plane_idx; \
+ req->par.update.x = _x; \
+ req->par.update.y = _y; \
+ req->par.update.width = _w; \
+ req->par.update.height = _h; \
+ req->par.update.out_x = _x_out; \
+ req->par.update.out_y = _y_out; \
+ req->par.update.out_width = _w_out; \
+ req->par.update.out_height = _h_out; \
+ req->par.update.bpp = bpp; \
+ req->par.update.color_mode = color_mode;\
+ req->par.update.flags = flags; \
+ list_add_tail(&req->entry, req_head); \
+} while(0)
+
+static void create_req_list(int plane_idx,
+ struct omapfb_update_window *win,
+ struct list_head *req_head)
+{
+ struct blizzard_request *req;
+ int x = win->x;
+ int y = win->y;
+ int width = win->width;
+ int height = win->height;
+ int x_out = win->out_x;
+ int y_out = win->out_y;
+ int width_out = win->out_width;
+ int height_out = win->out_height;
+ int color_mode;
+ int bpp;
+ int flags;
+ unsigned int ystart = y;
+ unsigned int yspan = height;
+ unsigned int ystart_out = y_out;
+ unsigned int yspan_out = height_out;
+
+ flags = win->format & ~OMAPFB_FORMAT_MASK;
+ color_mode = win->format & OMAPFB_FORMAT_MASK;
+ switch (color_mode) {
+ case OMAPFB_COLOR_YUV420:
+ /* Embedded window with different color mode */
+ bpp = 12;
+ /* X, Y, height must be aligned at 2, width at 4 pixels */
+ x &= ~1;
+ y &= ~1;
+ height = yspan = height & ~1;
+ width = width & ~3;
+ break;
+ default:
+ /* Same as the plane color mode */
+ bpp = blizzard.plane[plane_idx].bpp;
+ break;
+ }
+ if (width * height * bpp / 8 > blizzard.max_transmit_size) {
+ yspan = blizzard.max_transmit_size / (width * bpp / 8);
+ yspan_out = yspan * height_out / height;
+ ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
+ width_out, yspan_out);
+ ystart += yspan;
+ ystart_out += yspan_out;
+ yspan = height - yspan;
+ yspan_out = height_out - yspan_out;
+ flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+ }
+
+ ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
+ width_out, yspan_out);
+}
+
+static void auto_update_complete(void *data)
+{
+ if (!blizzard.stop_auto_update)
+ mod_timer(&blizzard.auto_update_timer,
+ jiffies + BLIZZARD_AUTO_UPDATE_TIME);
+}
+
+static void blizzard_update_window_auto(unsigned long arg)
+{
+ LIST_HEAD(req_list);
+ struct blizzard_request *last;
+ struct omapfb_plane_struct *plane;
+
+ plane = blizzard.fbdev->fb_info[0]->par;
+ create_req_list(plane->idx,
+ &blizzard.auto_update_window, &req_list);
+ last = list_entry(req_list.prev, struct blizzard_request, entry);
+
+ last->complete = auto_update_complete;
+ last->complete_data = NULL;
+
+ submit_req_list(&req_list);
+}
+
+int blizzard_update_window_async(struct fb_info *fbi,
+ struct omapfb_update_window *win,
+ void (*complete_callback)(void *arg),
+ void *complete_callback_data)
+{
+ LIST_HEAD(req_list);
+ struct blizzard_request *last;
+ struct omapfb_plane_struct *plane = fbi->par;
+
+ if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE))
+ return -EINVAL;
+ if (unlikely(!blizzard.te_connected &&
+ (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC)))
+ return -EINVAL;
+
+ create_req_list(plane->idx, win, &req_list);
+ last = list_entry(req_list.prev, struct blizzard_request, entry);
+
+ last->complete = complete_callback;
+ last->complete_data = (void *)complete_callback_data;
+
+ submit_req_list(&req_list);
+
+ return 0;
+}
+EXPORT_SYMBOL(blizzard_update_window_async);
+
+static int update_full_screen(void)
+{
+ return blizzard_update_window_async(blizzard.fbdev->fb_info[0],
+ &blizzard.auto_update_window, NULL, NULL);
+
+}
+
+static int blizzard_setup_plane(int plane, int channel_out,
+ unsigned long offset, int screen_width,
+ int pos_x, int pos_y, int width, int height,
+ int color_mode)
+{
+ struct plane_info *p;
+
+#ifdef VERBOSE
+ dev_dbg(blizzard.fbdev->dev,
+ "plane %d ch_out %d offset %#08lx scr_width %d "
+ "pos_x %d pos_y %d width %d height %d color_mode %d\n",
+ plane, channel_out, offset, screen_width,
+ pos_x, pos_y, width, height, color_mode);
+#endif
+ if ((unsigned)plane > OMAPFB_PLANE_NUM)
+ return -EINVAL;
+ p = &blizzard.plane[plane];
+
+ switch (color_mode) {
+ case OMAPFB_COLOR_YUV422:
+ case OMAPFB_COLOR_YUY422:
+ p->bpp = 16;
+ blizzard.vid_nonstd_color &= ~(1 << plane);
+ break;
+ case OMAPFB_COLOR_YUV420:
+ p->bpp = 12;
+ blizzard.vid_nonstd_color |= 1 << plane;
+ break;
+ case OMAPFB_COLOR_RGB565:
+ p->bpp = 16;
+ blizzard.vid_nonstd_color &= ~(1 << plane);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ p->offset = offset;
+ p->pos_x = pos_x;
+ p->pos_y = pos_y;
+ p->width = width;
+ p->height = height;
+ p->scr_width = screen_width;
+ if (!p->out_width)
+ p->out_width = width;
+ if (!p->out_height)
+ p->out_height = height;
+
+ p->color_mode = color_mode;
+
+ return 0;
+}
+
+static int blizzard_set_scale(int plane, int orig_w, int orig_h,
+ int out_w, int out_h)
+{
+ struct plane_info *p = &blizzard.plane[plane];
+ int r;
+
+ dev_dbg(blizzard.fbdev->dev,
+ "plane %d orig_w %d orig_h %d out_w %d out_h %d\n",
+ plane, orig_w, orig_h, out_w, out_h);
+ if ((unsigned)plane > OMAPFB_PLANE_NUM)
+ return -ENODEV;
+
+ r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h);
+ if (r < 0)
+ return r;
+
+ p->width = orig_w;
+ p->height = orig_h;
+ p->out_width = out_w;
+ p->out_height = out_h;
+ if (orig_w == out_w && orig_h == out_h)
+ blizzard.vid_scaled &= ~(1 << plane);
+ else
+ blizzard.vid_scaled |= 1 << plane;
+
+ return 0;
+}
+
+static int blizzard_enable_plane(int plane, int enable)
+{
+ if (enable)
+ blizzard.enabled_planes |= 1 << plane;
+ else
+ blizzard.enabled_planes &= ~(1 << plane);
+
+ return 0;
+}
+
+static int sync_handler(struct blizzard_request *req)
+{
+ complete(req->par.sync);
+ return REQ_COMPLETE;
+}
+
+static void blizzard_sync(void)
+{
+ LIST_HEAD(req_list);
+ struct blizzard_request *req;
+ struct completion comp;
+
+ req = alloc_req();
+
+ req->handler = sync_handler;
+ req->complete = NULL;
+ init_completion(&comp);
+ req->par.sync = &comp;
+
+ list_add(&req->entry, &req_list);
+ submit_req_list(&req_list);
+
+ wait_for_completion(&comp);
+}
+
+
+static void blizzard_bind_client(struct omapfb_notifier_block *nb)
+{
+ if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) {
+ omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
+ }
+}
+
+static int blizzard_set_update_mode(enum omapfb_update_mode mode)
+{
+ if (unlikely(mode != OMAPFB_MANUAL_UPDATE &&
+ mode != OMAPFB_AUTO_UPDATE &&
+ mode != OMAPFB_UPDATE_DISABLED))
+ return -EINVAL;
+
+ if (mode == blizzard.update_mode)
+ return 0;
+
+ dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n",
+ mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+ (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+ switch (blizzard.update_mode) {
+ case OMAPFB_MANUAL_UPDATE:
+ omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED);
+ break;
+ case OMAPFB_AUTO_UPDATE:
+ blizzard.stop_auto_update = 1;
+ del_timer_sync(&blizzard.auto_update_timer);
+ break;
+ case OMAPFB_UPDATE_DISABLED:
+ break;
+ }
+
+ blizzard.update_mode = mode;
+ blizzard_sync();
+ blizzard.stop_auto_update = 0;
+
+ switch (mode) {
+ case OMAPFB_MANUAL_UPDATE:
+ omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
+ break;
+ case OMAPFB_AUTO_UPDATE:
+ blizzard_update_window_auto(0);
+ break;
+ case OMAPFB_UPDATE_DISABLED:
+ break;
+ }
+
+ return 0;
+}
+
+static enum omapfb_update_mode blizzard_get_update_mode(void)
+{
+ return blizzard.update_mode;
+}
+
+static inline void set_extif_timings(const struct extif_timings *t)
+{
+ blizzard.extif->set_timings(t);
+}
+
+static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+ int bus_tick = blizzard.extif_clk_period * div;
+ return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+ struct extif_timings *t;
+ unsigned long systim;
+
+ /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+ * AccessTime 2 ns + 12.2 ns (regs),
+ * WEOffTime = WEOnTime + 1 ns,
+ * REOffTime = REOnTime + 12 ns (regs),
+ * CSOffTime = REOffTime + 1 ns
+ * ReadCycle = 2ns + 2*SYSCLK (regs),
+ * WriteCycle = 2*SYSCLK + 2 ns,
+ * CSPulseWidth = 10 ns */
+
+ systim = 1000000000 / (sysclk / 1000);
+ dev_dbg(blizzard.fbdev->dev,
+ "Blizzard systim %lu ps extif_clk_period %u div %d\n",
+ systim, blizzard.extif_clk_period, div);
+
+ t = &blizzard.reg_timings;
+ memset(t, 0, sizeof(*t));
+
+ t->clk_div = div;
+
+ t->cs_on_time = 0;
+ t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+ t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+ t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div);
+ t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+ t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+ if (t->we_cycle_time < t->we_off_time)
+ t->we_cycle_time = t->we_off_time;
+ t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+ if (t->re_cycle_time < t->re_off_time)
+ t->re_cycle_time = t->re_off_time;
+ t->cs_pulse_width = 0;
+
+ dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+ dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+ t->we_on_time, t->we_off_time, t->re_cycle_time,
+ t->we_cycle_time);
+ dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+ t->access_time, t->cs_pulse_width);
+
+ return blizzard.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+ struct extif_timings *t;
+ unsigned long systim;
+
+ /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+ * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+ * WEOffTime = WEOnTime + 1 ns,
+ * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+ * CSOffTime = REOffTime + 1 ns
+ * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+ * WriteCycle = 2*SYSCLK + 2 ns,
+ * CSPulseWidth = 10 ns */
+
+ systim = 1000000000 / (sysclk / 1000);
+ dev_dbg(blizzard.fbdev->dev,
+ "Blizzard systim %lu ps extif_clk_period %u div %d\n",
+ systim, blizzard.extif_clk_period, div);
+
+ t = &blizzard.lut_timings;
+ memset(t, 0, sizeof(*t));
+
+ t->clk_div = div;
+
+ t->cs_on_time = 0;
+ t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+ 26000, div);
+ t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+ t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+ 26000, div);
+ t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+ t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+ if (t->we_cycle_time < t->we_off_time)
+ t->we_cycle_time = t->we_off_time;
+ t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+ if (t->re_cycle_time < t->re_off_time)
+ t->re_cycle_time = t->re_off_time;
+ t->cs_pulse_width = 0;
+
+ dev_dbg(blizzard.fbdev->dev,
+ "[lut]cson %d csoff %d reon %d reoff %d\n",
+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+ dev_dbg(blizzard.fbdev->dev,
+ "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+ t->we_on_time, t->we_off_time, t->re_cycle_time,
+ t->we_cycle_time);
+ dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+ t->access_time, t->cs_pulse_width);
+
+ return blizzard.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+ int max_clk_div;
+ int div;
+
+ blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div);
+ for (div = 1; div <= max_clk_div; div++) {
+ if (calc_reg_timing(sysclk, div) == 0)
+ break;
+ }
+ if (div > max_clk_div) {
+ dev_dbg(blizzard.fbdev->dev, "reg timing failed\n");
+ goto err;
+ }
+ *extif_mem_div = div;
+
+ for (div = 1; div <= max_clk_div; div++) {
+ if (calc_lut_timing(sysclk, div) == 0)
+ break;
+ }
+
+ if (div > max_clk_div)
+ goto err;
+
+ blizzard.extif_clk_div = div;
+
+ return 0;
+err:
+ dev_err(blizzard.fbdev->dev, "can't setup timings\n");
+ return -1;
+}
+
+static void calc_blizzard_clk_rates(unsigned long ext_clk,
+ unsigned long *sys_clk, unsigned long *pix_clk)
+{
+ int pix_clk_src;
+ int sys_div = 0, sys_mul = 0;
+ int pix_div;
+
+ pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC);
+ pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+ if ((pix_clk_src & (0x3 << 1)) == 0) {
+ /* Source is the PLL */
+ sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1;
+ sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0);
+ sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1)
+ & 0x0f) << 11);
+ *sys_clk = ext_clk * sys_mul / sys_div;
+ } else /* else source is ext clk, or oscillator */
+ *sys_clk = ext_clk;
+
+ *pix_clk = *sys_clk / pix_div; /* HZ */
+ dev_dbg(blizzard.fbdev->dev,
+ "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+ ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+ dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+ *sys_clk, *pix_clk);
+}
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+ int hdisp, vdisp;
+ int hndp, vndp;
+ int hsw, vsw;
+ int hs, vs;
+ int hs_pol_inv, vs_pol_inv;
+ int use_hsvs, use_ndp;
+ u8 b;
+
+ hsw = blizzard_read_reg(BLIZZARD_HSW);
+ vsw = blizzard_read_reg(BLIZZARD_VSW);
+ hs_pol_inv = !(hsw & 0x80);
+ vs_pol_inv = !(vsw & 0x80);
+ hsw = hsw & 0x7f;
+ vsw = vsw & 0x3f;
+
+ hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8;
+ vdisp = blizzard_read_reg(BLIZZARD_VDISP0) +
+ ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8);
+
+ hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f;
+ vndp = blizzard_read_reg(BLIZZARD_VNDP);
+
+ /* time to transfer one pixel (16bpp) in ps */
+ blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time;
+ if (blizzard.extif->get_max_tx_rate != NULL) {
+ /* The external interface might have a rate limitation,
+ * if so, we have to maximize our transfer rate.
+ */
+ unsigned long min_tx_time;
+ unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate();
+
+ dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n",
+ max_tx_rate);
+ min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */
+ if (blizzard.pix_tx_time < min_tx_time)
+ blizzard.pix_tx_time = min_tx_time;
+ }
+
+ /* time to update one line in ps */
+ blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+ blizzard.line_upd_time *= 1000;
+ if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time)
+ /* transfer speed too low, we might have to use both
+ * HS and VS */
+ use_hsvs = 1;
+ else
+ /* decent transfer speed, we'll always use only VS */
+ use_hsvs = 0;
+
+ if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+ /* HS or'ed with VS doesn't work, use the active high
+ * TE signal based on HNDP / VNDP */
+ use_ndp = 1;
+ hs_pol_inv = 0;
+ vs_pol_inv = 0;
+ hs = hndp;
+ vs = vndp;
+ } else {
+ /* Use HS or'ed with VS as a TE signal if both are needed
+ * or VNDP if only vsync is needed. */
+ use_ndp = 0;
+ hs = hsw;
+ vs = vsw;
+ if (!use_hsvs) {
+ hs_pol_inv = 0;
+ vs_pol_inv = 0;
+ }
+ }
+
+ hs = hs * 1000000 / (pix_clk / 1000); /* ps */
+ hs *= 1000;
+
+ vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
+ vs *= 1000;
+
+ if (vs <= hs)
+ return -EDOM;
+ /* set VS to 120% of HS to minimize VS detection time */
+ vs = hs * 12 / 10;
+ /* minimize HS too */
+ if (hs > 10000)
+ hs = 10000;
+
+ b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
+ b &= ~0x3;
+ b |= use_hsvs ? 1 : 0;
+ b |= (use_ndp && use_hsvs) ? 0 : 2;
+ blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
+
+ blizzard.vsync_only = !use_hsvs;
+
+ dev_dbg(blizzard.fbdev->dev,
+ "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+ pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time);
+ dev_dbg(blizzard.fbdev->dev,
+ "hs %d ps vs %d ps mode %d vsync_only %d\n",
+ hs, vs, b & 0x3, !use_hsvs);
+
+ return blizzard.extif->setup_tearsync(1, hs, vs,
+ hs_pol_inv, vs_pol_inv,
+ extif_div);
+}
+
+static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
+{
+ blizzard.int_ctrl->get_caps(plane, caps);
+ caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
+ OMAPFB_CAPS_WINDOW_SCALE |
+ OMAPFB_CAPS_WINDOW_OVERLAY;
+ if (blizzard.te_connected)
+ caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+ caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+ (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void _save_regs(struct blizzard_reg_list *list, int cnt)
+{
+ int i;
+
+ for (i = 0; i < cnt; i++, list++) {
+ int reg;
+ for (reg = list->start; reg <= list->end; reg += 2)
+ blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg);
+ }
+}
+
+static void _restore_regs(struct blizzard_reg_list *list, int cnt)
+{
+ int i;
+
+ for (i = 0; i < cnt; i++, list++) {
+ int reg;
+ for (reg = list->start; reg <= list->end; reg += 2)
+ blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]);
+ }
+}
+
+static void blizzard_save_all_regs(void)
+{
+ _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
+ _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
+}
+
+static void blizzard_restore_pll_regs(void)
+{
+ _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
+}
+
+static void blizzard_restore_gen_regs(void)
+{
+ _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
+}
+
+static void blizzard_suspend(void)
+{
+ u32 l;
+ unsigned long tmo;
+
+ if (blizzard.last_color_mode) {
+ update_full_screen();
+ blizzard_sync();
+ }
+ blizzard.update_mode_before_suspend = blizzard.update_mode;
+ /* the following will disable clocks as well */
+ blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
+
+ blizzard_save_all_regs();
+
+ blizzard_stop_sdram();
+
+ l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
+ /* Standby, Sleep. We assume we use an external clock. */
+ l |= 0x03;
+ blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
+
+ tmo = jiffies + msecs_to_jiffies(100);
+ while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) {
+ if (time_after(jiffies, tmo)) {
+ dev_err(blizzard.fbdev->dev,
+ "s1d1374x: sleep timeout, stopping PLL manually\n");
+ l = blizzard_read_reg(BLIZZARD_PLL_MODE);
+ l &= ~0x03;
+ /* Disable PLL, counter function */
+ l |= 0x2;
+ blizzard_write_reg(BLIZZARD_PLL_MODE, l);
+ break;
+ }
+ msleep(1);
+ }
+
+ if (blizzard.power_down != NULL)
+ blizzard.power_down(blizzard.fbdev->dev);
+}
+
+static void blizzard_resume(void)
+{
+ u32 l;
+
+ if (blizzard.power_up != NULL)
+ blizzard.power_up(blizzard.fbdev->dev);
+
+ l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
+ /* Standby, Sleep */
+ l &= ~0x03;
+ blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
+
+ blizzard_restore_pll_regs();
+ l = blizzard_read_reg(BLIZZARD_PLL_MODE);
+ l &= ~0x03;
+ /* Enable PLL, counter function */
+ l |= 0x1;
+ blizzard_write_reg(BLIZZARD_PLL_MODE, l);
+
+ while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7)))
+ msleep(1);
+
+ blizzard_restart_sdram();
+
+ blizzard_restore_gen_regs();
+
+ /* Enable display */
+ blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01);
+
+ /* the following will enable clocks as necessary */
+ blizzard_set_update_mode(blizzard.update_mode_before_suspend);
+
+ /* Force a background update */
+ blizzard.zoom_on = 1;
+ update_full_screen();
+ blizzard_sync();
+}
+
+static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
+ struct omapfb_mem_desc *req_vram)
+{
+ int r = 0, i;
+ u8 rev, conf;
+ unsigned long ext_clk;
+ int extif_div;
+ unsigned long sys_clk, pix_clk;
+ struct omapfb_platform_data *omapfb_conf;
+ struct blizzard_platform_data *ctrl_conf;
+
+ blizzard.fbdev = fbdev;
+
+ BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+ blizzard.fbdev = fbdev;
+ blizzard.extif = fbdev->ext_if;
+ blizzard.int_ctrl = fbdev->int_ctrl;
+
+ omapfb_conf = fbdev->dev->platform_data;
+ ctrl_conf = omapfb_conf->ctrl_platform_data;
+ if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
+ dev_err(fbdev->dev, "s1d1374x: missing platform data\n");
+ r = -ENOENT;
+ goto err1;
+ }
+
+ blizzard.power_down = ctrl_conf->power_down;
+ blizzard.power_up = ctrl_conf->power_up;
+
+ spin_lock_init(&blizzard.req_lock);
+
+ if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+ goto err1;
+
+ if ((r = blizzard.extif->init(fbdev)) < 0)
+ goto err2;
+
+ blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key;
+ blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key;
+ blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem;
+ blizzard_ctrl.mmap = blizzard.int_ctrl->mmap;
+
+ ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
+ if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0)
+ goto err3;
+
+ set_extif_timings(&blizzard.reg_timings);
+
+ if (blizzard.power_up != NULL)
+ blizzard.power_up(fbdev->dev);
+
+ calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk);
+
+ if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0)
+ goto err3;
+ set_extif_timings(&blizzard.reg_timings);
+
+ if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) {
+ dev_err(fbdev->dev,
+ "controller not initialized by the bootloader\n");
+ r = -ENODEV;
+ goto err3;
+ }
+
+ if (ctrl_conf->te_connected) {
+ if ((r = setup_tearsync(pix_clk, extif_div)) < 0)
+ goto err3;
+ blizzard.te_connected = 1;
+ }
+
+ rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+ conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+ switch (rev & 0xfc) {
+ case 0x9c:
+ blizzard.version = BLIZZARD_VERSION_S1D13744;
+ pr_info("omapfb: s1d13744 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+ break;
+ case 0xa4:
+ blizzard.version = BLIZZARD_VERSION_S1D13745;
+ pr_info("omapfb: s1d13745 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+ break;
+ default:
+ dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n",
+ rev);
+ r = -ENODEV;
+ goto err3;
+ }
+
+ blizzard.max_transmit_size = blizzard.extif->max_transmit_size;
+
+ blizzard.update_mode = OMAPFB_UPDATE_DISABLED;
+
+ blizzard.auto_update_window.x = 0;
+ blizzard.auto_update_window.y = 0;
+ blizzard.auto_update_window.width = fbdev->panel->x_res;
+ blizzard.auto_update_window.height = fbdev->panel->y_res;
+ blizzard.auto_update_window.out_x = 0;
+ blizzard.auto_update_window.out_x = 0;
+ blizzard.auto_update_window.out_width = fbdev->panel->x_res;
+ blizzard.auto_update_window.out_height = fbdev->panel->y_res;
+ blizzard.auto_update_window.format = 0;
+
+ blizzard.screen_width = fbdev->panel->x_res;
+ blizzard.screen_height = fbdev->panel->y_res;
+
+ init_timer(&blizzard.auto_update_timer);
+ blizzard.auto_update_timer.function = blizzard_update_window_auto;
+ blizzard.auto_update_timer.data = 0;
+
+ INIT_LIST_HEAD(&blizzard.free_req_list);
+ INIT_LIST_HEAD(&blizzard.pending_req_list);
+ for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++)
+ list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list);
+ BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+ sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+ return 0;
+err3:
+ if (blizzard.power_down != NULL)
+ blizzard.power_down(fbdev->dev);
+ blizzard.extif->cleanup();
+err2:
+ blizzard.int_ctrl->cleanup();
+err1:
+ return r;
+}
+
+static void blizzard_cleanup(void)
+{
+ blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
+ blizzard.extif->cleanup();
+ blizzard.int_ctrl->cleanup();
+ if (blizzard.power_down != NULL)
+ blizzard.power_down(blizzard.fbdev->dev);
+}
+
+struct lcd_ctrl blizzard_ctrl = {
+ .name = "blizzard",
+ .init = blizzard_init,
+ .cleanup = blizzard_cleanup,
+ .bind_client = blizzard_bind_client,
+ .get_caps = blizzard_get_caps,
+ .set_update_mode = blizzard_set_update_mode,
+ .get_update_mode = blizzard_get_update_mode,
+ .setup_plane = blizzard_setup_plane,
+ .set_scale = blizzard_set_scale,
+ .enable_plane = blizzard_enable_plane,
+ .update_window = blizzard_update_window_async,
+ .sync = blizzard_sync,
+ .suspend = blizzard_suspend,
+ .resume = blizzard_resume,
+};
+
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
new file mode 100644
index 000000000000..f4c23434de6f
--- /dev/null
+++ b/drivers/video/omap/dispc.c
@@ -0,0 +1,1502 @@
+/*
+ * OMAP2 display controller support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/board.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME "dispc"
+
+#define DSS_BASE 0x48050000
+#define DSS_SYSCONFIG 0x0010
+
+#define DISPC_BASE 0x48050400
+
+/* DISPC common */
+#define DISPC_REVISION 0x0000
+#define DISPC_SYSCONFIG 0x0010
+#define DISPC_SYSSTATUS 0x0014
+#define DISPC_IRQSTATUS 0x0018
+#define DISPC_IRQENABLE 0x001C
+#define DISPC_CONTROL 0x0040
+#define DISPC_CONFIG 0x0044
+#define DISPC_CAPABLE 0x0048
+#define DISPC_DEFAULT_COLOR0 0x004C
+#define DISPC_DEFAULT_COLOR1 0x0050
+#define DISPC_TRANS_COLOR0 0x0054
+#define DISPC_TRANS_COLOR1 0x0058
+#define DISPC_LINE_STATUS 0x005C
+#define DISPC_LINE_NUMBER 0x0060
+#define DISPC_TIMING_H 0x0064
+#define DISPC_TIMING_V 0x0068
+#define DISPC_POL_FREQ 0x006C
+#define DISPC_DIVISOR 0x0070
+#define DISPC_SIZE_DIG 0x0078
+#define DISPC_SIZE_LCD 0x007C
+
+#define DISPC_DATA_CYCLE1 0x01D4
+#define DISPC_DATA_CYCLE2 0x01D8
+#define DISPC_DATA_CYCLE3 0x01DC
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0 0x0080
+#define DISPC_GFX_BA1 0x0084
+#define DISPC_GFX_POSITION 0x0088
+#define DISPC_GFX_SIZE 0x008C
+#define DISPC_GFX_ATTRIBUTES 0x00A0
+#define DISPC_GFX_FIFO_THRESHOLD 0x00A4
+#define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8
+#define DISPC_GFX_ROW_INC 0x00AC
+#define DISPC_GFX_PIXEL_INC 0x00B0
+#define DISPC_GFX_WINDOW_SKIP 0x00B4
+#define DISPC_GFX_TABLE_BA 0x00B8
+
+/* DISPC Video plane 1/2 */
+#define DISPC_VID1_BASE 0x00BC
+#define DISPC_VID2_BASE 0x014C
+
+/* Offsets into DISPC_VID1/2_BASE */
+#define DISPC_VID_BA0 0x0000
+#define DISPC_VID_BA1 0x0004
+#define DISPC_VID_POSITION 0x0008
+#define DISPC_VID_SIZE 0x000C
+#define DISPC_VID_ATTRIBUTES 0x0010
+#define DISPC_VID_FIFO_THRESHOLD 0x0014
+#define DISPC_VID_FIFO_SIZE_STATUS 0x0018
+#define DISPC_VID_ROW_INC 0x001C
+#define DISPC_VID_PIXEL_INC 0x0020
+#define DISPC_VID_FIR 0x0024
+#define DISPC_VID_PICTURE_SIZE 0x0028
+#define DISPC_VID_ACCU0 0x002C
+#define DISPC_VID_ACCU1 0x0030
+
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_H0 0x0034
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_HV0 0x0038
+/* 5 elements in 4 byte increments */
+#define DISPC_VID_CONV_COEF0 0x0074
+
+#define DISPC_IRQ_FRAMEMASK 0x0001
+#define DISPC_IRQ_VSYNC 0x0002
+#define DISPC_IRQ_EVSYNC_EVEN 0x0004
+#define DISPC_IRQ_EVSYNC_ODD 0x0008
+#define DISPC_IRQ_ACBIAS_COUNT_STAT 0x0010
+#define DISPC_IRQ_PROG_LINE_NUM 0x0020
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW 0x0040
+#define DISPC_IRQ_GFX_END_WIN 0x0080
+#define DISPC_IRQ_PAL_GAMMA_MASK 0x0100
+#define DISPC_IRQ_OCP_ERR 0x0200
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW 0x0400
+#define DISPC_IRQ_VID1_END_WIN 0x0800
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW 0x1000
+#define DISPC_IRQ_VID2_END_WIN 0x2000
+#define DISPC_IRQ_SYNC_LOST 0x4000
+
+#define DISPC_IRQ_MASK_ALL 0x7fff
+
+#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+ DISPC_IRQ_SYNC_LOST)
+
+#define RFBI_CONTROL 0x48050040
+
+#define MAX_PALETTE_SIZE (256 * 16)
+
+#define FLD_MASK(pos, len) (((1 << len) - 1) << pos)
+
+#define MOD_REG_FLD(reg, mask, val) \
+ dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
+
+#define OMAP2_SRAM_START 0x40200000
+/* Maximum size, in reality this is smaller if SRAM is partially locked. */
+#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
+
+/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
+#define DISPC_MEMTYPE_NUM 2
+
+#define RESMAP_SIZE(_page_cnt) \
+ ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
+#define RESMAP_PTR(_res_map, _page_nr) \
+ (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
+#define RESMAP_MASK(_page_nr) \
+ (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
+
+struct resmap {
+ unsigned long start;
+ unsigned page_cnt;
+ unsigned long *map;
+};
+
+static struct {
+ u32 base;
+
+ struct omapfb_mem_desc mem_desc;
+ struct resmap *res_map[DISPC_MEMTYPE_NUM];
+ atomic_t map_count[OMAPFB_PLANE_NUM];
+
+ dma_addr_t palette_paddr;
+ void *palette_vaddr;
+
+ int ext_mode;
+
+ unsigned long enabled_irqs;
+ void (*irq_callback)(void *);
+ void *irq_callback_data;
+ struct completion frame_done;
+
+ int fir_hinc[OMAPFB_PLANE_NUM];
+ int fir_vinc[OMAPFB_PLANE_NUM];
+
+ struct clk *dss_ick, *dss1_fck;
+ struct clk *dss_54m_fck;
+
+ enum omapfb_update_mode update_mode;
+ struct omapfb_device *fbdev;
+
+ struct omapfb_color_key color_key;
+} dispc;
+
+static void enable_lcd_clocks(int enable);
+
+static void inline dispc_write_reg(int idx, u32 val)
+{
+ __raw_writel(val, dispc.base + idx);
+}
+
+static u32 inline dispc_read_reg(int idx)
+{
+ u32 l = __raw_readl(dispc.base + idx);
+ return l;
+}
+
+/* Select RFBI or bypass mode */
+static void enable_rfbi_mode(int enable)
+{
+ u32 l;
+
+ l = dispc_read_reg(DISPC_CONTROL);
+ /* Enable RFBI, GPIO0/1 */
+ l &= ~((1 << 11) | (1 << 15) | (1 << 16));
+ l |= enable ? (1 << 11) : 0;
+ /* RFBI En: GPIO0/1=10 RFBI Dis: GPIO0/1=11 */
+ l |= 1 << 15;
+ l |= enable ? 0 : (1 << 16);
+ dispc_write_reg(DISPC_CONTROL, l);
+
+ /* Set bypass mode in RFBI module */
+ l = __raw_readl(io_p2v(RFBI_CONTROL));
+ l |= enable ? 0 : (1 << 1);
+ __raw_writel(l, io_p2v(RFBI_CONTROL));
+}
+
+static void set_lcd_data_lines(int data_lines)
+{
+ u32 l;
+ int code = 0;
+
+ switch (data_lines) {
+ case 12:
+ code = 0;
+ break;
+ case 16:
+ code = 1;
+ break;
+ case 18:
+ code = 2;
+ break;
+ case 24:
+ code = 3;
+ break;
+ default:
+ BUG();
+ }
+
+ l = dispc_read_reg(DISPC_CONTROL);
+ l &= ~(0x03 << 8);
+ l |= code << 8;
+ dispc_write_reg(DISPC_CONTROL, l);
+}
+
+static void set_load_mode(int mode)
+{
+ BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
+ DISPC_LOAD_CLUT_ONCE_FRAME));
+ MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
+}
+
+void omap_dispc_set_lcd_size(int x, int y)
+{
+ BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+ enable_lcd_clocks(1);
+ MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+ ((y - 1) << 16) | (x - 1));
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_set_lcd_size);
+
+void omap_dispc_set_digit_size(int x, int y)
+{
+ BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+ enable_lcd_clocks(1);
+ MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+ ((y - 1) << 16) | (x - 1));
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_set_digit_size);
+
+static void setup_plane_fifo(int plane, int ext_mode)
+{
+ const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+ DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
+ DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
+ const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+ DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
+ DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
+ int low, high;
+ u32 l;
+
+ BUG_ON(plane > 2);
+
+ l = dispc_read_reg(fsz_reg[plane]);
+ l &= FLD_MASK(0, 9);
+ if (ext_mode) {
+ low = l * 3 / 4;
+ high = l;
+ } else {
+ low = l / 4;
+ high = l * 3 / 4;
+ }
+ MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),
+ (high << 16) | low);
+}
+
+void omap_dispc_enable_lcd_out(int enable)
+{
+ enable_lcd_clocks(1);
+ MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
+
+void omap_dispc_enable_digit_out(int enable)
+{
+ enable_lcd_clocks(1);
+ MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_digit_out);
+
+static inline int _setup_plane(int plane, int channel_out,
+ u32 paddr, int screen_width,
+ int pos_x, int pos_y, int width, int height,
+ int color_mode)
+{
+ const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+ DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+ DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+ const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
+ DISPC_VID2_BASE + DISPC_VID_BA0 };
+ const u32 ps_reg[] = { DISPC_GFX_POSITION,
+ DISPC_VID1_BASE + DISPC_VID_POSITION,
+ DISPC_VID2_BASE + DISPC_VID_POSITION };
+ const u32 sz_reg[] = { DISPC_GFX_SIZE,
+ DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
+ DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
+ const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
+ DISPC_VID1_BASE + DISPC_VID_ROW_INC,
+ DISPC_VID2_BASE + DISPC_VID_ROW_INC };
+ const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+ DISPC_VID2_BASE + DISPC_VID_SIZE };
+
+ int chout_shift, burst_shift;
+ int chout_val;
+ int color_code;
+ int bpp;
+ int cconv_en;
+ int set_vsize;
+ u32 l;
+
+#ifdef VERBOSE
+ dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d"
+ " pos_x %d pos_y %d width %d height %d color_mode %d\n",
+ plane, channel_out, paddr, screen_width, pos_x, pos_y,
+ width, height, color_mode);
+#endif
+
+ set_vsize = 0;
+ switch (plane) {
+ case OMAPFB_PLANE_GFX:
+ burst_shift = 6;
+ chout_shift = 8;
+ break;
+ case OMAPFB_PLANE_VID1:
+ case OMAPFB_PLANE_VID2:
+ burst_shift = 14;
+ chout_shift = 16;
+ set_vsize = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (channel_out) {
+ case OMAPFB_CHANNEL_OUT_LCD:
+ chout_val = 0;
+ break;
+ case OMAPFB_CHANNEL_OUT_DIGIT:
+ chout_val = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cconv_en = 0;
+ switch (color_mode) {
+ case OMAPFB_COLOR_RGB565:
+ color_code = DISPC_RGB_16_BPP;
+ bpp = 16;
+ break;
+ case OMAPFB_COLOR_YUV422:
+ if (plane == 0)
+ return -EINVAL;
+ color_code = DISPC_UYVY_422;
+ cconv_en = 1;
+ bpp = 16;
+ break;
+ case OMAPFB_COLOR_YUY422:
+ if (plane == 0)
+ return -EINVAL;
+ color_code = DISPC_YUV2_422;
+ cconv_en = 1;
+ bpp = 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ l = dispc_read_reg(at_reg[plane]);
+
+ l &= ~(0x0f << 1);
+ l |= color_code << 1;
+ l &= ~(1 << 9);
+ l |= cconv_en << 9;
+
+ l &= ~(0x03 << burst_shift);
+ l |= DISPC_BURST_8x32 << burst_shift;
+
+ l &= ~(1 << chout_shift);
+ l |= chout_val << chout_shift;
+
+ dispc_write_reg(at_reg[plane], l);
+
+ dispc_write_reg(ba_reg[plane], paddr);
+ MOD_REG_FLD(ps_reg[plane],
+ FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
+
+ MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
+ ((height - 1) << 16) | (width - 1));
+
+ if (set_vsize) {
+ /* Set video size if set_scale hasn't set it */
+ if (!dispc.fir_vinc[plane])
+ MOD_REG_FLD(vs_reg[plane],
+ FLD_MASK(16, 11), (height - 1) << 16);
+ if (!dispc.fir_hinc[plane])
+ MOD_REG_FLD(vs_reg[plane],
+ FLD_MASK(0, 11), width - 1);
+ }
+
+ dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
+
+ return height * screen_width * bpp / 8;
+}
+
+static int omap_dispc_setup_plane(int plane, int channel_out,
+ unsigned long offset,
+ int screen_width,
+ int pos_x, int pos_y, int width, int height,
+ int color_mode)
+{
+ u32 paddr;
+ int r;
+
+ if ((unsigned)plane > dispc.mem_desc.region_cnt)
+ return -EINVAL;
+ paddr = dispc.mem_desc.region[plane].paddr + offset;
+ enable_lcd_clocks(1);
+ r = _setup_plane(plane, channel_out, paddr,
+ screen_width,
+ pos_x, pos_y, width, height, color_mode);
+ enable_lcd_clocks(0);
+ return r;
+}
+
+static void write_firh_reg(int plane, int reg, u32 value)
+{
+ u32 base;
+
+ if (plane == 1)
+ base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
+ else
+ base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
+ dispc_write_reg(base + reg * 8, value);
+}
+
+static void write_firhv_reg(int plane, int reg, u32 value)
+{
+ u32 base;
+
+ if (plane == 1)
+ base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
+ else
+ base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
+ dispc_write_reg(base + reg * 8, value);
+}
+
+static void set_upsampling_coef_table(int plane)
+{
+ const u32 coef[][2] = {
+ { 0x00800000, 0x00800000 },
+ { 0x0D7CF800, 0x037B02FF },
+ { 0x1E70F5FF, 0x0C6F05FE },
+ { 0x335FF5FE, 0x205907FB },
+ { 0xF74949F7, 0x00404000 },
+ { 0xF55F33FB, 0x075920FE },
+ { 0xF5701EFE, 0x056F0CFF },
+ { 0xF87C0DFF, 0x027B0300 },
+ };
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ write_firh_reg(plane, i, coef[i][0]);
+ write_firhv_reg(plane, i, coef[i][1]);
+ }
+}
+
+static int omap_dispc_set_scale(int plane,
+ int orig_width, int orig_height,
+ int out_width, int out_height)
+{
+ const u32 at_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+ DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+ const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
+ DISPC_VID2_BASE + DISPC_VID_SIZE };
+ const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
+ DISPC_VID2_BASE + DISPC_VID_FIR };
+
+ u32 l;
+ int fir_hinc;
+ int fir_vinc;
+
+ if ((unsigned)plane > OMAPFB_PLANE_NUM)
+ return -ENODEV;
+
+ if (plane == OMAPFB_PLANE_GFX &&
+ (out_width != orig_width || out_height != orig_height))
+ return -EINVAL;
+
+ enable_lcd_clocks(1);
+ if (orig_width < out_width) {
+ /*
+ * Upsampling.
+ * Currently you can only scale both dimensions in one way.
+ */
+ if (orig_height > out_height ||
+ orig_width * 8 < out_width ||
+ orig_height * 8 < out_height) {
+ enable_lcd_clocks(0);
+ return -EINVAL;
+ }
+ set_upsampling_coef_table(plane);
+ } else if (orig_width > out_width) {
+ /* Downsampling not yet supported
+ */
+
+ enable_lcd_clocks(0);
+ return -EINVAL;
+ }
+ if (!orig_width || orig_width == out_width)
+ fir_hinc = 0;
+ else
+ fir_hinc = 1024 * orig_width / out_width;
+ if (!orig_height || orig_height == out_height)
+ fir_vinc = 0;
+ else
+ fir_vinc = 1024 * orig_height / out_height;
+ dispc.fir_hinc[plane] = fir_hinc;
+ dispc.fir_vinc[plane] = fir_vinc;
+
+ MOD_REG_FLD(fir_reg[plane],
+ FLD_MASK(16, 12) | FLD_MASK(0, 12),
+ ((fir_vinc & 4095) << 16) |
+ (fir_hinc & 4095));
+
+ dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
+ "orig_height %d fir_hinc %d fir_vinc %d\n",
+ out_width, out_height, orig_width, orig_height,
+ fir_hinc, fir_vinc);
+
+ MOD_REG_FLD(vs_reg[plane],
+ FLD_MASK(16, 11) | FLD_MASK(0, 11),
+ ((out_height - 1) << 16) | (out_width - 1));
+
+ l = dispc_read_reg(at_reg[plane]);
+ l &= ~(0x03 << 5);
+ l |= fir_hinc ? (1 << 5) : 0;
+ l |= fir_vinc ? (1 << 6) : 0;
+ dispc_write_reg(at_reg[plane], l);
+
+ enable_lcd_clocks(0);
+ return 0;
+}
+
+static int omap_dispc_enable_plane(int plane, int enable)
+{
+ const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+ DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+ DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+ if ((unsigned int)plane > dispc.mem_desc.region_cnt)
+ return -EINVAL;
+
+ enable_lcd_clocks(1);
+ MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
+ enable_lcd_clocks(0);
+
+ return 0;
+}
+
+static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
+{
+ u32 df_reg, tr_reg;
+ int shift, val;
+
+ switch (ck->channel_out) {
+ case OMAPFB_CHANNEL_OUT_LCD:
+ df_reg = DISPC_DEFAULT_COLOR0;
+ tr_reg = DISPC_TRANS_COLOR0;
+ shift = 10;
+ break;
+ case OMAPFB_CHANNEL_OUT_DIGIT:
+ df_reg = DISPC_DEFAULT_COLOR1;
+ tr_reg = DISPC_TRANS_COLOR1;
+ shift = 12;
+ break;
+ default:
+ return -EINVAL;
+ }
+ switch (ck->key_type) {
+ case OMAPFB_COLOR_KEY_DISABLED:
+ val = 0;
+ break;
+ case OMAPFB_COLOR_KEY_GFX_DST:
+ val = 1;
+ break;
+ case OMAPFB_COLOR_KEY_VID_SRC:
+ val = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+ enable_lcd_clocks(1);
+ MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
+
+ if (val != 0)
+ dispc_write_reg(tr_reg, ck->trans_key);
+ dispc_write_reg(df_reg, ck->background);
+ enable_lcd_clocks(0);
+
+ dispc.color_key = *ck;
+
+ return 0;
+}
+
+static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
+{
+ *ck = dispc.color_key;
+ return 0;
+}
+
+static void load_palette(void)
+{
+}
+
+static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
+{
+ int r = 0;
+
+ if (mode != dispc.update_mode) {
+ switch (mode) {
+ case OMAPFB_AUTO_UPDATE:
+ case OMAPFB_MANUAL_UPDATE:
+ enable_lcd_clocks(1);
+ omap_dispc_enable_lcd_out(1);
+ dispc.update_mode = mode;
+ break;
+ case OMAPFB_UPDATE_DISABLED:
+ init_completion(&dispc.frame_done);
+ omap_dispc_enable_lcd_out(0);
+ if (!wait_for_completion_timeout(&dispc.frame_done,
+ msecs_to_jiffies(500))) {
+ dev_err(dispc.fbdev->dev,
+ "timeout waiting for FRAME DONE\n");
+ }
+ dispc.update_mode = mode;
+ enable_lcd_clocks(0);
+ break;
+ default:
+ r = -EINVAL;
+ }
+ }
+
+ return r;
+}
+
+static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps)
+{
+ caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM;
+ if (plane > 0)
+ caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE;
+ caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) |
+ (1 << OMAPFB_COLOR_YUV422) |
+ (1 << OMAPFB_COLOR_YUY422);
+ if (plane == 0)
+ caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) |
+ (1 << OMAPFB_COLOR_CLUT_4BPP) |
+ (1 << OMAPFB_COLOR_CLUT_2BPP) |
+ (1 << OMAPFB_COLOR_CLUT_1BPP) |
+ (1 << OMAPFB_COLOR_RGB444);
+}
+
+static enum omapfb_update_mode omap_dispc_get_update_mode(void)
+{
+ return dispc.update_mode;
+}
+
+static void setup_color_conv_coef(void)
+{
+ u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
+ int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
+ int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
+ int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
+ int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
+ const struct color_conv_coef {
+ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
+ int full_range;
+ } ctbl_bt601_5 = {
+ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
+ };
+ const struct color_conv_coef *ct;
+#define CVAL(x, y) (((x & 2047) << 16) | (y & 2047))
+
+ ct = &ctbl_bt601_5;
+
+ MOD_REG_FLD(cf1_reg, mask, CVAL(ct->rcr, ct->ry));
+ MOD_REG_FLD(cf1_reg + 4, mask, CVAL(ct->gy, ct->rcb));
+ MOD_REG_FLD(cf1_reg + 8, mask, CVAL(ct->gcb, ct->gcr));
+ MOD_REG_FLD(cf1_reg + 12, mask, CVAL(ct->bcr, ct->by));
+ MOD_REG_FLD(cf1_reg + 16, mask, CVAL(0, ct->bcb));
+
+ MOD_REG_FLD(cf2_reg, mask, CVAL(ct->rcr, ct->ry));
+ MOD_REG_FLD(cf2_reg + 4, mask, CVAL(ct->gy, ct->rcb));
+ MOD_REG_FLD(cf2_reg + 8, mask, CVAL(ct->gcb, ct->gcr));
+ MOD_REG_FLD(cf2_reg + 12, mask, CVAL(ct->bcr, ct->by));
+ MOD_REG_FLD(cf2_reg + 16, mask, CVAL(0, ct->bcb));
+#undef CVAL
+
+ MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
+ MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
+}
+
+static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
+{
+ unsigned long fck, lck;
+
+ *lck_div = 1;
+ pck = max(1, pck);
+ fck = clk_get_rate(dispc.dss1_fck);
+ lck = fck;
+ *pck_div = (lck + pck - 1) / pck;
+ if (is_tft)
+ *pck_div = max(2, *pck_div);
+ else
+ *pck_div = max(3, *pck_div);
+ if (*pck_div > 255) {
+ *pck_div = 255;
+ lck = pck * *pck_div;
+ *lck_div = fck / lck;
+ BUG_ON(*lck_div < 1);
+ if (*lck_div > 255) {
+ *lck_div = 255;
+ dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
+ pck / 1000);
+ }
+ }
+}
+
+static void set_lcd_tft_mode(int enable)
+{
+ u32 mask;
+
+ mask = 1 << 3;
+ MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0);
+}
+
+static void set_lcd_timings(void)
+{
+ u32 l;
+ int lck_div, pck_div;
+ struct lcd_panel *panel = dispc.fbdev->panel;
+ int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+ unsigned long fck;
+
+ l = dispc_read_reg(DISPC_TIMING_H);
+ l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+ l |= ( max(1, (min(64, panel->hsw))) - 1 ) << 0;
+ l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
+ l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
+ dispc_write_reg(DISPC_TIMING_H, l);
+
+ l = dispc_read_reg(DISPC_TIMING_V);
+ l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+ l |= ( max(1, (min(64, panel->vsw))) - 1 ) << 0;
+ l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
+ l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
+ dispc_write_reg(DISPC_TIMING_V, l);
+
+ l = dispc_read_reg(DISPC_POL_FREQ);
+ l &= ~FLD_MASK(12, 6);
+ l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
+ l |= panel->acb & 0xff;
+ dispc_write_reg(DISPC_POL_FREQ, l);
+
+ calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
+
+ l = dispc_read_reg(DISPC_DIVISOR);
+ l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
+ l |= (lck_div << 16) | (pck_div << 0);
+ dispc_write_reg(DISPC_DIVISOR, l);
+
+ /* update panel info with the exact clock */
+ fck = clk_get_rate(dispc.dss1_fck);
+ panel->pixel_clock = fck / lck_div / pck_div / 1000;
+}
+
+int omap_dispc_request_irq(void (*callback)(void *data), void *data)
+{
+ int r = 0;
+
+ BUG_ON(callback == NULL);
+
+ if (dispc.irq_callback)
+ r = -EBUSY;
+ else {
+ dispc.irq_callback = callback;
+ dispc.irq_callback_data = data;
+ }
+
+ return r;
+}
+EXPORT_SYMBOL(omap_dispc_request_irq);
+
+void omap_dispc_enable_irqs(int irq_mask)
+{
+ enable_lcd_clocks(1);
+ dispc.enabled_irqs = irq_mask;
+ irq_mask |= DISPC_IRQ_MASK_ERROR;
+ MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_irqs);
+
+void omap_dispc_disable_irqs(int irq_mask)
+{
+ enable_lcd_clocks(1);
+ dispc.enabled_irqs &= ~irq_mask;
+ irq_mask &= ~DISPC_IRQ_MASK_ERROR;
+ MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_disable_irqs);
+
+void omap_dispc_free_irq(void)
+{
+ enable_lcd_clocks(1);
+ omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
+ dispc.irq_callback = NULL;
+ dispc.irq_callback_data = NULL;
+ enable_lcd_clocks(0);
+}
+EXPORT_SYMBOL(omap_dispc_free_irq);
+
+static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
+{
+ u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
+
+ if (stat & DISPC_IRQ_FRAMEMASK)
+ complete(&dispc.frame_done);
+
+ if (stat & DISPC_IRQ_MASK_ERROR) {
+ if (printk_ratelimit()) {
+ dev_err(dispc.fbdev->dev, "irq error status %04x\n",
+ stat & 0x7fff);
+ }
+ }
+
+ if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
+ dispc.irq_callback(dispc.irq_callback_data);
+
+ dispc_write_reg(DISPC_IRQSTATUS, stat);
+
+ return IRQ_HANDLED;
+}
+
+static int get_dss_clocks(void)
+{
+ if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
+ dev_err(dispc.fbdev->dev, "can't get dss_ick");
+ return PTR_ERR(dispc.dss_ick);
+ }
+
+ if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
+ dev_err(dispc.fbdev->dev, "can't get dss1_fck");
+ clk_put(dispc.dss_ick);
+ return PTR_ERR(dispc.dss1_fck);
+ }
+
+ if (IS_ERR((dispc.dss_54m_fck =
+ clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
+ dev_err(dispc.fbdev->dev, "can't get dss_54m_fck");
+ clk_put(dispc.dss_ick);
+ clk_put(dispc.dss1_fck);
+ return PTR_ERR(dispc.dss_54m_fck);
+ }
+
+ return 0;
+}
+
+static void put_dss_clocks(void)
+{
+ clk_put(dispc.dss_54m_fck);
+ clk_put(dispc.dss1_fck);
+ clk_put(dispc.dss_ick);
+}
+
+static void enable_lcd_clocks(int enable)
+{
+ if (enable)
+ clk_enable(dispc.dss1_fck);
+ else
+ clk_disable(dispc.dss1_fck);
+}
+
+static void enable_interface_clocks(int enable)
+{
+ if (enable)
+ clk_enable(dispc.dss_ick);
+ else
+ clk_disable(dispc.dss_ick);
+}
+
+static void enable_digit_clocks(int enable)
+{
+ if (enable)
+ clk_enable(dispc.dss_54m_fck);
+ else
+ clk_disable(dispc.dss_54m_fck);
+}
+
+static void omap_dispc_suspend(void)
+{
+ if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+ init_completion(&dispc.frame_done);
+ omap_dispc_enable_lcd_out(0);
+ if (!wait_for_completion_timeout(&dispc.frame_done,
+ msecs_to_jiffies(500))) {
+ dev_err(dispc.fbdev->dev,
+ "timeout waiting for FRAME DONE\n");
+ }
+ enable_lcd_clocks(0);
+ }
+}
+
+static void omap_dispc_resume(void)
+{
+ if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+ enable_lcd_clocks(1);
+ if (!dispc.ext_mode) {
+ set_lcd_timings();
+ load_palette();
+ }
+ omap_dispc_enable_lcd_out(1);
+ }
+}
+
+
+static int omap_dispc_update_window(struct fb_info *fbi,
+ struct omapfb_update_window *win,
+ void (*complete_callback)(void *arg),
+ void *complete_callback_data)
+{
+ return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
+}
+
+static int mmap_kern(struct omapfb_mem_region *region)
+{
+ struct vm_struct *kvma;
+ struct vm_area_struct vma;
+ pgprot_t pgprot;
+ unsigned long vaddr;
+
+ kvma = get_vm_area(region->size, VM_IOREMAP);
+ if (kvma == NULL) {
+ dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
+ return -ENOMEM;
+ }
+ vma.vm_mm = &init_mm;
+
+ vaddr = (unsigned long)kvma->addr;
+
+ pgprot = pgprot_writecombine(pgprot_kernel);
+ vma.vm_start = vaddr;
+ vma.vm_end = vaddr + region->size;
+ if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
+ region->size, pgprot) < 0) {
+ dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
+ return -EAGAIN;
+ }
+ region->vaddr = (void *)vaddr;
+
+ return 0;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+ int plane = (int)vma->vm_private_data;
+
+ atomic_inc(&dispc.map_count[plane]);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+ int plane = (int)vma->vm_private_data;
+
+ atomic_dec(&dispc.map_count[plane]);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+ .open = mmap_user_open,
+ .close = mmap_user_close,
+};
+
+static int omap_dispc_mmap_user(struct fb_info *info,
+ struct vm_area_struct *vma)
+{
+ struct omapfb_plane_struct *plane = info->par;
+ unsigned long off;
+ unsigned long start;
+ u32 len;
+
+ if (vma->vm_end - vma->vm_start == 0)
+ return 0;
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+ return -EINVAL;
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ start = info->fix.smem_start;
+ len = info->fix.smem_len;
+ if (off >= len)
+ return -EINVAL;
+ if ((vma->vm_end - vma->vm_start + off) > len)
+ return -EINVAL;
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_ops = &mmap_user_ops;
+ vma->vm_private_data = (void *)plane->idx;
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+ /* vm_ops.open won't be called for mmap itself. */
+ atomic_inc(&dispc.map_count[plane->idx]);
+ return 0;
+}
+
+static void unmap_kern(struct omapfb_mem_region *region)
+{
+ vunmap(region->vaddr);
+}
+
+static int alloc_palette_ram(void)
+{
+ dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+ MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
+ if (dispc.palette_vaddr == NULL) {
+ dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void free_palette_ram(void)
+{
+ dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE,
+ dispc.palette_vaddr, dispc.palette_paddr);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+ region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
+ region->size, &region->paddr, GFP_KERNEL);
+
+ if (region->vaddr == NULL) {
+ dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void free_fbmem(struct omapfb_mem_region *region)
+{
+ dma_free_writecombine(dispc.fbdev->dev, region->size,
+ region->vaddr, region->paddr);
+}
+
+static struct resmap *init_resmap(unsigned long start, size_t size)
+{
+ unsigned page_cnt;
+ struct resmap *res_map;
+
+ page_cnt = PAGE_ALIGN(size) / PAGE_SIZE;
+ res_map =
+ kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL);
+ if (res_map == NULL)
+ return NULL;
+ res_map->start = start;
+ res_map->page_cnt = page_cnt;
+ res_map->map = (unsigned long *)(res_map + 1);
+ return res_map;
+}
+
+static void cleanup_resmap(struct resmap *res_map)
+{
+ kfree(res_map);
+}
+
+static inline int resmap_mem_type(unsigned long start)
+{
+ if (start >= OMAP2_SRAM_START &&
+ start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
+ return OMAPFB_MEMTYPE_SRAM;
+ else
+ return OMAPFB_MEMTYPE_SDRAM;
+}
+
+static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr)
+{
+ return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0;
+}
+
+static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr)
+{
+ BUG_ON(resmap_page_reserved(res_map, page_nr));
+ *RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr);
+}
+
+static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr)
+{
+ BUG_ON(!resmap_page_reserved(res_map, page_nr));
+ *RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr);
+}
+
+static void resmap_reserve_region(unsigned long start, size_t size)
+{
+
+ struct resmap *res_map;
+ unsigned start_page;
+ unsigned end_page;
+ int mtype;
+ unsigned i;
+
+ mtype = resmap_mem_type(start);
+ res_map = dispc.res_map[mtype];
+ dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n",
+ mtype, start, size);
+ start_page = (start - res_map->start) / PAGE_SIZE;
+ end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
+ for (i = start_page; i < end_page; i++)
+ resmap_reserve_page(res_map, i);
+}
+
+static void resmap_free_region(unsigned long start, size_t size)
+{
+ struct resmap *res_map;
+ unsigned start_page;
+ unsigned end_page;
+ unsigned i;
+ int mtype;
+
+ mtype = resmap_mem_type(start);
+ res_map = dispc.res_map[mtype];
+ dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n",
+ mtype, start, size);
+ start_page = (start - res_map->start) / PAGE_SIZE;
+ end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
+ for (i = start_page; i < end_page; i++)
+ resmap_free_page(res_map, i);
+}
+
+static unsigned long resmap_alloc_region(int mtype, size_t size)
+{
+ unsigned i;
+ unsigned total;
+ unsigned start_page;
+ unsigned long start;
+ struct resmap *res_map = dispc.res_map[mtype];
+
+ BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size);
+
+ size = PAGE_ALIGN(size) / PAGE_SIZE;
+ start_page = 0;
+ total = 0;
+ for (i = 0; i < res_map->page_cnt; i++) {
+ if (resmap_page_reserved(res_map, i)) {
+ start_page = i + 1;
+ total = 0;
+ } else if (++total == size)
+ break;
+ }
+ if (total < size)
+ return 0;
+
+ start = res_map->start + start_page * PAGE_SIZE;
+ resmap_reserve_region(start, size * PAGE_SIZE);
+
+ return start;
+}
+
+/* Note that this will only work for user mappings, we don't deal with
+ * kernel mappings here, so fbcon will keep using the old region.
+ */
+static int omap_dispc_setup_mem(int plane, size_t size, int mem_type,
+ unsigned long *paddr)
+{
+ struct omapfb_mem_region *rg;
+ unsigned long new_addr = 0;
+
+ if ((unsigned)plane > dispc.mem_desc.region_cnt)
+ return -EINVAL;
+ if (mem_type >= DISPC_MEMTYPE_NUM)
+ return -EINVAL;
+ if (dispc.res_map[mem_type] == NULL)
+ return -ENOMEM;
+ rg = &dispc.mem_desc.region[plane];
+ if (size == rg->size && mem_type == rg->type)
+ return 0;
+ if (atomic_read(&dispc.map_count[plane]))
+ return -EBUSY;
+ if (rg->size != 0)
+ resmap_free_region(rg->paddr, rg->size);
+ if (size != 0) {
+ new_addr = resmap_alloc_region(mem_type, size);
+ if (!new_addr) {
+ /* Reallocate old region. */
+ resmap_reserve_region(rg->paddr, rg->size);
+ return -ENOMEM;
+ }
+ }
+ rg->paddr = new_addr;
+ rg->size = size;
+ rg->type = mem_type;
+
+ *paddr = new_addr;
+
+ return 0;
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+ struct omapfb_mem_region *rg;
+ int i;
+ int r;
+ unsigned long mem_start[DISPC_MEMTYPE_NUM];
+ unsigned long mem_end[DISPC_MEMTYPE_NUM];
+
+ if (!req_md->region_cnt) {
+ dev_err(dispc.fbdev->dev, "no memory regions defined\n");
+ return -ENOENT;
+ }
+
+ rg = &req_md->region[0];
+ memset(mem_start, 0xff, sizeof(mem_start));
+ memset(mem_end, 0, sizeof(mem_end));
+
+ for (i = 0; i < req_md->region_cnt; i++, rg++) {
+ int mtype;
+ if (rg->paddr) {
+ rg->alloc = 0;
+ if (rg->vaddr == NULL) {
+ rg->map = 1;
+ if ((r = mmap_kern(rg)) < 0)
+ return r;
+ }
+ } else {
+ if (rg->type != OMAPFB_MEMTYPE_SDRAM) {
+ dev_err(dispc.fbdev->dev,
+ "unsupported memory type\n");
+ return -EINVAL;
+ }
+ rg->alloc = rg->map = 1;
+ if ((r = alloc_fbmem(rg)) < 0)
+ return r;
+ }
+ mtype = rg->type;
+
+ if (rg->paddr < mem_start[mtype])
+ mem_start[mtype] = rg->paddr;
+ if (rg->paddr + rg->size > mem_end[mtype])
+ mem_end[mtype] = rg->paddr + rg->size;
+ }
+
+ for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+ unsigned long start;
+ size_t size;
+ if (mem_end[i] == 0)
+ continue;
+ start = mem_start[i];
+ size = mem_end[i] - start;
+ dispc.res_map[i] = init_resmap(start, size);
+ r = -ENOMEM;
+ if (dispc.res_map[i] == NULL)
+ goto fail;
+ /* Initial state is that everything is reserved. This
+ * includes possible holes as well, which will never be
+ * freed.
+ */
+ resmap_reserve_region(start, size);
+ }
+
+ dispc.mem_desc = *req_md;
+
+ return 0;
+fail:
+ for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+ if (dispc.res_map[i] != NULL)
+ cleanup_resmap(dispc.res_map[i]);
+ }
+ return r;
+}
+
+static void cleanup_fbmem(void)
+{
+ struct omapfb_mem_region *rg;
+ int i;
+
+ for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
+ if (dispc.res_map[i] != NULL)
+ cleanup_resmap(dispc.res_map[i]);
+ }
+ rg = &dispc.mem_desc.region[0];
+ for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) {
+ if (rg->alloc)
+ free_fbmem(rg);
+ else {
+ if (rg->map)
+ unmap_kern(rg);
+ }
+ }
+}
+
+static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
+ struct omapfb_mem_desc *req_vram)
+{
+ int r;
+ u32 l;
+ struct lcd_panel *panel = fbdev->panel;
+ int tmo = 10000;
+ int skip_init = 0;
+ int i;
+
+ memset(&dispc, 0, sizeof(dispc));
+
+ dispc.base = io_p2v(DISPC_BASE);
+ dispc.fbdev = fbdev;
+ dispc.ext_mode = ext_mode;
+
+ init_completion(&dispc.frame_done);
+
+ if ((r = get_dss_clocks()) < 0)
+ return r;
+
+ enable_interface_clocks(1);
+ enable_lcd_clocks(1);
+
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ l = dispc_read_reg(DISPC_CONTROL);
+ /* LCD enabled ? */
+ if (l & 1) {
+ pr_info("omapfb: skipping hardware initialization\n");
+ skip_init = 1;
+ }
+#endif
+
+ if (!skip_init) {
+ /* Reset monitoring works only w/ the 54M clk */
+ enable_digit_clocks(1);
+
+ /* Soft reset */
+ MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
+
+ while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
+ if (!--tmo) {
+ dev_err(dispc.fbdev->dev, "soft reset failed\n");
+ r = -ENODEV;
+ enable_digit_clocks(0);
+ goto fail1;
+ }
+ }
+
+ enable_digit_clocks(0);
+ }
+
+ /* Enable smart idle and autoidle */
+ l = dispc_read_reg(DISPC_CONTROL);
+ l &= ~((3 << 12) | (3 << 3));
+ l |= (2 << 12) | (2 << 3) | (1 << 0);
+ dispc_write_reg(DISPC_SYSCONFIG, l);
+ omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
+
+ /* Set functional clock autogating */
+ l = dispc_read_reg(DISPC_CONFIG);
+ l |= 1 << 9;
+ dispc_write_reg(DISPC_CONFIG, l);
+
+ l = dispc_read_reg(DISPC_IRQSTATUS);
+ dispc_write_reg(l, DISPC_IRQSTATUS);
+
+ /* Enable those that we handle always */
+ omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
+
+ if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
+ 0, MODULE_NAME, fbdev)) < 0) {
+ dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
+ goto fail1;
+ }
+
+ /* L3 firewall setting: enable access to OCM RAM */
+ __raw_writel(0x402000b0, io_p2v(0x680050a0));
+
+ if ((r = alloc_palette_ram()) < 0)
+ goto fail2;
+
+ if ((r = setup_fbmem(req_vram)) < 0)
+ goto fail3;
+
+ if (!skip_init) {
+ for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
+ memset(dispc.mem_desc.region[i].vaddr, 0,
+ dispc.mem_desc.region[i].size);
+ }
+
+ /* Set logic clock to fck, pixel clock to fck/2 for now */
+ MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
+ MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0);
+
+ setup_plane_fifo(0, ext_mode);
+ setup_plane_fifo(1, ext_mode);
+ setup_plane_fifo(2, ext_mode);
+
+ setup_color_conv_coef();
+
+ set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
+ set_load_mode(DISPC_LOAD_FRAME_ONLY);
+
+ if (!ext_mode) {
+ set_lcd_data_lines(panel->data_lines);
+ omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
+ set_lcd_timings();
+ } else
+ set_lcd_data_lines(panel->bpp);
+ enable_rfbi_mode(ext_mode);
+ }
+
+ l = dispc_read_reg(DISPC_REVISION);
+ pr_info("omapfb: DISPC version %d.%d initialized\n",
+ l >> 4 & 0x0f, l & 0x0f);
+ enable_lcd_clocks(0);
+
+ return 0;
+fail3:
+ free_palette_ram();
+fail2:
+ free_irq(INT_24XX_DSS_IRQ, fbdev);
+fail1:
+ enable_lcd_clocks(0);
+ enable_interface_clocks(0);
+ put_dss_clocks();
+
+ return r;
+}
+
+static void omap_dispc_cleanup(void)
+{
+ int i;
+
+ omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
+ /* This will also disable clocks that are on */
+ for (i = 0; i < dispc.mem_desc.region_cnt; i++)
+ omap_dispc_enable_plane(i, 0);
+ cleanup_fbmem();
+ free_palette_ram();
+ free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
+ enable_interface_clocks(0);
+ put_dss_clocks();
+}
+
+const struct lcd_ctrl omap2_int_ctrl = {
+ .name = "internal",
+ .init = omap_dispc_init,
+ .cleanup = omap_dispc_cleanup,
+ .get_caps = omap_dispc_get_caps,
+ .set_update_mode = omap_dispc_set_update_mode,
+ .get_update_mode = omap_dispc_get_update_mode,
+ .update_window = omap_dispc_update_window,
+ .suspend = omap_dispc_suspend,
+ .resume = omap_dispc_resume,
+ .setup_plane = omap_dispc_setup_plane,
+ .setup_mem = omap_dispc_setup_mem,
+ .set_scale = omap_dispc_set_scale,
+ .enable_plane = omap_dispc_enable_plane,
+ .set_color_key = omap_dispc_set_color_key,
+ .get_color_key = omap_dispc_get_color_key,
+ .mmap = omap_dispc_mmap_user,
+};
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
new file mode 100644
index 000000000000..eb1512b56ce8
--- /dev/null
+++ b/drivers/video/omap/dispc.h
@@ -0,0 +1,43 @@
+#ifndef _DISPC_H
+#define _DISPC_H
+
+#include <linux/interrupt.h>
+
+#define DISPC_PLANE_GFX 0
+#define DISPC_PLANE_VID1 1
+#define DISPC_PLANE_VID2 2
+
+#define DISPC_RGB_1_BPP 0x00
+#define DISPC_RGB_2_BPP 0x01
+#define DISPC_RGB_4_BPP 0x02
+#define DISPC_RGB_8_BPP 0x03
+#define DISPC_RGB_12_BPP 0x04
+#define DISPC_RGB_16_BPP 0x06
+#define DISPC_RGB_24_BPP 0x08
+#define DISPC_RGB_24_BPP_UNPACK_32 0x09
+#define DISPC_YUV2_422 0x0a
+#define DISPC_UYVY_422 0x0b
+
+#define DISPC_BURST_4x32 0
+#define DISPC_BURST_8x32 1
+#define DISPC_BURST_16x32 2
+
+#define DISPC_LOAD_CLUT_AND_FRAME 0x00
+#define DISPC_LOAD_CLUT_ONLY 0x01
+#define DISPC_LOAD_FRAME_ONLY 0x02
+#define DISPC_LOAD_CLUT_ONCE_FRAME 0x03
+
+#define DISPC_TFT_DATA_LINES_12 0
+#define DISPC_TFT_DATA_LINES_16 1
+#define DISPC_TFT_DATA_LINES_18 2
+#define DISPC_TFT_DATA_LINES_24 3
+
+extern void omap_dispc_set_lcd_size(int width, int height);
+
+extern void omap_dispc_enable_lcd_out(int enable);
+extern void omap_dispc_enable_digit_out(int enable);
+
+extern int omap_dispc_request_irq(void (*callback)(void *data), void *data);
+extern void omap_dispc_free_irq(void);
+
+#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
new file mode 100644
index 000000000000..dc48e02f215c
--- /dev/null
+++ b/drivers/video/omap/hwa742.c
@@ -0,0 +1,1077 @@
+/*
+ * Epson HWA742 LCD controller driver
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Authors: Juha Yrjölä <juha.yrjola@nokia.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * YUV support: Jussi Laako <jussi.laako@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/mm.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/hwa742.h>
+
+#define HWA742_REV_CODE_REG 0x0
+#define HWA742_CONFIG_REG 0x2
+#define HWA742_PLL_DIV_REG 0x4
+#define HWA742_PLL_0_REG 0x6
+#define HWA742_PLL_1_REG 0x8
+#define HWA742_PLL_2_REG 0xa
+#define HWA742_PLL_3_REG 0xc
+#define HWA742_PLL_4_REG 0xe
+#define HWA742_CLK_SRC_REG 0x12
+#define HWA742_PANEL_TYPE_REG 0x14
+#define HWA742_H_DISP_REG 0x16
+#define HWA742_H_NDP_REG 0x18
+#define HWA742_V_DISP_1_REG 0x1a
+#define HWA742_V_DISP_2_REG 0x1c
+#define HWA742_V_NDP_REG 0x1e
+#define HWA742_HS_W_REG 0x20
+#define HWA742_HP_S_REG 0x22
+#define HWA742_VS_W_REG 0x24
+#define HWA742_VP_S_REG 0x26
+#define HWA742_PCLK_POL_REG 0x28
+#define HWA742_INPUT_MODE_REG 0x2a
+#define HWA742_TRANSL_MODE_REG1 0x2e
+#define HWA742_DISP_MODE_REG 0x34
+#define HWA742_WINDOW_TYPE 0x36
+#define HWA742_WINDOW_X_START_0 0x38
+#define HWA742_WINDOW_X_START_1 0x3a
+#define HWA742_WINDOW_Y_START_0 0x3c
+#define HWA742_WINDOW_Y_START_1 0x3e
+#define HWA742_WINDOW_X_END_0 0x40
+#define HWA742_WINDOW_X_END_1 0x42
+#define HWA742_WINDOW_Y_END_0 0x44
+#define HWA742_WINDOW_Y_END_1 0x46
+#define HWA742_MEMORY_WRITE_LSB 0x48
+#define HWA742_MEMORY_WRITE_MSB 0x49
+#define HWA742_MEMORY_READ_0 0x4a
+#define HWA742_MEMORY_READ_1 0x4c
+#define HWA742_MEMORY_READ_2 0x4e
+#define HWA742_POWER_SAVE 0x56
+#define HWA742_NDP_CTRL 0x58
+
+#define HWA742_AUTO_UPDATE_TIME (HZ / 20)
+
+/* Reserve 4 request slots for requests in irq context */
+#define REQ_POOL_SIZE 24
+#define IRQ_REQ_POOL_SIZE 4
+
+#define REQ_FROM_IRQ_POOL 0x01
+
+#define REQ_COMPLETE 0
+#define REQ_PENDING 1
+
+struct update_param {
+ int x, y, width, height;
+ int color_mode;
+ int flags;
+};
+
+struct hwa742_request {
+ struct list_head entry;
+ unsigned int flags;
+
+ int (*handler)(struct hwa742_request *req);
+ void (*complete)(void *data);
+ void *complete_data;
+
+ union {
+ struct update_param update;
+ struct completion *sync;
+ } par;
+};
+
+struct {
+ enum omapfb_update_mode update_mode;
+ enum omapfb_update_mode update_mode_before_suspend;
+
+ struct timer_list auto_update_timer;
+ int stop_auto_update;
+ struct omapfb_update_window auto_update_window;
+ unsigned te_connected:1;
+ unsigned vsync_only:1;
+
+ struct hwa742_request req_pool[REQ_POOL_SIZE];
+ struct list_head pending_req_list;
+ struct list_head free_req_list;
+ struct semaphore req_sema;
+ spinlock_t req_lock;
+
+ struct extif_timings reg_timings, lut_timings;
+
+ int prev_color_mode;
+ int prev_flags;
+ int window_type;
+
+ u32 max_transmit_size;
+ u32 extif_clk_period;
+ unsigned long pix_tx_time;
+ unsigned long line_upd_time;
+
+
+ struct omapfb_device *fbdev;
+ struct lcd_ctrl_extif *extif;
+ struct lcd_ctrl *int_ctrl;
+
+ void (*power_up)(struct device *dev);
+ void (*power_down)(struct device *dev);
+} hwa742;
+
+struct lcd_ctrl hwa742_ctrl;
+
+static u8 hwa742_read_reg(u8 reg)
+{
+ u8 data;
+
+ hwa742.extif->set_bits_per_cycle(8);
+ hwa742.extif->write_command(&reg, 1);
+ hwa742.extif->read_data(&data, 1);
+
+ return data;
+}
+
+static void hwa742_write_reg(u8 reg, u8 data)
+{
+ hwa742.extif->set_bits_per_cycle(8);
+ hwa742.extif->write_command(&reg, 1);
+ hwa742.extif->write_data(&data, 1);
+}
+
+static void set_window_regs(int x_start, int y_start, int x_end, int y_end)
+{
+ u8 tmp[8];
+ u8 cmd;
+
+ x_end--;
+ y_end--;
+ tmp[0] = x_start;
+ tmp[1] = x_start >> 8;
+ tmp[2] = y_start;
+ tmp[3] = y_start >> 8;
+ tmp[4] = x_end;
+ tmp[5] = x_end >> 8;
+ tmp[6] = y_end;
+ tmp[7] = y_end >> 8;
+
+ hwa742.extif->set_bits_per_cycle(8);
+ cmd = HWA742_WINDOW_X_START_0;
+
+ hwa742.extif->write_command(&cmd, 1);
+
+ hwa742.extif->write_data(tmp, 8);
+}
+
+static void set_format_regs(int conv, int transl, int flags)
+{
+ if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
+ hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01);
+#ifdef VERBOSE
+ dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n");
+#endif
+ } else {
+ hwa742.window_type = (hwa742.window_type & 0xfc);
+#ifdef VERBOSE
+ dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n");
+#endif
+ }
+
+ hwa742_write_reg(HWA742_INPUT_MODE_REG, conv);
+ hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl);
+ hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type);
+}
+
+static void enable_tearsync(int y, int width, int height, int screen_height,
+ int force_vsync)
+{
+ u8 b;
+
+ b = hwa742_read_reg(HWA742_NDP_CTRL);
+ b |= 1 << 2;
+ hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+ if (likely(hwa742.vsync_only || force_vsync)) {
+ hwa742.extif->enable_tearsync(1, 0);
+ return;
+ }
+
+ if (width * hwa742.pix_tx_time < hwa742.line_upd_time) {
+ hwa742.extif->enable_tearsync(1, 0);
+ return;
+ }
+
+ if ((width * hwa742.pix_tx_time / 1000) * height <
+ (y + height) * (hwa742.line_upd_time / 1000)) {
+ hwa742.extif->enable_tearsync(1, 0);
+ return;
+ }
+
+ hwa742.extif->enable_tearsync(1, y + 1);
+}
+
+static void disable_tearsync(void)
+{
+ u8 b;
+
+ hwa742.extif->enable_tearsync(0, 0);
+
+ b = hwa742_read_reg(HWA742_NDP_CTRL);
+ b &= ~(1 << 2);
+ hwa742_write_reg(HWA742_NDP_CTRL, b);
+}
+
+static inline struct hwa742_request *alloc_req(void)
+{
+ unsigned long flags;
+ struct hwa742_request *req;
+ int req_flags = 0;
+
+ if (!in_interrupt())
+ down(&hwa742.req_sema);
+ else
+ req_flags = REQ_FROM_IRQ_POOL;
+
+ spin_lock_irqsave(&hwa742.req_lock, flags);
+ BUG_ON(list_empty(&hwa742.free_req_list));
+ req = list_entry(hwa742.free_req_list.next,
+ struct hwa742_request, entry);
+ list_del(&req->entry);
+ spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+ INIT_LIST_HEAD(&req->entry);
+ req->flags = req_flags;
+
+ return req;
+}
+
+static inline void free_req(struct hwa742_request *req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hwa742.req_lock, flags);
+
+ list_del(&req->entry);
+ list_add(&req->entry, &hwa742.free_req_list);
+ if (!(req->flags & REQ_FROM_IRQ_POOL))
+ up(&hwa742.req_sema);
+
+ spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void process_pending_requests(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hwa742.req_lock, flags);
+
+ while (!list_empty(&hwa742.pending_req_list)) {
+ struct hwa742_request *req;
+ void (*complete)(void *);
+ void *complete_data;
+
+ req = list_entry(hwa742.pending_req_list.next,
+ struct hwa742_request, entry);
+ spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+ if (req->handler(req) == REQ_PENDING)
+ return;
+
+ complete = req->complete;
+ complete_data = req->complete_data;
+ free_req(req);
+
+ if (complete)
+ complete(complete_data);
+
+ spin_lock_irqsave(&hwa742.req_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&hwa742.req_lock, flags);
+}
+
+static void submit_req_list(struct list_head *head)
+{
+ unsigned long flags;
+ int process = 1;
+
+ spin_lock_irqsave(&hwa742.req_lock, flags);
+ if (likely(!list_empty(&hwa742.pending_req_list)))
+ process = 0;
+ list_splice_init(head, hwa742.pending_req_list.prev);
+ spin_unlock_irqrestore(&hwa742.req_lock, flags);
+
+ if (process)
+ process_pending_requests();
+}
+
+static void request_complete(void *data)
+{
+ struct hwa742_request *req = (struct hwa742_request *)data;
+ void (*complete)(void *);
+ void *complete_data;
+
+ complete = req->complete;
+ complete_data = req->complete_data;
+
+ free_req(req);
+
+ if (complete)
+ complete(complete_data);
+
+ process_pending_requests();
+}
+
+static int send_frame_handler(struct hwa742_request *req)
+{
+ struct update_param *par = &req->par.update;
+ int x = par->x;
+ int y = par->y;
+ int w = par->width;
+ int h = par->height;
+ int bpp;
+ int conv, transl;
+ unsigned long offset;
+ int color_mode = par->color_mode;
+ int flags = par->flags;
+ int scr_width = hwa742.fbdev->panel->x_res;
+ int scr_height = hwa742.fbdev->panel->y_res;
+
+#ifdef VERBOSE
+ dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d "
+ "color_mode %d flags %d\n",
+ x, y, w, h, scr_width, color_mode, flags);
+#endif
+
+ switch (color_mode) {
+ case OMAPFB_COLOR_YUV422:
+ bpp = 16;
+ conv = 0x08;
+ transl = 0x25;
+ break;
+ case OMAPFB_COLOR_YUV420:
+ bpp = 12;
+ conv = 0x09;
+ transl = 0x25;
+ break;
+ case OMAPFB_COLOR_RGB565:
+ bpp = 16;
+ conv = 0x01;
+ transl = 0x05;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (hwa742.prev_flags != flags ||
+ hwa742.prev_color_mode != color_mode) {
+ set_format_regs(conv, transl, flags);
+ hwa742.prev_color_mode = color_mode;
+ hwa742.prev_flags = flags;
+ }
+ flags = req->par.update.flags;
+ if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
+ enable_tearsync(y, scr_width, h, scr_height,
+ flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
+ else
+ disable_tearsync();
+
+ set_window_regs(x, y, x + w, y + h);
+
+ offset = (scr_width * y + x) * bpp / 8;
+
+ hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX,
+ OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h,
+ color_mode);
+
+ hwa742.extif->set_bits_per_cycle(16);
+
+ hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+ hwa742.extif->transfer_area(w, h, request_complete, req);
+
+ return REQ_PENDING;
+}
+
+static void send_frame_complete(void *data)
+{
+ hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0);
+}
+
+#define ADD_PREQ(_x, _y, _w, _h) do { \
+ req = alloc_req(); \
+ req->handler = send_frame_handler; \
+ req->complete = send_frame_complete; \
+ req->par.update.x = _x; \
+ req->par.update.y = _y; \
+ req->par.update.width = _w; \
+ req->par.update.height = _h; \
+ req->par.update.color_mode = color_mode;\
+ req->par.update.flags = flags; \
+ list_add_tail(&req->entry, req_head); \
+} while(0)
+
+static void create_req_list(struct omapfb_update_window *win,
+ struct list_head *req_head)
+{
+ struct hwa742_request *req;
+ int x = win->x;
+ int y = win->y;
+ int width = win->width;
+ int height = win->height;
+ int color_mode;
+ int flags;
+
+ flags = win->format & ~OMAPFB_FORMAT_MASK;
+ color_mode = win->format & OMAPFB_FORMAT_MASK;
+
+ if (x & 1) {
+ ADD_PREQ(x, y, 1, height);
+ width--;
+ x++;
+ flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+ }
+ if (width & ~1) {
+ unsigned int xspan = width & ~1;
+ unsigned int ystart = y;
+ unsigned int yspan = height;
+
+ if (xspan * height * 2 > hwa742.max_transmit_size) {
+ yspan = hwa742.max_transmit_size / (xspan * 2);
+ ADD_PREQ(x, ystart, xspan, yspan);
+ ystart += yspan;
+ yspan = height - yspan;
+ flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+ }
+
+ ADD_PREQ(x, ystart, xspan, yspan);
+ x += xspan;
+ width -= xspan;
+ flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
+ }
+ if (width)
+ ADD_PREQ(x, y, 1, height);
+}
+
+static void auto_update_complete(void *data)
+{
+ if (!hwa742.stop_auto_update)
+ mod_timer(&hwa742.auto_update_timer,
+ jiffies + HWA742_AUTO_UPDATE_TIME);
+}
+
+static void hwa742_update_window_auto(unsigned long arg)
+{
+ LIST_HEAD(req_list);
+ struct hwa742_request *last;
+
+ create_req_list(&hwa742.auto_update_window, &req_list);
+ last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+ last->complete = auto_update_complete;
+ last->complete_data = NULL;
+
+ submit_req_list(&req_list);
+}
+
+int hwa742_update_window_async(struct fb_info *fbi,
+ struct omapfb_update_window *win,
+ void (*complete_callback)(void *arg),
+ void *complete_callback_data)
+{
+ LIST_HEAD(req_list);
+ struct hwa742_request *last;
+ int r = 0;
+
+ if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) {
+ dev_dbg(hwa742.fbdev->dev, "invalid update mode\n");
+ r = -EINVAL;
+ goto out;
+ }
+ if (unlikely(win->format &
+ ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE |
+ OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) {
+ dev_dbg(hwa742.fbdev->dev, "invalid window flag");
+ r = -EINVAL;
+ goto out;
+ }
+
+ create_req_list(win, &req_list);
+ last = list_entry(req_list.prev, struct hwa742_request, entry);
+
+ last->complete = complete_callback;
+ last->complete_data = (void *)complete_callback_data;
+
+ submit_req_list(&req_list);
+
+out:
+ return r;
+}
+EXPORT_SYMBOL(hwa742_update_window_async);
+
+static int hwa742_setup_plane(int plane, int channel_out,
+ unsigned long offset, int screen_width,
+ int pos_x, int pos_y, int width, int height,
+ int color_mode)
+{
+ if (plane != OMAPFB_PLANE_GFX ||
+ channel_out != OMAPFB_CHANNEL_OUT_LCD)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int hwa742_enable_plane(int plane, int enable)
+{
+ if (plane != 0)
+ return -EINVAL;
+
+ hwa742.int_ctrl->enable_plane(plane, enable);
+
+ return 0;
+}
+
+static int sync_handler(struct hwa742_request *req)
+{
+ complete(req->par.sync);
+ return REQ_COMPLETE;
+}
+
+static void hwa742_sync(void)
+{
+ LIST_HEAD(req_list);
+ struct hwa742_request *req;
+ struct completion comp;
+
+ req = alloc_req();
+
+ req->handler = sync_handler;
+ req->complete = NULL;
+ init_completion(&comp);
+ req->par.sync = &comp;
+
+ list_add(&req->entry, &req_list);
+ submit_req_list(&req_list);
+
+ wait_for_completion(&comp);
+}
+
+static void hwa742_bind_client(struct omapfb_notifier_block *nb)
+{
+ dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode);
+ if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) {
+ omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+ }
+}
+
+static int hwa742_set_update_mode(enum omapfb_update_mode mode)
+{
+ if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE &&
+ mode != OMAPFB_UPDATE_DISABLED)
+ return -EINVAL;
+
+ if (mode == hwa742.update_mode)
+ return 0;
+
+ dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n",
+ mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
+ (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
+
+ switch (hwa742.update_mode) {
+ case OMAPFB_MANUAL_UPDATE:
+ omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED);
+ break;
+ case OMAPFB_AUTO_UPDATE:
+ hwa742.stop_auto_update = 1;
+ del_timer_sync(&hwa742.auto_update_timer);
+ break;
+ case OMAPFB_UPDATE_DISABLED:
+ break;
+ }
+
+ hwa742.update_mode = mode;
+ hwa742_sync();
+ hwa742.stop_auto_update = 0;
+
+ switch (mode) {
+ case OMAPFB_MANUAL_UPDATE:
+ omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY);
+ break;
+ case OMAPFB_AUTO_UPDATE:
+ hwa742_update_window_auto(0);
+ break;
+ case OMAPFB_UPDATE_DISABLED:
+ break;
+ }
+
+ return 0;
+}
+
+static enum omapfb_update_mode hwa742_get_update_mode(void)
+{
+ return hwa742.update_mode;
+}
+
+static unsigned long round_to_extif_ticks(unsigned long ps, int div)
+{
+ int bus_tick = hwa742.extif_clk_period * div;
+ return (ps + bus_tick - 1) / bus_tick * bus_tick;
+}
+
+static int calc_reg_timing(unsigned long sysclk, int div)
+{
+ struct extif_timings *t;
+ unsigned long systim;
+
+ /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+ * AccessTime 2 ns + 12.2 ns (regs),
+ * WEOffTime = WEOnTime + 1 ns,
+ * REOffTime = REOnTime + 16 ns (regs),
+ * CSOffTime = REOffTime + 1 ns
+ * ReadCycle = 2ns + 2*SYSCLK (regs),
+ * WriteCycle = 2*SYSCLK + 2 ns,
+ * CSPulseWidth = 10 ns */
+ systim = 1000000000 / (sysclk / 1000);
+ dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+ "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+ t = &hwa742.reg_timings;
+ memset(t, 0, sizeof(*t));
+ t->clk_div = div;
+ t->cs_on_time = 0;
+ t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
+ t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+ t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div);
+ t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+ t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+ if (t->we_cycle_time < t->we_off_time)
+ t->we_cycle_time = t->we_off_time;
+ t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+ if (t->re_cycle_time < t->re_off_time)
+ t->re_cycle_time = t->re_off_time;
+ t->cs_pulse_width = 0;
+
+ dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+ dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
+ t->we_on_time, t->we_off_time, t->re_cycle_time,
+ t->we_cycle_time);
+ dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
+ t->access_time, t->cs_pulse_width);
+
+ return hwa742.extif->convert_timings(t);
+}
+
+static int calc_lut_timing(unsigned long sysclk, int div)
+{
+ struct extif_timings *t;
+ unsigned long systim;
+
+ /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
+ * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
+ * WEOffTime = WEOnTime + 1 ns,
+ * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
+ * CSOffTime = REOffTime + 1 ns
+ * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
+ * WriteCycle = 2*SYSCLK + 2 ns,
+ * CSPulseWidth = 10 ns
+ */
+ systim = 1000000000 / (sysclk / 1000);
+ dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps"
+ "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div);
+
+ t = &hwa742.lut_timings;
+ memset(t, 0, sizeof(*t));
+
+ t->clk_div = div;
+
+ t->cs_on_time = 0;
+ t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
+ t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+ 26000, div);
+ t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
+ t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
+ 26000, div);
+ t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
+ t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
+ if (t->we_cycle_time < t->we_off_time)
+ t->we_cycle_time = t->we_off_time;
+ t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
+ if (t->re_cycle_time < t->re_off_time)
+ t->re_cycle_time = t->re_off_time;
+ t->cs_pulse_width = 0;
+
+ dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n",
+ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
+ dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n",
+ t->we_on_time, t->we_off_time, t->re_cycle_time,
+ t->we_cycle_time);
+ dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
+ t->access_time, t->cs_pulse_width);
+
+ return hwa742.extif->convert_timings(t);
+}
+
+static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
+{
+ int max_clk_div;
+ int div;
+
+ hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div);
+ for (div = 1; div < max_clk_div; div++) {
+ if (calc_reg_timing(sysclk, div) == 0)
+ break;
+ }
+ if (div > max_clk_div)
+ goto err;
+
+ *extif_mem_div = div;
+
+ for (div = 1; div < max_clk_div; div++) {
+ if (calc_lut_timing(sysclk, div) == 0)
+ break;
+ }
+
+ if (div > max_clk_div)
+ goto err;
+
+ return 0;
+
+err:
+ dev_err(hwa742.fbdev->dev, "can't setup timings\n");
+ return -1;
+}
+
+static void calc_hwa742_clk_rates(unsigned long ext_clk,
+ unsigned long *sys_clk, unsigned long *pix_clk)
+{
+ int pix_clk_src;
+ int sys_div = 0, sys_mul = 0;
+ int pix_div;
+
+ pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG);
+ pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
+ if ((pix_clk_src & (0x3 << 1)) == 0) {
+ /* Source is the PLL */
+ sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1;
+ sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1;
+ *sys_clk = ext_clk * sys_mul / sys_div;
+ } else /* else source is ext clk, or oscillator */
+ *sys_clk = ext_clk;
+
+ *pix_clk = *sys_clk / pix_div; /* HZ */
+ dev_dbg(hwa742.fbdev->dev,
+ "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
+ ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
+ dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
+ *sys_clk, *pix_clk);
+}
+
+
+static int setup_tearsync(unsigned long pix_clk, int extif_div)
+{
+ int hdisp, vdisp;
+ int hndp, vndp;
+ int hsw, vsw;
+ int hs, vs;
+ int hs_pol_inv, vs_pol_inv;
+ int use_hsvs, use_ndp;
+ u8 b;
+
+ hsw = hwa742_read_reg(HWA742_HS_W_REG);
+ vsw = hwa742_read_reg(HWA742_VS_W_REG);
+ hs_pol_inv = !(hsw & 0x80);
+ vs_pol_inv = !(vsw & 0x80);
+ hsw = hsw & 0x7f;
+ vsw = vsw & 0x3f;
+
+ hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8;
+ vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) +
+ ((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8);
+
+ hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f;
+ vndp = hwa742_read_reg(HWA742_V_NDP_REG);
+
+ /* time to transfer one pixel (16bpp) in ps */
+ hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time;
+ if (hwa742.extif->get_max_tx_rate != NULL) {
+ /*
+ * The external interface might have a rate limitation,
+ * if so, we have to maximize our transfer rate.
+ */
+ unsigned long min_tx_time;
+ unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate();
+
+ dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n",
+ max_tx_rate);
+ min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */
+ if (hwa742.pix_tx_time < min_tx_time)
+ hwa742.pix_tx_time = min_tx_time;
+ }
+
+ /* time to update one line in ps */
+ hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
+ hwa742.line_upd_time *= 1000;
+ if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time)
+ /*
+ * transfer speed too low, we might have to use both
+ * HS and VS
+ */
+ use_hsvs = 1;
+ else
+ /* decent transfer speed, we'll always use only VS */
+ use_hsvs = 0;
+
+ if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
+ /*
+ * HS or'ed with VS doesn't work, use the active high
+ * TE signal based on HNDP / VNDP
+ */
+ use_ndp = 1;
+ hs_pol_inv = 0;
+ vs_pol_inv = 0;
+ hs = hndp;
+ vs = vndp;
+ } else {
+ /*
+ * Use HS or'ed with VS as a TE signal if both are needed
+ * or VNDP if only vsync is needed.
+ */
+ use_ndp = 0;
+ hs = hsw;
+ vs = vsw;
+ if (!use_hsvs) {
+ hs_pol_inv = 0;
+ vs_pol_inv = 0;
+ }
+ }
+
+ hs = hs * 1000000 / (pix_clk / 1000); /* ps */
+ hs *= 1000;
+
+ vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
+ vs *= 1000;
+
+ if (vs <= hs)
+ return -EDOM;
+ /* set VS to 120% of HS to minimize VS detection time */
+ vs = hs * 12 / 10;
+ /* minimize HS too */
+ hs = 10000;
+
+ b = hwa742_read_reg(HWA742_NDP_CTRL);
+ b &= ~0x3;
+ b |= use_hsvs ? 1 : 0;
+ b |= (use_ndp && use_hsvs) ? 0 : 2;
+ hwa742_write_reg(HWA742_NDP_CTRL, b);
+
+ hwa742.vsync_only = !use_hsvs;
+
+ dev_dbg(hwa742.fbdev->dev,
+ "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
+ pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time);
+ dev_dbg(hwa742.fbdev->dev,
+ "hs %d ps vs %d ps mode %d vsync_only %d\n",
+ hs, vs, (b & 0x3), !use_hsvs);
+
+ return hwa742.extif->setup_tearsync(1, hs, vs,
+ hs_pol_inv, vs_pol_inv, extif_div);
+}
+
+static void hwa742_get_caps(int plane, struct omapfb_caps *caps)
+{
+ hwa742.int_ctrl->get_caps(plane, caps);
+ caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
+ OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE;
+ if (hwa742.te_connected)
+ caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
+ caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
+ (1 << OMAPFB_COLOR_YUV420);
+}
+
+static void hwa742_suspend(void)
+{
+ hwa742.update_mode_before_suspend = hwa742.update_mode;
+ hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+ /* Enable sleep mode */
+ hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1);
+ if (hwa742.power_down != NULL)
+ hwa742.power_down(hwa742.fbdev->dev);
+}
+
+static void hwa742_resume(void)
+{
+ if (hwa742.power_up != NULL)
+ hwa742.power_up(hwa742.fbdev->dev);
+ /* Disable sleep mode */
+ hwa742_write_reg(HWA742_POWER_SAVE, 0);
+ while (1) {
+ /* Loop until PLL output is stabilized */
+ if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7))
+ break;
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(msecs_to_jiffies(5));
+ }
+ hwa742_set_update_mode(hwa742.update_mode_before_suspend);
+}
+
+static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
+ struct omapfb_mem_desc *req_vram)
+{
+ int r = 0, i;
+ u8 rev, conf;
+ unsigned long ext_clk;
+ unsigned long sys_clk, pix_clk;
+ int extif_mem_div;
+ struct omapfb_platform_data *omapfb_conf;
+ struct hwa742_platform_data *ctrl_conf;
+
+ BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
+
+ hwa742.fbdev = fbdev;
+ hwa742.extif = fbdev->ext_if;
+ hwa742.int_ctrl = fbdev->int_ctrl;
+
+ omapfb_conf = fbdev->dev->platform_data;
+ ctrl_conf = omapfb_conf->ctrl_platform_data;
+
+ if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
+ dev_err(fbdev->dev, "HWA742: missing platform data\n");
+ r = -ENOENT;
+ goto err1;
+ }
+
+ hwa742.power_down = ctrl_conf->power_down;
+ hwa742.power_up = ctrl_conf->power_up;
+
+ spin_lock_init(&hwa742.req_lock);
+
+ if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0)
+ goto err1;
+
+ if ((r = hwa742.extif->init(fbdev)) < 0)
+ goto err2;
+
+ ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
+ if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
+ goto err3;
+ hwa742.extif->set_timings(&hwa742.reg_timings);
+ if (hwa742.power_up != NULL)
+ hwa742.power_up(fbdev->dev);
+
+ calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
+ if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
+ goto err4;
+ hwa742.extif->set_timings(&hwa742.reg_timings);
+
+ rev = hwa742_read_reg(HWA742_REV_CODE_REG);
+ if ((rev & 0xfc) != 0x80) {
+ dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev);
+ r = -ENODEV;
+ goto err4;
+ }
+
+
+ if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) {
+ dev_err(fbdev->dev,
+ "HWA742: controller not initialized by the bootloader\n");
+ r = -ENODEV;
+ goto err4;
+ }
+
+ if (ctrl_conf->te_connected) {
+ if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
+ dev_err(hwa742.fbdev->dev,
+ "HWA742: can't setup tearing synchronization\n");
+ goto err4;
+ }
+ hwa742.te_connected = 1;
+ }
+
+ hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
+
+ hwa742.update_mode = OMAPFB_UPDATE_DISABLED;
+
+ hwa742.auto_update_window.x = 0;
+ hwa742.auto_update_window.y = 0;
+ hwa742.auto_update_window.width = fbdev->panel->x_res;
+ hwa742.auto_update_window.height = fbdev->panel->y_res;
+ hwa742.auto_update_window.format = 0;
+
+ init_timer(&hwa742.auto_update_timer);
+ hwa742.auto_update_timer.function = hwa742_update_window_auto;
+ hwa742.auto_update_timer.data = 0;
+
+ hwa742.prev_color_mode = -1;
+ hwa742.prev_flags = 0;
+
+ hwa742.fbdev = fbdev;
+
+ INIT_LIST_HEAD(&hwa742.free_req_list);
+ INIT_LIST_HEAD(&hwa742.pending_req_list);
+ for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++)
+ list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list);
+ BUG_ON(i <= IRQ_REQ_POOL_SIZE);
+ sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE);
+
+ conf = hwa742_read_reg(HWA742_CONFIG_REG);
+ dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+
+ return 0;
+err4:
+ if (hwa742.power_down != NULL)
+ hwa742.power_down(fbdev->dev);
+err3:
+ hwa742.extif->cleanup();
+err2:
+ hwa742.int_ctrl->cleanup();
+err1:
+ return r;
+}
+
+static void hwa742_cleanup(void)
+{
+ hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
+ hwa742.extif->cleanup();
+ hwa742.int_ctrl->cleanup();
+ if (hwa742.power_down != NULL)
+ hwa742.power_down(hwa742.fbdev->dev);
+}
+
+struct lcd_ctrl hwa742_ctrl = {
+ .name = "hwa742",
+ .init = hwa742_init,
+ .cleanup = hwa742_cleanup,
+ .bind_client = hwa742_bind_client,
+ .get_caps = hwa742_get_caps,
+ .set_update_mode = hwa742_set_update_mode,
+ .get_update_mode = hwa742_get_update_mode,
+ .setup_plane = hwa742_setup_plane,
+ .enable_plane = hwa742_enable_plane,
+ .update_window = hwa742_update_window_async,
+ .sync = hwa742_sync,
+ .suspend = hwa742_suspend,
+ .resume = hwa742_resume,
+};
+
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
new file mode 100644
index 000000000000..51807b4e26d1
--- /dev/null
+++ b/drivers/video/omap/lcd_h3.c
@@ -0,0 +1,141 @@
+/*
+ * LCD panel support for the TI OMAP H3 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME "omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void h3_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h3_panel_enable(struct lcd_panel *panel)
+{
+ int r = 0;
+
+ /* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+ r = tps65010_set_gpio_out_value(GPIO1, HIGH);
+ if (!r)
+ r = tps65010_set_gpio_out_value(GPIO2, HIGH);
+ if (r)
+ pr_err("Unable to turn on LCD panel\n");
+
+ return r;
+}
+
+static void h3_panel_disable(struct lcd_panel *panel)
+{
+ int r = 0;
+
+ /* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+ r = tps65010_set_gpio_out_value(GPIO1, LOW);
+ if (!r)
+ tps65010_set_gpio_out_value(GPIO2, LOW);
+ if (r)
+ pr_err("Unable to turn off LCD panel\n");
+}
+
+static unsigned long h3_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel h3_panel = {
+ .name = "h3",
+ .config = OMAP_LCDC_PANEL_TFT,
+
+ .data_lines = 16,
+ .bpp = 16,
+ .x_res = 240,
+ .y_res = 320,
+ .pixel_clock = 12000,
+ .hsw = 12,
+ .hfp = 14,
+ .hbp = 72 - 12,
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 0,
+ .pcd = 0,
+
+ .init = h3_panel_init,
+ .cleanup = h3_panel_cleanup,
+ .enable = h3_panel_enable,
+ .disable = h3_panel_disable,
+ .get_caps = h3_panel_get_caps,
+};
+
+static int h3_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&h3_panel);
+ return 0;
+}
+
+static int h3_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int h3_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver h3_panel_driver = {
+ .probe = h3_panel_probe,
+ .remove = h3_panel_remove,
+ .suspend = h3_panel_suspend,
+ .resume = h3_panel_resume,
+ .driver = {
+ .name = "lcd_h3",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int h3_panel_drv_init(void)
+{
+ return platform_driver_register(&h3_panel_driver);
+}
+
+static void h3_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&h3_panel_driver);
+}
+
+module_init(h3_panel_drv_init);
+module_exit(h3_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
new file mode 100644
index 000000000000..fd6f0eb16de1
--- /dev/null
+++ b/drivers/video/omap/lcd_h4.c
@@ -0,0 +1,117 @@
+/*
+ * LCD panel support for the TI OMAP H4 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/platform_device.h>
+
+#include <asm/arch/omapfb.h>
+
+static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void h4_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int h4_panel_enable(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+static void h4_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel h4_panel = {
+ .name = "h4",
+ .config = OMAP_LCDC_PANEL_TFT,
+
+ .bpp = 16,
+ .data_lines = 16,
+ .x_res = 240,
+ .y_res = 320,
+ .pixel_clock = 6250,
+ .hsw = 15,
+ .hfp = 15,
+ .hbp = 60,
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 1,
+
+ .init = h4_panel_init,
+ .cleanup = h4_panel_cleanup,
+ .enable = h4_panel_enable,
+ .disable = h4_panel_disable,
+ .get_caps = h4_panel_get_caps,
+};
+
+static int h4_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&h4_panel);
+ return 0;
+}
+
+static int h4_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int h4_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver h4_panel_driver = {
+ .probe = h4_panel_probe,
+ .remove = h4_panel_remove,
+ .suspend = h4_panel_suspend,
+ .resume = h4_panel_resume,
+ .driver = {
+ .name = "lcd_h4",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int h4_panel_drv_init(void)
+{
+ return platform_driver_register(&h4_panel_driver);
+}
+
+static void h4_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&h4_panel_driver);
+}
+
+module_init(h4_panel_drv_init);
+module_exit(h4_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
new file mode 100644
index 000000000000..551f385861d1
--- /dev/null
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -0,0 +1,124 @@
+/*
+ * LCD panel support for the TI OMAP1510 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+static int innovator1510_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void innovator1510_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int innovator1510_panel_enable(struct lcd_panel *panel)
+{
+ fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ return 0;
+}
+
+static void innovator1510_panel_disable(struct lcd_panel *panel)
+{
+ fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+}
+
+static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel innovator1510_panel = {
+ .name = "inn1510",
+ .config = OMAP_LCDC_PANEL_TFT,
+
+ .bpp = 16,
+ .data_lines = 16,
+ .x_res = 240,
+ .y_res = 320,
+ .pixel_clock = 12500,
+ .hsw = 40,
+ .hfp = 40,
+ .hbp = 72,
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 0,
+ .pcd = 12,
+
+ .init = innovator1510_panel_init,
+ .cleanup = innovator1510_panel_cleanup,
+ .enable = innovator1510_panel_enable,
+ .disable = innovator1510_panel_disable,
+ .get_caps = innovator1510_panel_get_caps,
+};
+
+static int innovator1510_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&innovator1510_panel);
+ return 0;
+}
+
+static int innovator1510_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int innovator1510_panel_suspend(struct platform_device *pdev,
+ pm_message_t mesg)
+{
+ return 0;
+}
+
+static int innovator1510_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver innovator1510_panel_driver = {
+ .probe = innovator1510_panel_probe,
+ .remove = innovator1510_panel_remove,
+ .suspend = innovator1510_panel_suspend,
+ .resume = innovator1510_panel_resume,
+ .driver = {
+ .name = "lcd_inn1510",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int innovator1510_panel_drv_init(void)
+{
+ return platform_driver_register(&innovator1510_panel_driver);
+}
+
+static void innovator1510_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&innovator1510_panel_driver);
+}
+
+module_init(innovator1510_panel_drv_init);
+module_exit(innovator1510_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
new file mode 100644
index 000000000000..95604ca43301
--- /dev/null
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -0,0 +1,150 @@
+/*
+ * LCD panel support for the TI OMAP1610 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME "omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int innovator1610_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+{
+ int r = 0;
+
+ if (omap_request_gpio(14)) {
+ pr_err("can't request GPIO 14\n");
+ r = -1;
+ goto exit;
+ }
+ if (omap_request_gpio(15)) {
+ pr_err("can't request GPIO 15\n");
+ omap_free_gpio(14);
+ r = -1;
+ goto exit;
+ }
+ /* configure GPIO(14, 15) as outputs */
+ omap_set_gpio_direction(14, 0);
+ omap_set_gpio_direction(15, 0);
+exit:
+ return r;
+}
+
+static void innovator1610_panel_cleanup(struct lcd_panel *panel)
+{
+ omap_free_gpio(15);
+ omap_free_gpio(14);
+}
+
+static int innovator1610_panel_enable(struct lcd_panel *panel)
+{
+ /* set GPIO14 and GPIO15 high */
+ omap_set_gpio_dataout(14, 1);
+ omap_set_gpio_dataout(15, 1);
+ return 0;
+}
+
+static void innovator1610_panel_disable(struct lcd_panel *panel)
+{
+ /* set GPIO13, GPIO14 and GPIO15 low */
+ omap_set_gpio_dataout(14, 0);
+ omap_set_gpio_dataout(15, 0);
+}
+
+static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel innovator1610_panel = {
+ .name = "inn1610",
+ .config = OMAP_LCDC_PANEL_TFT,
+
+ .bpp = 16,
+ .data_lines = 16,
+ .x_res = 320,
+ .y_res = 240,
+ .pixel_clock = 12500,
+ .hsw = 40,
+ .hfp = 40,
+ .hbp = 72,
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 0,
+ .pcd = 12,
+
+ .init = innovator1610_panel_init,
+ .cleanup = innovator1610_panel_cleanup,
+ .enable = innovator1610_panel_enable,
+ .disable = innovator1610_panel_disable,
+ .get_caps = innovator1610_panel_get_caps,
+};
+
+static int innovator1610_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&innovator1610_panel);
+ return 0;
+}
+
+static int innovator1610_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int innovator1610_panel_suspend(struct platform_device *pdev,
+ pm_message_t mesg)
+{
+ return 0;
+}
+
+static int innovator1610_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver innovator1610_panel_driver = {
+ .probe = innovator1610_panel_probe,
+ .remove = innovator1610_panel_remove,
+ .suspend = innovator1610_panel_suspend,
+ .resume = innovator1610_panel_resume,
+ .driver = {
+ .name = "lcd_inn1610",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int innovator1610_panel_drv_init(void)
+{
+ return platform_driver_register(&innovator1610_panel_driver);
+}
+
+static void innovator1610_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&innovator1610_panel_driver);
+}
+
+module_init(innovator1610_panel_drv_init);
+module_exit(innovator1610_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
new file mode 100644
index 000000000000..a38038840fd6
--- /dev/null
+++ b/drivers/video/omap/lcd_osk.c
@@ -0,0 +1,144 @@
+/*
+ * LCD panel support for the TI OMAP OSK board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ * Adapted for OSK by <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This 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/platform_device.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
+
+static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void osk_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int osk_panel_enable(struct lcd_panel *panel)
+{
+ /* configure PWL pin */
+ omap_cfg_reg(PWL);
+
+ /* Enable PWL unit */
+ omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
+
+ /* Set PWL level */
+ omap_writeb(0xFF, OMAP_PWL_ENABLE);
+
+ /* configure GPIO2 as output */
+ omap_set_gpio_direction(2, 0);
+
+ /* set GPIO2 high */
+ omap_set_gpio_dataout(2, 1);
+
+ return 0;
+}
+
+static void osk_panel_disable(struct lcd_panel *panel)
+{
+ /* Set PWL level to zero */
+ omap_writeb(0x00, OMAP_PWL_ENABLE);
+
+ /* Disable PWL unit */
+ omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
+
+ /* set GPIO2 low */
+ omap_set_gpio_dataout(2, 0);
+}
+
+static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel osk_panel = {
+ .name = "osk",
+ .config = OMAP_LCDC_PANEL_TFT,
+
+ .bpp = 16,
+ .data_lines = 16,
+ .x_res = 240,
+ .y_res = 320,
+ .pixel_clock = 12500,
+ .hsw = 40,
+ .hfp = 40,
+ .hbp = 72,
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 0,
+ .pcd = 12,
+
+ .init = osk_panel_init,
+ .cleanup = osk_panel_cleanup,
+ .enable = osk_panel_enable,
+ .disable = osk_panel_disable,
+ .get_caps = osk_panel_get_caps,
+};
+
+static int osk_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&osk_panel);
+ return 0;
+}
+
+static int osk_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int osk_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver osk_panel_driver = {
+ .probe = osk_panel_probe,
+ .remove = osk_panel_remove,
+ .suspend = osk_panel_suspend,
+ .resume = osk_panel_resume,
+ .driver = {
+ .name = "lcd_osk",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int osk_panel_drv_init(void)
+{
+ return platform_driver_register(&osk_panel_driver);
+}
+
+static void osk_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&osk_panel_driver);
+}
+
+module_init(osk_panel_drv_init);
+module_exit(osk_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
new file mode 100644
index 000000000000..52bdfdac42c9
--- /dev/null
+++ b/drivers/video/omap/lcd_palmte.c
@@ -0,0 +1,123 @@
+/*
+ * LCD panel support for the Palm Tungsten E
+ *
+ * Original version : Romain Goyet <r.goyet@gmail.com>
+ * Current version : Laurent Gonzalez <palmte.linux@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+static int palmte_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void palmte_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmte_panel_enable(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+static void palmte_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel palmte_panel = {
+ .name = "palmte",
+ .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+ OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+ OMAP_LCDC_HSVS_OPPOSITE,
+
+ .data_lines = 16,
+ .bpp = 8,
+ .pixel_clock = 12000,
+ .x_res = 320,
+ .y_res = 320,
+ .hsw = 4,
+ .hfp = 8,
+ .hbp = 28,
+ .vsw = 1,
+ .vfp = 8,
+ .vbp = 7,
+ .pcd = 0,
+
+ .init = palmte_panel_init,
+ .cleanup = palmte_panel_cleanup,
+ .enable = palmte_panel_enable,
+ .disable = palmte_panel_disable,
+ .get_caps = palmte_panel_get_caps,
+};
+
+static int palmte_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&palmte_panel);
+ return 0;
+}
+
+static int palmte_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int palmte_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver palmte_panel_driver = {
+ .probe = palmte_panel_probe,
+ .remove = palmte_panel_remove,
+ .suspend = palmte_panel_suspend,
+ .resume = palmte_panel_resume,
+ .driver = {
+ .name = "lcd_palmte",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int palmte_panel_drv_init(void)
+{
+ return platform_driver_register(&palmte_panel_driver);
+}
+
+static void palmte_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&palmte_panel_driver);
+}
+
+module_init(palmte_panel_drv_init);
+module_exit(palmte_panel_drv_cleanup);
+
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
new file mode 100644
index 000000000000..4bb349f54356
--- /dev/null
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -0,0 +1,127 @@
+/*
+ * LCD panel support for Palm Tungsten|T
+ * Current version : Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Modified from lcd_inn1510.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+GPIO11 - backlight
+GPIO12 - screen blanking
+GPIO13 - screen blanking
+*/
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+static int palmtt_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void palmtt_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static int palmtt_panel_enable(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+static void palmtt_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmtt_panel_get_caps(struct lcd_panel *panel)
+{
+ return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmtt_panel = {
+ .name = "palmtt",
+ .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+ OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+ OMAP_LCDC_HSVS_OPPOSITE,
+ .bpp = 16,
+ .data_lines = 16,
+ .x_res = 320,
+ .y_res = 320,
+ .pixel_clock = 10000,
+ .hsw = 4,
+ .hfp = 8,
+ .hbp = 28,
+ .vsw = 1,
+ .vfp = 8,
+ .vbp = 7,
+ .pcd = 0,
+
+ .init = palmtt_panel_init,
+ .cleanup = palmtt_panel_cleanup,
+ .enable = palmtt_panel_enable,
+ .disable = palmtt_panel_disable,
+ .get_caps = palmtt_panel_get_caps,
+};
+
+static int palmtt_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&palmtt_panel);
+ return 0;
+}
+
+static int palmtt_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int palmtt_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int palmtt_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver palmtt_panel_driver = {
+ .probe = palmtt_panel_probe,
+ .remove = palmtt_panel_remove,
+ .suspend = palmtt_panel_suspend,
+ .resume = palmtt_panel_resume,
+ .driver = {
+ .name = "lcd_palmtt",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int palmtt_panel_drv_init(void)
+{
+ return platform_driver_register(&palmtt_panel_driver);
+}
+
+static void palmtt_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&palmtt_panel_driver);
+}
+
+module_init(palmtt_panel_drv_init);
+module_exit(palmtt_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
new file mode 100644
index 000000000000..ea6170ddff35
--- /dev/null
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -0,0 +1,123 @@
+/*
+ * LCD panel support for the Palm Zire71
+ *
+ * Original version : Romain Goyet
+ * Current version : Laurent Gonzalez
+ * Modified for zire71 : Marek Vasut
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License 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/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/arch/omapfb.h>
+
+static int palmz71_panel_init(struct lcd_panel *panel,
+ struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void palmz71_panel_cleanup(struct lcd_panel *panel)
+{
+
+}
+
+static int palmz71_panel_enable(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+static void palmz71_panel_disable(struct lcd_panel *panel)
+{
+}
+
+static unsigned long palmz71_panel_get_caps(struct lcd_panel *panel)
+{
+ return OMAPFB_CAPS_SET_BACKLIGHT;
+}
+
+struct lcd_panel palmz71_panel = {
+ .name = "palmz71",
+ .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+ OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+ OMAP_LCDC_HSVS_OPPOSITE,
+ .data_lines = 16,
+ .bpp = 16,
+ .pixel_clock = 24000,
+ .x_res = 320,
+ .y_res = 320,
+ .hsw = 4,
+ .hfp = 8,
+ .hbp = 28,
+ .vsw = 1,
+ .vfp = 8,
+ .vbp = 7,
+ .pcd = 0,
+
+ .init = palmz71_panel_init,
+ .cleanup = palmz71_panel_cleanup,
+ .enable = palmz71_panel_enable,
+ .disable = palmz71_panel_disable,
+ .get_caps = palmz71_panel_get_caps,
+};
+
+static int palmz71_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&palmz71_panel);
+ return 0;
+}
+
+static int palmz71_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int palmz71_panel_suspend(struct platform_device *pdev,
+ pm_message_t mesg)
+{
+ return 0;
+}
+
+static int palmz71_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver palmz71_panel_driver = {
+ .probe = palmz71_panel_probe,
+ .remove = palmz71_panel_remove,
+ .suspend = palmz71_panel_suspend,
+ .resume = palmz71_panel_resume,
+ .driver = {
+ .name = "lcd_palmz71",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int palmz71_panel_drv_init(void)
+{
+ return platform_driver_register(&palmz71_panel_driver);
+}
+
+static void palmz71_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&palmz71_panel_driver);
+}
+
+module_init(palmz71_panel_drv_init);
+module_exit(palmz71_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c
new file mode 100644
index 000000000000..c4f306a4e5c9
--- /dev/null
+++ b/drivers/video/omap/lcd_sx1.c
@@ -0,0 +1,334 @@
+/*
+ * LCD panel support for the Siemens SX1 mobile phone
+ *
+ * Current version : Vovan888@gmail.com, great help from FCA00000
+ *
+ * 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/mux.h>
+
+/*
+ * OMAP310 GPIO registers
+ */
+#define GPIO_DATA_INPUT 0xfffce000
+#define GPIO_DATA_OUTPUT 0xfffce004
+#define GPIO_DIR_CONTROL 0xfffce008
+#define GPIO_INT_CONTROL 0xfffce00c
+#define GPIO_INT_MASK 0xfffce010
+#define GPIO_INT_STATUS 0xfffce014
+#define GPIO_PIN_CONTROL 0xfffce018
+
+
+#define A_LCD_SSC_RD 3
+#define A_LCD_SSC_SD 7
+#define _A_LCD_RESET 9
+#define _A_LCD_SSC_CS 12
+#define _A_LCD_SSC_A0 13
+
+#define DSP_REG 0xE1017024
+
+const unsigned char INIT_1[12] = {
+ 0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00
+};
+
+const unsigned char INIT_2[127] = {
+ 0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00,
+ 0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00,
+ 0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00,
+ 0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01,
+ 0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01,
+ 0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01,
+ 0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01,
+ 0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01,
+ 0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01,
+ 0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01,
+ 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01,
+ 0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01,
+ 0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01,
+ 0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01,
+ 0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02,
+ 0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00
+};
+
+const unsigned char INIT_3[15] = {
+ 0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59,
+ 0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF
+};
+
+static void epson_sendbyte(int flag, unsigned char byte)
+{
+ int i, shifter = 0x80;
+
+ if (!flag)
+ omap_set_gpio_dataout(_A_LCD_SSC_A0, 0);
+ mdelay(2);
+ omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+
+ omap_set_gpio_dataout(A_LCD_SSC_SD, flag);
+
+ OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
+ OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
+ for (i = 0; i < 8; i++) {
+ OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
+ omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte);
+ OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
+ shifter >>= 1;
+ }
+ omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+}
+
+static void init_system(void)
+{
+ omap_mcbsp_request(OMAP_MCBSP3);
+ omap_mcbsp_stop(OMAP_MCBSP3);
+}
+
+static void setup_GPIO(void)
+{
+ /* new wave */
+ omap_request_gpio(A_LCD_SSC_RD);
+ omap_request_gpio(A_LCD_SSC_SD);
+ omap_request_gpio(_A_LCD_RESET);
+ omap_request_gpio(_A_LCD_SSC_CS);
+ omap_request_gpio(_A_LCD_SSC_A0);
+
+ /* set all GPIOs to output */
+ omap_set_gpio_direction(A_LCD_SSC_RD, 0);
+ omap_set_gpio_direction(A_LCD_SSC_SD, 0);
+ omap_set_gpio_direction(_A_LCD_RESET, 0);
+ omap_set_gpio_direction(_A_LCD_SSC_CS, 0);
+ omap_set_gpio_direction(_A_LCD_SSC_A0, 0);
+
+ /* set GPIO data */
+ omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+ omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
+ omap_set_gpio_dataout(_A_LCD_RESET, 0);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+}
+
+static void display_init(void)
+{
+ int i;
+
+ omap_cfg_reg(MCBSP3_CLKX);
+
+ mdelay(2);
+ setup_GPIO();
+ mdelay(2);
+
+ /* reset LCD */
+ omap_set_gpio_dataout(A_LCD_SSC_SD, 1);
+ epson_sendbyte(0, 0x25);
+
+ omap_set_gpio_dataout(_A_LCD_RESET, 0);
+ mdelay(10);
+ omap_set_gpio_dataout(_A_LCD_RESET, 1);
+
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ mdelay(2);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD, phase 1 */
+ epson_sendbyte(0, 0xCA);
+ for (i = 0; i < 10; i++)
+ epson_sendbyte(1, INIT_1[i]);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 2 */
+ epson_sendbyte(0, 0xCB);
+ for (i = 0; i < 125; i++)
+ epson_sendbyte(1, INIT_2[i]);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 2a */
+ epson_sendbyte(0, 0xCC);
+ for (i = 0; i < 14; i++)
+ epson_sendbyte(1, INIT_3[i]);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 3 */
+ epson_sendbyte(0, 0xBC);
+ epson_sendbyte(1, 0x08);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 4 */
+ epson_sendbyte(0, 0x07);
+ epson_sendbyte(1, 0x05);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 5 */
+ epson_sendbyte(0, 0x94);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 6 */
+ epson_sendbyte(0, 0xC6);
+ epson_sendbyte(1, 0x80);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ mdelay(100); /* used to be 1000 */
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 7 */
+ epson_sendbyte(0, 0x16);
+ epson_sendbyte(1, 0x02);
+ epson_sendbyte(1, 0x00);
+ epson_sendbyte(1, 0xB1);
+ epson_sendbyte(1, 0x00);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 8 */
+ epson_sendbyte(0, 0x76);
+ epson_sendbyte(1, 0x00);
+ epson_sendbyte(1, 0x00);
+ epson_sendbyte(1, 0xDB);
+ epson_sendbyte(1, 0x00);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ /* init LCD phase 9 */
+ epson_sendbyte(0, 0xAF);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+}
+
+static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
+{
+ return 0;
+}
+
+static void sx1_panel_cleanup(struct lcd_panel *panel)
+{
+}
+
+static void sx1_panel_disable(struct lcd_panel *panel)
+{
+ printk(KERN_INFO "SX1: LCD panel disable\n");
+ sx1_setmmipower(0);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+
+ epson_sendbyte(0, 0x25);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ epson_sendbyte(0, 0xAE);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+ mdelay(100);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+
+ epson_sendbyte(0, 0x95);
+ omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+}
+
+static int sx1_panel_enable(struct lcd_panel *panel)
+{
+ printk(KERN_INFO "lcd_sx1: LCD panel enable\n");
+ init_system();
+ display_init();
+
+ sx1_setmmipower(1);
+ sx1_setbacklight(0x18);
+ sx1_setkeylight (0x06);
+ return 0;
+}
+
+
+static unsigned long sx1_panel_get_caps(struct lcd_panel *panel)
+{
+ return 0;
+}
+
+struct lcd_panel sx1_panel = {
+ .name = "sx1",
+ .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+ OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK |
+ OMAP_LCDC_INV_OUTPUT_EN,
+
+ .x_res = 176,
+ .y_res = 220,
+ .data_lines = 16,
+ .bpp = 16,
+ .hsw = 5,
+ .hfp = 5,
+ .hbp = 5,
+ .vsw = 2,
+ .vfp = 1,
+ .vbp = 1,
+ .pixel_clock = 1500,
+
+ .init = sx1_panel_init,
+ .cleanup = sx1_panel_cleanup,
+ .enable = sx1_panel_enable,
+ .disable = sx1_panel_disable,
+ .get_caps = sx1_panel_get_caps,
+};
+
+static int sx1_panel_probe(struct platform_device *pdev)
+{
+ omapfb_register_panel(&sx1_panel);
+ return 0;
+}
+
+static int sx1_panel_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int sx1_panel_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver sx1_panel_driver = {
+ .probe = sx1_panel_probe,
+ .remove = sx1_panel_remove,
+ .suspend = sx1_panel_suspend,
+ .resume = sx1_panel_resume,
+ .driver = {
+ .name = "lcd_sx1",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int sx1_panel_drv_init(void)
+{
+ return platform_driver_register(&sx1_panel_driver);
+}
+
+static void sx1_panel_drv_cleanup(void)
+{
+ platform_driver_unregister(&sx1_panel_driver);
+}
+
+module_init(sx1_panel_drv_init);
+module_exit(sx1_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
new file mode 100644
index 000000000000..9085188d815e
--- /dev/null
+++ b/drivers/video/omap/lcdc.c
@@ -0,0 +1,893 @@
+/*
+ * OMAP1 internal LCD controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include <asm/mach-types.h>
+
+#define MODULE_NAME "lcdc"
+
+#define OMAP_LCDC_BASE 0xfffec000
+#define OMAP_LCDC_SIZE 256
+#define OMAP_LCDC_IRQ INT_LCD_CTRL
+
+#define OMAP_LCDC_CONTROL (OMAP_LCDC_BASE + 0x00)
+#define OMAP_LCDC_TIMING0 (OMAP_LCDC_BASE + 0x04)
+#define OMAP_LCDC_TIMING1 (OMAP_LCDC_BASE + 0x08)
+#define OMAP_LCDC_TIMING2 (OMAP_LCDC_BASE + 0x0c)
+#define OMAP_LCDC_STATUS (OMAP_LCDC_BASE + 0x10)
+#define OMAP_LCDC_SUBPANEL (OMAP_LCDC_BASE + 0x14)
+#define OMAP_LCDC_LINE_INT (OMAP_LCDC_BASE + 0x18)
+#define OMAP_LCDC_DISPLAY_STATUS (OMAP_LCDC_BASE + 0x1c)
+
+#define OMAP_LCDC_STAT_DONE (1 << 0)
+#define OMAP_LCDC_STAT_VSYNC (1 << 1)
+#define OMAP_LCDC_STAT_SYNC_LOST (1 << 2)
+#define OMAP_LCDC_STAT_ABC (1 << 3)
+#define OMAP_LCDC_STAT_LINE_INT (1 << 4)
+#define OMAP_LCDC_STAT_FUF (1 << 5)
+#define OMAP_LCDC_STAT_LOADED_PALETTE (1 << 6)
+
+#define OMAP_LCDC_CTRL_LCD_EN (1 << 0)
+#define OMAP_LCDC_CTRL_LCD_TFT (1 << 7)
+#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL (1 << 10)
+
+#define OMAP_LCDC_IRQ_VSYNC (1 << 2)
+#define OMAP_LCDC_IRQ_DONE (1 << 3)
+#define OMAP_LCDC_IRQ_LOADED_PALETTE (1 << 4)
+#define OMAP_LCDC_IRQ_LINE_NIRQ (1 << 5)
+#define OMAP_LCDC_IRQ_LINE (1 << 6)
+#define OMAP_LCDC_IRQ_MASK (((1 << 5) - 1) << 2)
+
+#define MAX_PALETTE_SIZE PAGE_SIZE
+
+enum lcdc_load_mode {
+ OMAP_LCDC_LOAD_PALETTE,
+ OMAP_LCDC_LOAD_FRAME,
+ OMAP_LCDC_LOAD_PALETTE_AND_FRAME
+};
+
+static struct omap_lcd_controller {
+ enum omapfb_update_mode update_mode;
+ int ext_mode;
+
+ unsigned long frame_offset;
+ int screen_width;
+ int xres;
+ int yres;
+
+ enum omapfb_color_format color_mode;
+ int bpp;
+ void *palette_virt;
+ dma_addr_t palette_phys;
+ int palette_code;
+ int palette_size;
+
+ unsigned int irq_mask;
+ struct completion last_frame_complete;
+ struct completion palette_load_complete;
+ struct clk *lcd_ck;
+ struct omapfb_device *fbdev;
+
+ void (*dma_callback)(void *data);
+ void *dma_callback_data;
+
+ int fbmem_allocated;
+ dma_addr_t vram_phys;
+ void *vram_virt;
+ unsigned long vram_size;
+} lcdc;
+
+static void inline enable_irqs(int mask)
+{
+ lcdc.irq_mask |= mask;
+}
+
+static void inline disable_irqs(int mask)
+{
+ lcdc.irq_mask &= ~mask;
+}
+
+static void set_load_mode(enum lcdc_load_mode mode)
+{
+ u32 l;
+
+ l = omap_readl(OMAP_LCDC_CONTROL);
+ l &= ~(3 << 20);
+ switch (mode) {
+ case OMAP_LCDC_LOAD_PALETTE:
+ l |= 1 << 20;
+ break;
+ case OMAP_LCDC_LOAD_FRAME:
+ l |= 2 << 20;
+ break;
+ case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
+ break;
+ default:
+ BUG();
+ }
+ omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void enable_controller(void)
+{
+ u32 l;
+
+ l = omap_readl(OMAP_LCDC_CONTROL);
+ l |= OMAP_LCDC_CTRL_LCD_EN;
+ l &= ~OMAP_LCDC_IRQ_MASK;
+ l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE; /* enabled IRQs */
+ omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller_async(void)
+{
+ u32 l;
+ u32 mask;
+
+ l = omap_readl(OMAP_LCDC_CONTROL);
+ mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
+ /*
+ * Preserve the DONE mask, since we still want to get the
+ * final DONE irq. It will be disabled in the IRQ handler.
+ */
+ mask &= ~OMAP_LCDC_IRQ_DONE;
+ l &= ~mask;
+ omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller(void)
+{
+ init_completion(&lcdc.last_frame_complete);
+ disable_controller_async();
+ if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
+ msecs_to_jiffies(500)))
+ dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+}
+
+static void reset_controller(u32 status)
+{
+ static unsigned long reset_count;
+ static unsigned long last_jiffies;
+
+ disable_controller_async();
+ reset_count++;
+ if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
+ dev_err(lcdc.fbdev->dev,
+ "resetting (status %#010x,reset count %lu)\n",
+ status, reset_count);
+ last_jiffies = jiffies;
+ }
+ if (reset_count < 100) {
+ enable_controller();
+ } else {
+ reset_count = 0;
+ dev_err(lcdc.fbdev->dev,
+ "too many reset attempts, giving up.\n");
+ }
+}
+
+/*
+ * Configure the LCD DMA according to the current mode specified by parameters
+ * in lcdc.fbdev and fbdev->var.
+ */
+static void setup_lcd_dma(void)
+{
+ static const int dma_elem_type[] = {
+ 0,
+ OMAP_DMA_DATA_TYPE_S8,
+ OMAP_DMA_DATA_TYPE_S16,
+ 0,
+ OMAP_DMA_DATA_TYPE_S32,
+ };
+ struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
+ struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+ unsigned long src;
+ int esize, xelem, yelem;
+
+ src = lcdc.vram_phys + lcdc.frame_offset;
+
+ switch (var->rotate) {
+ case 0:
+ if (plane->info.mirror || (src & 3) ||
+ lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
+ (lcdc.xres & 1))
+ esize = 2;
+ else
+ esize = 4;
+ xelem = lcdc.xres * lcdc.bpp / 8 / esize;
+ yelem = lcdc.yres;
+ break;
+ case 90:
+ case 180:
+ case 270:
+ if (cpu_is_omap15xx()) {
+ BUG();
+ }
+ esize = 2;
+ xelem = lcdc.yres * lcdc.bpp / 16;
+ yelem = lcdc.xres;
+ break;
+ default:
+ BUG();
+ return;
+ }
+#ifdef VERBOSE
+ dev_dbg(lcdc.fbdev->dev,
+ "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
+ src, esize, xelem, yelem);
+#endif
+ omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
+ if (!cpu_is_omap15xx()) {
+ int bpp = lcdc.bpp;
+
+ /*
+ * YUV support is only for external mode when we have the
+ * YUV window embedded in a 16bpp frame buffer.
+ */
+ if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
+ bpp = 16;
+ /* Set virtual xres elem size */
+ omap_set_lcd_dma_b1_vxres(
+ lcdc.screen_width * bpp / 8 / esize);
+ /* Setup transformations */
+ omap_set_lcd_dma_b1_rotation(var->rotate);
+ omap_set_lcd_dma_b1_mirror(plane->info.mirror);
+ }
+ omap_setup_lcd_dma();
+}
+
+static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
+{
+ u32 status;
+
+ status = omap_readl(OMAP_LCDC_STATUS);
+
+ if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
+ reset_controller(status);
+ else {
+ if (status & OMAP_LCDC_STAT_DONE) {
+ u32 l;
+
+ /*
+ * Disable IRQ_DONE. The status bit will be cleared
+ * only when the controller is reenabled and we don't
+ * want to get more interrupts.
+ */
+ l = omap_readl(OMAP_LCDC_CONTROL);
+ l &= ~OMAP_LCDC_IRQ_DONE;
+ omap_writel(l, OMAP_LCDC_CONTROL);
+ complete(&lcdc.last_frame_complete);
+ }
+ if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
+ disable_controller_async();
+ complete(&lcdc.palette_load_complete);
+ }
+ }
+
+ /*
+ * Clear these interrupt status bits.
+ * Sync_lost, FUF bits were cleared by disabling the LCD controller
+ * LOADED_PALETTE can be cleared this way only in palette only
+ * load mode. In other load modes it's cleared by disabling the
+ * controller.
+ */
+ status &= ~(OMAP_LCDC_STAT_VSYNC |
+ OMAP_LCDC_STAT_LOADED_PALETTE |
+ OMAP_LCDC_STAT_ABC |
+ OMAP_LCDC_STAT_LINE_INT);
+ omap_writel(status, OMAP_LCDC_STATUS);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Change to a new video mode. We defer this to a later time to avoid any
+ * flicker and not to mess up the current LCD DMA context. For this we disable
+ * the LCD controler, which will generate a DONE irq after the last frame has
+ * been transferred. Then it'll be safe to reconfigure both the LCD controller
+ * as well as the LCD DMA.
+ */
+static int omap_lcdc_setup_plane(int plane, int channel_out,
+ unsigned long offset, int screen_width,
+ int pos_x, int pos_y, int width, int height,
+ int color_mode)
+{
+ struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
+ struct lcd_panel *panel = lcdc.fbdev->panel;
+ int rot_x, rot_y;
+
+ if (var->rotate == 0) {
+ rot_x = panel->x_res;
+ rot_y = panel->y_res;
+ } else {
+ rot_x = panel->y_res;
+ rot_y = panel->x_res;
+ }
+ if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
+ width > rot_x || height > rot_y) {
+#ifdef VERBOSE
+ dev_dbg(lcdc.fbdev->dev,
+ "invalid plane params plane %d pos_x %d pos_y %d "
+ "w %d h %d\n", plane, pos_x, pos_y, width, height);
+#endif
+ return -EINVAL;
+ }
+
+ lcdc.frame_offset = offset;
+ lcdc.xres = width;
+ lcdc.yres = height;
+ lcdc.screen_width = screen_width;
+ lcdc.color_mode = color_mode;
+
+ switch (color_mode) {
+ case OMAPFB_COLOR_CLUT_8BPP:
+ lcdc.bpp = 8;
+ lcdc.palette_code = 0x3000;
+ lcdc.palette_size = 512;
+ break;
+ case OMAPFB_COLOR_RGB565:
+ lcdc.bpp = 16;
+ lcdc.palette_code = 0x4000;
+ lcdc.palette_size = 32;
+ break;
+ case OMAPFB_COLOR_RGB444:
+ lcdc.bpp = 16;
+ lcdc.palette_code = 0x4000;
+ lcdc.palette_size = 32;
+ break;
+ case OMAPFB_COLOR_YUV420:
+ if (lcdc.ext_mode) {
+ lcdc.bpp = 12;
+ break;
+ }
+ /* fallthrough */
+ case OMAPFB_COLOR_YUV422:
+ if (lcdc.ext_mode) {
+ lcdc.bpp = 16;
+ break;
+ }
+ /* fallthrough */
+ default:
+ /* FIXME: other BPPs.
+ * bpp1: code 0, size 256
+ * bpp2: code 0x1000 size 256
+ * bpp4: code 0x2000 size 256
+ * bpp12: code 0x4000 size 32
+ */
+ dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
+ BUG();
+ return -1;
+ }
+
+ if (lcdc.ext_mode) {
+ setup_lcd_dma();
+ return 0;
+ }
+
+ if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+ disable_controller();
+ omap_stop_lcd_dma();
+ setup_lcd_dma();
+ enable_controller();
+ }
+
+ return 0;
+}
+
+static int omap_lcdc_enable_plane(int plane, int enable)
+{
+ dev_dbg(lcdc.fbdev->dev,
+ "plane %d enable %d update_mode %d ext_mode %d\n",
+ plane, enable, lcdc.update_mode, lcdc.ext_mode);
+ if (plane != OMAPFB_PLANE_GFX)
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Configure the LCD DMA for a palette load operation and do the palette
+ * downloading synchronously. We don't use the frame+palette load mode of
+ * the controller, since the palette can always be downloaded seperately.
+ */
+static void load_palette(void)
+{
+ u16 *palette;
+
+ palette = (u16 *)lcdc.palette_virt;
+
+ *(u16 *)palette &= 0x0fff;
+ *(u16 *)palette |= lcdc.palette_code;
+
+ omap_set_lcd_dma_b1(lcdc.palette_phys,
+ lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
+
+ omap_set_lcd_dma_single_transfer(1);
+ omap_setup_lcd_dma();
+
+ init_completion(&lcdc.palette_load_complete);
+ enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+ set_load_mode(OMAP_LCDC_LOAD_PALETTE);
+ enable_controller();
+ if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
+ msecs_to_jiffies(500)))
+ dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
+ /* The controller gets disabled in the irq handler */
+ disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+ omap_stop_lcd_dma();
+
+ omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
+}
+
+/* Used only in internal controller mode */
+static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
+ u16 transp, int update_hw_pal)
+{
+ u16 *palette;
+
+ if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
+ return -EINVAL;
+
+ palette = (u16 *)lcdc.palette_virt;
+
+ palette[regno] &= ~0x0fff;
+ palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
+ (blue >> 12);
+
+ if (update_hw_pal) {
+ disable_controller();
+ omap_stop_lcd_dma();
+ load_palette();
+ setup_lcd_dma();
+ set_load_mode(OMAP_LCDC_LOAD_FRAME);
+ enable_controller();
+ }
+
+ return 0;
+}
+
+static void calc_ck_div(int is_tft, int pck, int *pck_div)
+{
+ unsigned long lck;
+
+ pck = max(1, pck);
+ lck = clk_get_rate(lcdc.lcd_ck);
+ *pck_div = (lck + pck - 1) / pck;
+ if (is_tft)
+ *pck_div = max(2, *pck_div);
+ else
+ *pck_div = max(3, *pck_div);
+ if (*pck_div > 255) {
+ /* FIXME: try to adjust logic clock divider as well */
+ *pck_div = 255;
+ dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
+ pck / 1000);
+ }
+}
+
+static void inline setup_regs(void)
+{
+ u32 l;
+ struct lcd_panel *panel = lcdc.fbdev->panel;
+ int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+ unsigned long lck;
+ int pcd;
+
+ l = omap_readl(OMAP_LCDC_CONTROL);
+ l &= ~OMAP_LCDC_CTRL_LCD_TFT;
+ l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
+#ifdef CONFIG_MACH_OMAP_PALMTE
+/* FIXME:if (machine_is_omap_palmte()) { */
+ /* PalmTE uses alternate TFT setting in 8BPP mode */
+ l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;
+/* } */
+#endif
+ omap_writel(l, OMAP_LCDC_CONTROL);
+
+ l = omap_readl(OMAP_LCDC_TIMING2);
+ l &= ~(((1 << 6) - 1) << 20);
+ l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
+ omap_writel(l, OMAP_LCDC_TIMING2);
+
+ l = panel->x_res - 1;
+ l |= (panel->hsw - 1) << 10;
+ l |= (panel->hfp - 1) << 16;
+ l |= (panel->hbp - 1) << 24;
+ omap_writel(l, OMAP_LCDC_TIMING0);
+
+ l = panel->y_res - 1;
+ l |= (panel->vsw - 1) << 10;
+ l |= panel->vfp << 16;
+ l |= panel->vbp << 24;
+ omap_writel(l, OMAP_LCDC_TIMING1);
+
+ l = omap_readl(OMAP_LCDC_TIMING2);
+ l &= ~0xff;
+
+ lck = clk_get_rate(lcdc.lcd_ck);
+
+ if (!panel->pcd)
+ calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
+ else {
+ dev_warn(lcdc.fbdev->dev,
+ "Pixel clock divider value is obsolete.\n"
+ "Try to set pixel_clock to %lu and pcd to 0 "
+ "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
+ lck / panel->pcd / 1000, panel->name);
+
+ pcd = panel->pcd;
+ }
+ l |= pcd & 0xff;
+ l |= panel->acb << 8;
+ omap_writel(l, OMAP_LCDC_TIMING2);
+
+ /* update panel info with the exact clock */
+ panel->pixel_clock = lck / pcd / 1000;
+}
+
+/*
+ * Configure the LCD controller, download the color palette and start a looped
+ * DMA transfer of the frame image data. Called only in internal
+ * controller mode.
+ */
+static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
+{
+ int r = 0;
+
+ if (mode != lcdc.update_mode) {
+ switch (mode) {
+ case OMAPFB_AUTO_UPDATE:
+ setup_regs();
+ load_palette();
+
+ /* Setup and start LCD DMA */
+ setup_lcd_dma();
+
+ set_load_mode(OMAP_LCDC_LOAD_FRAME);
+ enable_irqs(OMAP_LCDC_IRQ_DONE);
+ /* This will start the actual DMA transfer */
+ enable_controller();
+ lcdc.update_mode = mode;
+ break;
+ case OMAPFB_UPDATE_DISABLED:
+ disable_controller();
+ omap_stop_lcd_dma();
+ lcdc.update_mode = mode;
+ break;
+ default:
+ r = -EINVAL;
+ }
+ }
+
+ return r;
+}
+
+static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
+{
+ return lcdc.update_mode;
+}
+
+/* PM code called only in internal controller mode */
+static void omap_lcdc_suspend(void)
+{
+ if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+ disable_controller();
+ omap_stop_lcd_dma();
+ }
+}
+
+static void omap_lcdc_resume(void)
+{
+ if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+ setup_regs();
+ load_palette();
+ setup_lcd_dma();
+ set_load_mode(OMAP_LCDC_LOAD_FRAME);
+ enable_irqs(OMAP_LCDC_IRQ_DONE);
+ enable_controller();
+ }
+}
+
+static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
+{
+ return;
+}
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
+{
+ BUG_ON(callback == NULL);
+
+ if (lcdc.dma_callback)
+ return -EBUSY;
+ else {
+ lcdc.dma_callback = callback;
+ lcdc.dma_callback_data = data;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
+
+void omap_lcdc_free_dma_callback(void)
+{
+ lcdc.dma_callback = NULL;
+}
+EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
+
+static void lcdc_dma_handler(u16 status, void *data)
+{
+ if (lcdc.dma_callback)
+ lcdc.dma_callback(lcdc.dma_callback_data);
+}
+
+static int mmap_kern(void)
+{
+ struct vm_struct *kvma;
+ struct vm_area_struct vma;
+ pgprot_t pgprot;
+ unsigned long vaddr;
+
+ kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP);
+ if (kvma == NULL) {
+ dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n");
+ return -ENOMEM;
+ }
+ vma.vm_mm = &init_mm;
+
+ vaddr = (unsigned long)kvma->addr;
+ vma.vm_start = vaddr;
+ vma.vm_end = vaddr + lcdc.vram_size;
+
+ pgprot = pgprot_writecombine(pgprot_kernel);
+ if (io_remap_pfn_range(&vma, vaddr,
+ lcdc.vram_phys >> PAGE_SHIFT,
+ lcdc.vram_size, pgprot) < 0) {
+ dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n");
+ return -EAGAIN;
+ }
+
+ lcdc.vram_virt = (void *)vaddr;
+
+ return 0;
+}
+
+static void unmap_kern(void)
+{
+ vunmap(lcdc.vram_virt);
+}
+
+static int alloc_palette_ram(void)
+{
+ lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+ MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
+ if (lcdc.palette_virt == NULL) {
+ dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
+ return -ENOMEM;
+ }
+ memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
+
+ return 0;
+}
+
+static void free_palette_ram(void)
+{
+ dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
+ lcdc.palette_virt, lcdc.palette_phys);
+}
+
+static int alloc_fbmem(struct omapfb_mem_region *region)
+{
+ int bpp;
+ int frame_size;
+ struct lcd_panel *panel = lcdc.fbdev->panel;
+
+ bpp = panel->bpp;
+ if (bpp == 12)
+ bpp = 16;
+ frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
+ if (region->size > frame_size)
+ frame_size = region->size;
+ lcdc.vram_size = frame_size;
+ lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
+ lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
+ if (lcdc.vram_virt == NULL) {
+ dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
+ return -ENOMEM;
+ }
+ region->size = frame_size;
+ region->paddr = lcdc.vram_phys;
+ region->vaddr = lcdc.vram_virt;
+ region->alloc = 1;
+
+ memset(lcdc.vram_virt, 0, lcdc.vram_size);
+
+ return 0;
+}
+
+static void free_fbmem(void)
+{
+ dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
+ lcdc.vram_virt, lcdc.vram_phys);
+}
+
+static int setup_fbmem(struct omapfb_mem_desc *req_md)
+{
+ int r;
+
+ if (!req_md->region_cnt) {
+ dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
+ return -EINVAL;
+ }
+
+ if (req_md->region_cnt > 1) {
+ dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
+ req_md->region_cnt = 1;
+ }
+
+ if (req_md->region[0].paddr == 0) {
+ lcdc.fbmem_allocated = 1;
+ if ((r = alloc_fbmem(&req_md->region[0])) < 0)
+ return r;
+ return 0;
+ }
+
+ lcdc.vram_phys = req_md->region[0].paddr;
+ lcdc.vram_size = req_md->region[0].size;
+
+ if ((r = mmap_kern()) < 0)
+ return r;
+
+ dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n",
+ lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt);
+
+ return 0;
+}
+
+static void cleanup_fbmem(void)
+{
+ if (lcdc.fbmem_allocated)
+ free_fbmem();
+ else
+ unmap_kern();
+}
+
+static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
+ struct omapfb_mem_desc *req_vram)
+{
+ int r;
+ u32 l;
+ int rate;
+ struct clk *tc_ck;
+
+ lcdc.irq_mask = 0;
+
+ lcdc.fbdev = fbdev;
+ lcdc.ext_mode = ext_mode;
+
+ l = 0;
+ omap_writel(l, OMAP_LCDC_CONTROL);
+
+ /* FIXME:
+ * According to errata some platforms have a clock rate limitiation
+ */
+ lcdc.lcd_ck = clk_get(NULL, "lcd_ck");
+ if (IS_ERR(lcdc.lcd_ck)) {
+ dev_err(fbdev->dev, "unable to access LCD clock\n");
+ r = PTR_ERR(lcdc.lcd_ck);
+ goto fail0;
+ }
+
+ tc_ck = clk_get(NULL, "tc_ck");
+ if (IS_ERR(tc_ck)) {
+ dev_err(fbdev->dev, "unable to access TC clock\n");
+ r = PTR_ERR(tc_ck);
+ goto fail1;
+ }
+
+ rate = clk_get_rate(tc_ck);
+ clk_put(tc_ck);
+
+ if (machine_is_ams_delta())
+ rate /= 4;
+ if (machine_is_omap_h3())
+ rate /= 3;
+ r = clk_set_rate(lcdc.lcd_ck, rate);
+ if (r) {
+ dev_err(fbdev->dev, "failed to adjust LCD rate\n");
+ goto fail1;
+ }
+ clk_enable(lcdc.lcd_ck);
+
+ r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
+ if (r) {
+ dev_err(fbdev->dev, "unable to get IRQ\n");
+ goto fail2;
+ }
+
+ r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
+ if (r) {
+ dev_err(fbdev->dev, "unable to get LCD DMA\n");
+ goto fail3;
+ }
+
+ omap_set_lcd_dma_single_transfer(ext_mode);
+ omap_set_lcd_dma_ext_controller(ext_mode);
+
+ if (!ext_mode)
+ if ((r = alloc_palette_ram()) < 0)
+ goto fail4;
+
+ if ((r = setup_fbmem(req_vram)) < 0)
+ goto fail5;
+
+ pr_info("omapfb: LCDC initialized\n");
+
+ return 0;
+fail5:
+ if (!ext_mode)
+ free_palette_ram();
+fail4:
+ omap_free_lcd_dma();
+fail3:
+ free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+fail2:
+ clk_disable(lcdc.lcd_ck);
+fail1:
+ clk_put(lcdc.lcd_ck);
+fail0:
+ return r;
+}
+
+static void omap_lcdc_cleanup(void)
+{
+ if (!lcdc.ext_mode)
+ free_palette_ram();
+ cleanup_fbmem();
+ omap_free_lcd_dma();
+ free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
+ clk_disable(lcdc.lcd_ck);
+ clk_put(lcdc.lcd_ck);
+}
+
+const struct lcd_ctrl omap1_int_ctrl = {
+ .name = "internal",
+ .init = omap_lcdc_init,
+ .cleanup = omap_lcdc_cleanup,
+ .get_caps = omap_lcdc_get_caps,
+ .set_update_mode = omap_lcdc_set_update_mode,
+ .get_update_mode = omap_lcdc_get_update_mode,
+ .update_window = NULL,
+ .suspend = omap_lcdc_suspend,
+ .resume = omap_lcdc_resume,
+ .setup_plane = omap_lcdc_setup_plane,
+ .enable_plane = omap_lcdc_enable_plane,
+ .setcolreg = omap_lcdc_setcolreg,
+};
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h
new file mode 100644
index 000000000000..adb731e5314a
--- /dev/null
+++ b/drivers/video/omap/lcdc.h
@@ -0,0 +1,7 @@
+#ifndef LCDC_H
+#define LCDC_H
+
+int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
+void omap_lcdc_free_dma_callback(void);
+
+#endif
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
new file mode 100644
index 000000000000..14d0f7a11145
--- /dev/null
+++ b/drivers/video/omap/omapfb_main.c
@@ -0,0 +1,1941 @@
+/*
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * Acknowledgements:
+ * Alex McMains <aam@ridgerun.com> - Original driver
+ * Juha Yrjola <juha.yrjola@nokia.com> - Original driver and improvements
+ * Dirk Behme <dirk.behme@de.bosch.com> - changes for 2.6 kernel API
+ * Texas Instruments - H3 support
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#define MODULE_NAME "omapfb"
+
+static unsigned int def_accel;
+static unsigned long def_vram[OMAPFB_PLANE_NUM];
+static int def_vram_cnt;
+static unsigned long def_vxres;
+static unsigned long def_vyres;
+static unsigned int def_rotate;
+static unsigned int def_mirror;
+
+#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
+static int manual_update = 1;
+#else
+static int manual_update;
+#endif
+
+static struct platform_device *fbdev_pdev;
+static struct lcd_panel *fbdev_panel;
+static struct omapfb_device *omapfb_dev;
+
+struct caps_table_struct {
+ unsigned long flag;
+ const char *name;
+};
+
+static struct caps_table_struct ctrl_caps[] = {
+ { OMAPFB_CAPS_MANUAL_UPDATE, "manual update" },
+ { OMAPFB_CAPS_TEARSYNC, "tearing synchronization" },
+ { OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" },
+ { OMAPFB_CAPS_PLANE_SCALE, "scale plane" },
+ { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
+ { OMAPFB_CAPS_WINDOW_SCALE, "scale window" },
+ { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
+ { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" },
+};
+
+static struct caps_table_struct color_caps[] = {
+ { 1 << OMAPFB_COLOR_RGB565, "RGB565", },
+ { 1 << OMAPFB_COLOR_YUV422, "YUV422", },
+ { 1 << OMAPFB_COLOR_YUV420, "YUV420", },
+ { 1 << OMAPFB_COLOR_CLUT_8BPP, "CLUT8", },
+ { 1 << OMAPFB_COLOR_CLUT_4BPP, "CLUT4", },
+ { 1 << OMAPFB_COLOR_CLUT_2BPP, "CLUT2", },
+ { 1 << OMAPFB_COLOR_CLUT_1BPP, "CLUT1", },
+ { 1 << OMAPFB_COLOR_RGB444, "RGB444", },
+ { 1 << OMAPFB_COLOR_YUY422, "YUY422", },
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD panel
+ * ---------------------------------------------------------------------------
+ */
+extern struct lcd_ctrl omap1_int_ctrl;
+extern struct lcd_ctrl omap2_int_ctrl;
+extern struct lcd_ctrl hwa742_ctrl;
+extern struct lcd_ctrl blizzard_ctrl;
+
+static struct lcd_ctrl *ctrls[] = {
+#ifdef CONFIG_ARCH_OMAP1
+ &omap1_int_ctrl,
+#else
+ &omap2_int_ctrl,
+#endif
+
+#ifdef CONFIG_FB_OMAP_LCDC_HWA742
+ &hwa742_ctrl,
+#endif
+#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD
+ &blizzard_ctrl,
+#endif
+};
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+#ifdef CONFIG_ARCH_OMAP1
+extern struct lcd_ctrl_extif omap1_ext_if;
+#else
+extern struct lcd_ctrl_extif omap2_ext_if;
+#endif
+#endif
+
+static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
+{
+ mutex_lock(&fbdev->rqueue_mutex);
+}
+
+static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
+{
+ mutex_unlock(&fbdev->rqueue_mutex);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD controller and LCD DMA
+ * ---------------------------------------------------------------------------
+ */
+/* Lookup table to map elem size to elem type. */
+static const int dma_elem_type[] = {
+ 0,
+ OMAP_DMA_DATA_TYPE_S8,
+ OMAP_DMA_DATA_TYPE_S16,
+ 0,
+ OMAP_DMA_DATA_TYPE_S32,
+};
+
+/*
+ * Allocate resources needed for LCD controller and LCD DMA operations. Video
+ * memory is allocated from system memory according to the virtual display
+ * size, except if a bigger memory size is specified explicitly as a kernel
+ * parameter.
+ */
+static int ctrl_init(struct omapfb_device *fbdev)
+{
+ int r;
+ int i;
+
+ /* kernel/module vram parameters override boot tags/board config */
+ if (def_vram_cnt) {
+ for (i = 0; i < def_vram_cnt; i++)
+ fbdev->mem_desc.region[i].size =
+ PAGE_ALIGN(def_vram[i]);
+ fbdev->mem_desc.region_cnt = i;
+ } else {
+ struct omapfb_platform_data *conf;
+
+ conf = fbdev->dev->platform_data;
+ fbdev->mem_desc = conf->mem_desc;
+ }
+
+ if (!fbdev->mem_desc.region_cnt) {
+ struct lcd_panel *panel = fbdev->panel;
+ int def_size;
+ int bpp = panel->bpp;
+
+ /* 12 bpp is packed in 16 bits */
+ if (bpp == 12)
+ bpp = 16;
+ def_size = def_vxres * def_vyres * bpp / 8;
+ fbdev->mem_desc.region_cnt = 1;
+ fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size);
+ }
+ r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc);
+ if (r < 0) {
+ dev_err(fbdev->dev, "controller initialization failed (%d)\n",
+ r);
+ return r;
+ }
+
+#ifdef DEBUG
+ for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+ dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n",
+ i,
+ fbdev->mem_desc.region[i].paddr,
+ fbdev->mem_desc.region[i].vaddr,
+ fbdev->mem_desc.region[i].size);
+ }
+#endif
+ return 0;
+}
+
+static void ctrl_cleanup(struct omapfb_device *fbdev)
+{
+ fbdev->ctrl->cleanup();
+}
+
+/* Must be called with fbdev->rqueue_mutex held. */
+static int ctrl_change_mode(struct fb_info *fbi)
+{
+ int r;
+ unsigned long offset;
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct fb_var_screeninfo *var = &fbi->var;
+
+ offset = var->yoffset * fbi->fix.line_length +
+ var->xoffset * var->bits_per_pixel / 8;
+
+ if (fbdev->ctrl->sync)
+ fbdev->ctrl->sync();
+ r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out,
+ offset, var->xres_virtual,
+ plane->info.pos_x, plane->info.pos_y,
+ var->xres, var->yres, plane->color_mode);
+ if (fbdev->ctrl->set_scale != NULL)
+ r = fbdev->ctrl->set_scale(plane->idx,
+ var->xres, var->yres,
+ plane->info.out_width,
+ plane->info.out_height);
+
+ return r;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks and the ioctl interface
+ * ---------------------------------------------------------------------------
+ */
+/* Called each time the omapfb device is opened */
+static int omapfb_open(struct fb_info *info, int user)
+{
+ return 0;
+}
+
+static void omapfb_sync(struct fb_info *info);
+
+/* Called when the omapfb device is closed. We make sure that any pending
+ * gfx DMA operations are ended, before we return. */
+static int omapfb_release(struct fb_info *info, int user)
+{
+ omapfb_sync(info);
+ return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
+ u_int blue, u_int transp, int update_hw_pal)
+{
+ struct omapfb_plane_struct *plane = info->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct fb_var_screeninfo *var = &info->var;
+ int r = 0;
+
+ switch (plane->color_mode) {
+ case OMAPFB_COLOR_YUV422:
+ case OMAPFB_COLOR_YUV420:
+ case OMAPFB_COLOR_YUY422:
+ r = -EINVAL;
+ break;
+ case OMAPFB_COLOR_CLUT_8BPP:
+ case OMAPFB_COLOR_CLUT_4BPP:
+ case OMAPFB_COLOR_CLUT_2BPP:
+ case OMAPFB_COLOR_CLUT_1BPP:
+ if (fbdev->ctrl->setcolreg)
+ r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+ transp, update_hw_pal);
+ /* Fallthrough */
+ case OMAPFB_COLOR_RGB565:
+ case OMAPFB_COLOR_RGB444:
+ if (r != 0)
+ break;
+
+ if (regno < 0) {
+ r = -EINVAL;
+ break;
+ }
+
+ if (regno < 16) {
+ u16 pal;
+ pal = ((red >> (16 - var->red.length)) <<
+ var->red.offset) |
+ ((green >> (16 - var->green.length)) <<
+ var->green.offset) |
+ (blue >> (16 - var->blue.length));
+ ((u32 *)(info->pseudo_palette))[regno] = pal;
+ }
+ break;
+ default:
+ BUG();
+ }
+ return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ int count, index, r;
+ u16 *red, *green, *blue, *transp;
+ u16 trans = 0xffff;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ index = cmap->start;
+
+ for (count = 0; count < cmap->len; count++) {
+ if (transp)
+ trans = *transp++;
+ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+ count == cmap->len - 1);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi);
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ int do_update = 0;
+ int r = 0;
+
+ omapfb_rqueue_lock(fbdev);
+ switch (blank) {
+ case VESA_NO_BLANKING:
+ if (fbdev->state == OMAPFB_SUSPENDED) {
+ if (fbdev->ctrl->resume)
+ fbdev->ctrl->resume();
+ fbdev->panel->enable(fbdev->panel);
+ fbdev->state = OMAPFB_ACTIVE;
+ if (fbdev->ctrl->get_update_mode() ==
+ OMAPFB_MANUAL_UPDATE)
+ do_update = 1;
+ }
+ break;
+ case VESA_POWERDOWN:
+ if (fbdev->state == OMAPFB_ACTIVE) {
+ fbdev->panel->disable(fbdev->panel);
+ if (fbdev->ctrl->suspend)
+ fbdev->ctrl->suspend();
+ fbdev->state = OMAPFB_SUSPENDED;
+ }
+ break;
+ default:
+ r = -EINVAL;
+ }
+ omapfb_rqueue_unlock(fbdev);
+
+ if (r == 0 && do_update)
+ r = omapfb_update_full_screen(fbi);
+
+ return r;
+}
+
+static void omapfb_sync(struct fb_info *fbi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+
+ omapfb_rqueue_lock(fbdev);
+ if (fbdev->ctrl->sync)
+ fbdev->ctrl->sync();
+ omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set fb_info.fix fields and also updates fbdev.
+ * When calling this fb_info.var must be set up already.
+ */
+static void set_fb_fix(struct fb_info *fbi)
+{
+ struct fb_fix_screeninfo *fix = &fbi->fix;
+ struct fb_var_screeninfo *var = &fbi->var;
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_mem_region *rg;
+ int bpp;
+
+ rg = &plane->fbdev->mem_desc.region[plane->idx];
+ fbi->screen_base = (char __iomem *)rg->vaddr;
+ fix->smem_start = rg->paddr;
+ fix->smem_len = rg->size;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ bpp = var->bits_per_pixel;
+ if (var->nonstd)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else switch (var->bits_per_pixel) {
+ case 16:
+ case 12:
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ /* 12bpp is stored in 16 bits */
+ bpp = 16;
+ break;
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ }
+ fix->accel = FB_ACCEL_OMAP1610;
+ fix->line_length = var->xres_virtual * bpp / 8;
+}
+
+static int set_color_mode(struct omapfb_plane_struct *plane,
+ struct fb_var_screeninfo *var)
+{
+ switch (var->nonstd) {
+ case 0:
+ break;
+ case OMAPFB_COLOR_YUV422:
+ var->bits_per_pixel = 16;
+ plane->color_mode = var->nonstd;
+ return 0;
+ case OMAPFB_COLOR_YUV420:
+ var->bits_per_pixel = 12;
+ plane->color_mode = var->nonstd;
+ return 0;
+ case OMAPFB_COLOR_YUY422:
+ var->bits_per_pixel = 16;
+ plane->color_mode = var->nonstd;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ switch (var->bits_per_pixel) {
+ case 1:
+ plane->color_mode = OMAPFB_COLOR_CLUT_1BPP;
+ return 0;
+ case 2:
+ plane->color_mode = OMAPFB_COLOR_CLUT_2BPP;
+ return 0;
+ case 4:
+ plane->color_mode = OMAPFB_COLOR_CLUT_4BPP;
+ return 0;
+ case 8:
+ plane->color_mode = OMAPFB_COLOR_CLUT_8BPP;
+ return 0;
+ case 12:
+ var->bits_per_pixel = 16;
+ plane->color_mode = OMAPFB_COLOR_RGB444;
+ return 0;
+ case 16:
+ plane->color_mode = OMAPFB_COLOR_RGB565;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * Check the values in var against our capabilities and in case of out of
+ * bound values try to adjust them.
+ */
+static int set_fb_var(struct fb_info *fbi,
+ struct fb_var_screeninfo *var)
+{
+ int bpp;
+ unsigned long max_frame_size;
+ unsigned long line_size;
+ int xres_min, xres_max;
+ int yres_min, yres_max;
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct lcd_panel *panel = fbdev->panel;
+
+ if (set_color_mode(plane, var) < 0)
+ return -EINVAL;
+
+ bpp = var->bits_per_pixel;
+ if (plane->color_mode == OMAPFB_COLOR_RGB444)
+ bpp = 16;
+
+ switch (var->rotate) {
+ case 0:
+ case 180:
+ xres_min = OMAPFB_PLANE_XRES_MIN;
+ xres_max = panel->x_res;
+ yres_min = OMAPFB_PLANE_YRES_MIN;
+ yres_max = panel->y_res;
+ if (cpu_is_omap15xx()) {
+ var->xres = panel->x_res;
+ var->yres = panel->y_res;
+ }
+ break;
+ case 90:
+ case 270:
+ xres_min = OMAPFB_PLANE_YRES_MIN;
+ xres_max = panel->y_res;
+ yres_min = OMAPFB_PLANE_XRES_MIN;
+ yres_max = panel->x_res;
+ if (cpu_is_omap15xx()) {
+ var->xres = panel->y_res;
+ var->yres = panel->x_res;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (var->xres < xres_min)
+ var->xres = xres_min;
+ if (var->yres < yres_min)
+ var->yres = yres_min;
+ if (var->xres > xres_max)
+ var->xres = xres_max;
+ if (var->yres > yres_max)
+ var->yres = yres_max;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+ max_frame_size = fbdev->mem_desc.region[plane->idx].size;
+ line_size = var->xres_virtual * bpp / 8;
+ if (line_size * var->yres_virtual > max_frame_size) {
+ /* Try to keep yres_virtual first */
+ line_size = max_frame_size / var->yres_virtual;
+ var->xres_virtual = line_size * 8 / bpp;
+ if (var->xres_virtual < var->xres) {
+ /* Still doesn't fit. Shrink yres_virtual too */
+ var->xres_virtual = var->xres;
+ line_size = var->xres * bpp / 8;
+ var->yres_virtual = max_frame_size / line_size;
+ }
+ /* Recheck this, as the virtual size changed. */
+ if (var->xres_virtual < var->xres)
+ var->xres = var->xres_virtual;
+ if (var->yres_virtual < var->yres)
+ var->yres = var->yres_virtual;
+ if (var->xres < xres_min || var->yres < yres_min)
+ return -EINVAL;
+ }
+ if (var->xres + var->xoffset > var->xres_virtual)
+ var->xoffset = var->xres_virtual - var->xres;
+ if (var->yres + var->yoffset > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+ line_size = var->xres * bpp / 8;
+
+ if (plane->color_mode == OMAPFB_COLOR_RGB444) {
+ var->red.offset = 8; var->red.length = 4;
+ var->red.msb_right = 0;
+ var->green.offset = 4; var->green.length = 4;
+ var->green.msb_right = 0;
+ var->blue.offset = 0; var->blue.length = 4;
+ var->blue.msb_right = 0;
+ } else {
+ var->red.offset = 11; var->red.length = 5;
+ var->red.msb_right = 0;
+ var->green.offset = 5; var->green.length = 6;
+ var->green.msb_right = 0;
+ var->blue.offset = 0; var->blue.length = 5;
+ var->blue.msb_right = 0;
+ }
+
+ var->height = -1;
+ var->width = -1;
+ var->grayscale = 0;
+
+ /* pixclock in ps, the rest in pixclock */
+ var->pixclock = 10000000 / (panel->pixel_clock / 100);
+ var->left_margin = panel->hfp;
+ var->right_margin = panel->hbp;
+ var->upper_margin = panel->vfp;
+ var->lower_margin = panel->vbp;
+ var->hsync_len = panel->hsw;
+ var->vsync_len = panel->vsw;
+
+ /* TODO: get these from panel->config */
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->sync = 0;
+
+ return 0;
+}
+
+
+/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
+static void omapfb_rotate(struct fb_info *fbi, int rotate)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+
+ omapfb_rqueue_lock(fbdev);
+ if (cpu_is_omap15xx() && rotate != fbi->var.rotate) {
+ struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+ memcpy(new_var, &fbi->var, sizeof(*new_var));
+ new_var->rotate = rotate;
+ if (set_fb_var(fbi, new_var) == 0 &&
+ memcmp(new_var, &fbi->var, sizeof(*new_var))) {
+ memcpy(&fbi->var, new_var, sizeof(*new_var));
+ ctrl_change_mode(fbi);
+ }
+ }
+ omapfb_rqueue_unlock(fbdev);
+}
+
+/*
+ * Set new x,y offsets in the virtual display for the visible area and switch
+ * to the new mode.
+ */
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ int r = 0;
+
+ omapfb_rqueue_lock(fbdev);
+ if (var->xoffset != fbi->var.xoffset ||
+ var->yoffset != fbi->var.yoffset) {
+ struct fb_var_screeninfo *new_var = &fbdev->new_var;
+
+ memcpy(new_var, &fbi->var, sizeof(*new_var));
+ new_var->xoffset = var->xoffset;
+ new_var->yoffset = var->yoffset;
+ if (set_fb_var(fbi, new_var))
+ r = -EINVAL;
+ else {
+ memcpy(&fbi->var, new_var, sizeof(*new_var));
+ ctrl_change_mode(fbi);
+ }
+ }
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+/* Set mirror to vertical axis and switch to the new mode. */
+static int omapfb_mirror(struct fb_info *fbi, int mirror)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ int r = 0;
+
+ omapfb_rqueue_lock(fbdev);
+ mirror = mirror ? 1 : 0;
+ if (cpu_is_omap15xx())
+ r = -EINVAL;
+ else if (mirror != plane->info.mirror) {
+ plane->info.mirror = mirror;
+ r = ctrl_change_mode(fbi);
+ }
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+/*
+ * Check values in var, try to adjust them in case of out of bound values if
+ * possible, or return error.
+ */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ int r;
+
+ omapfb_rqueue_lock(fbdev);
+ if (fbdev->ctrl->sync != NULL)
+ fbdev->ctrl->sync();
+ r = set_fb_var(fbi, var);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+/*
+ * Switch to a new mode. The parameters for it has been check already by
+ * omapfb_check_var.
+ */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ int r = 0;
+
+ omapfb_rqueue_lock(fbdev);
+ set_fb_fix(fbi);
+ r = ctrl_change_mode(fbi);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+int omapfb_update_window_async(struct fb_info *fbi,
+ struct omapfb_update_window *win,
+ void (*callback)(void *),
+ void *callback_data)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct fb_var_screeninfo *var;
+
+ var = &fbi->var;
+ if (win->x >= var->xres || win->y >= var->yres ||
+ win->out_x > var->xres || win->out_y >= var->yres)
+ return -EINVAL;
+
+ if (!fbdev->ctrl->update_window ||
+ fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+ return -ENODEV;
+
+ if (win->x + win->width >= var->xres)
+ win->width = var->xres - win->x;
+ if (win->y + win->height >= var->yres)
+ win->height = var->yres - win->y;
+ /* The out sizes should be cropped to the LCD size */
+ if (win->out_x + win->out_width > fbdev->panel->x_res)
+ win->out_width = fbdev->panel->x_res - win->out_x;
+ if (win->out_y + win->out_height > fbdev->panel->y_res)
+ win->out_height = fbdev->panel->y_res - win->out_y;
+ if (!win->width || !win->height || !win->out_width || !win->out_height)
+ return 0;
+
+ return fbdev->ctrl->update_window(fbi, win, callback, callback_data);
+}
+EXPORT_SYMBOL(omapfb_update_window_async);
+
+static int omapfb_update_win(struct fb_info *fbi,
+ struct omapfb_update_window *win)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ int ret;
+
+ omapfb_rqueue_lock(plane->fbdev);
+ ret = omapfb_update_window_async(fbi, win, NULL, 0);
+ omapfb_rqueue_unlock(plane->fbdev);
+
+ return ret;
+}
+
+static int omapfb_update_full_screen(struct fb_info *fbi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct omapfb_update_window win;
+ int r;
+
+ if (!fbdev->ctrl->update_window ||
+ fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+ return -ENODEV;
+
+ win.x = 0;
+ win.y = 0;
+ win.width = fbi->var.xres;
+ win.height = fbi->var.yres;
+ win.out_x = 0;
+ win.out_y = 0;
+ win.out_width = fbi->var.xres;
+ win.out_height = fbi->var.yres;
+ win.format = 0;
+
+ omapfb_rqueue_lock(fbdev);
+ r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct lcd_panel *panel = fbdev->panel;
+ struct omapfb_plane_info old_info;
+ int r = 0;
+
+ if (pi->pos_x + pi->out_width > panel->x_res ||
+ pi->pos_y + pi->out_height > panel->y_res)
+ return -EINVAL;
+
+ omapfb_rqueue_lock(fbdev);
+ if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) {
+ /*
+ * This plane's memory was freed, can't enable it
+ * until it's reallocated.
+ */
+ r = -EINVAL;
+ goto out;
+ }
+ old_info = plane->info;
+ plane->info = *pi;
+ if (pi->enabled) {
+ r = ctrl_change_mode(fbi);
+ if (r < 0) {
+ plane->info = old_info;
+ goto out;
+ }
+ }
+ r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled);
+ if (r < 0) {
+ plane->info = old_info;
+ goto out;
+ }
+out:
+ omapfb_rqueue_unlock(fbdev);
+ return r;
+}
+
+static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+
+ *pi = plane->info;
+ return 0;
+}
+
+static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx];
+ size_t size;
+ int r = 0;
+
+ if (fbdev->ctrl->setup_mem == NULL)
+ return -ENODEV;
+ if (mi->type > OMAPFB_MEMTYPE_MAX)
+ return -EINVAL;
+
+ size = PAGE_ALIGN(mi->size);
+ omapfb_rqueue_lock(fbdev);
+ if (plane->info.enabled) {
+ r = -EBUSY;
+ goto out;
+ }
+ if (rg->size != size || rg->type != mi->type) {
+ struct fb_var_screeninfo *new_var = &fbdev->new_var;
+ unsigned long old_size = rg->size;
+ u8 old_type = rg->type;
+ unsigned long paddr;
+
+ rg->size = size;
+ rg->type = mi->type;
+ /*
+ * size == 0 is a special case, for which we
+ * don't check / adjust the screen parameters.
+ * This isn't a problem since the plane can't
+ * be reenabled unless its size is > 0.
+ */
+ if (old_size != size && size) {
+ if (size) {
+ memcpy(new_var, &fbi->var, sizeof(*new_var));
+ r = set_fb_var(fbi, new_var);
+ if (r < 0)
+ goto out;
+ }
+ }
+
+ if (fbdev->ctrl->sync)
+ fbdev->ctrl->sync();
+ r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr);
+ if (r < 0) {
+ /* Revert changes. */
+ rg->size = old_size;
+ rg->type = old_type;
+ goto out;
+ }
+ rg->paddr = paddr;
+
+ if (old_size != size) {
+ if (size) {
+ memcpy(&fbi->var, new_var, sizeof(fbi->var));
+ set_fb_fix(fbi);
+ } else {
+ /*
+ * Set these explicitly to indicate that the
+ * plane memory is dealloce'd, the other
+ * screen parameters in var / fix are invalid.
+ */
+ fbi->fix.smem_start = 0;
+ fbi->fix.smem_len = 0;
+ }
+ }
+ }
+out:
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct omapfb_mem_region *rg;
+
+ rg = &fbdev->mem_desc.region[plane->idx];
+ memset(mi, 0, sizeof(*mi));
+ mi->size = rg->size;
+ mi->type = rg->type;
+
+ return 0;
+}
+
+static int omapfb_set_color_key(struct omapfb_device *fbdev,
+ struct omapfb_color_key *ck)
+{
+ int r;
+
+ if (!fbdev->ctrl->set_color_key)
+ return -ENODEV;
+
+ omapfb_rqueue_lock(fbdev);
+ r = fbdev->ctrl->set_color_key(ck);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+static int omapfb_get_color_key(struct omapfb_device *fbdev,
+ struct omapfb_color_key *ck)
+{
+ int r;
+
+ if (!fbdev->ctrl->get_color_key)
+ return -ENODEV;
+
+ omapfb_rqueue_lock(fbdev);
+ r = fbdev->ctrl->get_color_key(ck);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];
+static int notifier_inited;
+
+static void omapfb_init_notifier(void)
+{
+ int i;
+
+ for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+ BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);
+}
+
+int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
+ omapfb_notifier_callback_t callback,
+ void *callback_data)
+{
+ int r;
+
+ if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+ return -EINVAL;
+
+ if (!notifier_inited) {
+ omapfb_init_notifier();
+ notifier_inited = 1;
+ }
+
+ omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,
+ unsigned long, void *))callback;
+ omapfb_nb->data = callback_data;
+ r = blocking_notifier_chain_register(
+ &omapfb_client_list[omapfb_nb->plane_idx],
+ &omapfb_nb->nb);
+ if (r)
+ return r;
+ if (omapfb_dev != NULL &&
+ omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) {
+ omapfb_dev->ctrl->bind_client(omapfb_nb);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omapfb_register_client);
+
+int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb)
+{
+ return blocking_notifier_chain_unregister(
+ &omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb);
+}
+EXPORT_SYMBOL(omapfb_unregister_client);
+
+void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event)
+{
+ int i;
+
+ if (!notifier_inited)
+ /* no client registered yet */
+ return;
+
+ for (i = 0; i < OMAPFB_PLANE_NUM; i++)
+ blocking_notifier_call_chain(&omapfb_client_list[i], event,
+ fbdev->fb_info[i]);
+}
+EXPORT_SYMBOL(omapfb_notify_clients);
+
+static int omapfb_set_update_mode(struct omapfb_device *fbdev,
+ enum omapfb_update_mode mode)
+{
+ int r;
+
+ omapfb_rqueue_lock(fbdev);
+ r = fbdev->ctrl->set_update_mode(mode);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
+{
+ int r;
+
+ omapfb_rqueue_lock(fbdev);
+ r = fbdev->ctrl->get_update_mode();
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+static void omapfb_get_caps(struct omapfb_device *fbdev, int plane,
+ struct omapfb_caps *caps)
+{
+ memset(caps, 0, sizeof(*caps));
+ fbdev->ctrl->get_caps(plane, caps);
+ caps->ctrl |= fbdev->panel->get_caps(fbdev->panel);
+}
+
+/* For lcd testing */
+void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
+{
+ omapfb_rqueue_lock(fbdev);
+ *(u16 *)fbdev->mem_desc.region[0].vaddr = pixval;
+ if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
+ struct omapfb_update_window win;
+
+ memset(&win, 0, sizeof(win));
+ win.width = 2;
+ win.height = 2;
+ win.out_width = 2;
+ win.out_height = 2;
+ fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
+ }
+ omapfb_rqueue_unlock(fbdev);
+}
+EXPORT_SYMBOL(omapfb_write_first_pixel);
+
+/*
+ * Ioctl interface. Part of the kernel mode frame buffer API is duplicated
+ * here to be accessible by user mode code.
+ */
+static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd,
+ unsigned long arg)
+{
+ struct omapfb_plane_struct *plane = fbi->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ struct fb_ops *ops = fbi->fbops;
+ union {
+ struct omapfb_update_window update_window;
+ struct omapfb_plane_info plane_info;
+ struct omapfb_mem_info mem_info;
+ struct omapfb_color_key color_key;
+ enum omapfb_update_mode update_mode;
+ struct omapfb_caps caps;
+ unsigned int mirror;
+ int plane_out;
+ int enable_plane;
+ } p;
+ int r = 0;
+
+ BUG_ON(!ops);
+ switch (cmd) {
+ case OMAPFB_MIRROR:
+ if (get_user(p.mirror, (int __user *)arg))
+ r = -EFAULT;
+ else
+ omapfb_mirror(fbi, p.mirror);
+ break;
+ case OMAPFB_SYNC_GFX:
+ omapfb_sync(fbi);
+ break;
+ case OMAPFB_VSYNC:
+ break;
+ case OMAPFB_SET_UPDATE_MODE:
+ if (get_user(p.update_mode, (int __user *)arg))
+ r = -EFAULT;
+ else
+ r = omapfb_set_update_mode(fbdev, p.update_mode);
+ break;
+ case OMAPFB_GET_UPDATE_MODE:
+ p.update_mode = omapfb_get_update_mode(fbdev);
+ if (put_user(p.update_mode,
+ (enum omapfb_update_mode __user *)arg))
+ r = -EFAULT;
+ break;
+ case OMAPFB_UPDATE_WINDOW_OLD:
+ if (copy_from_user(&p.update_window, (void __user *)arg,
+ sizeof(struct omapfb_update_window_old)))
+ r = -EFAULT;
+ else {
+ struct omapfb_update_window *u = &p.update_window;
+ u->out_x = u->x;
+ u->out_y = u->y;
+ u->out_width = u->width;
+ u->out_height = u->height;
+ memset(u->reserved, 0, sizeof(u->reserved));
+ r = omapfb_update_win(fbi, u);
+ }
+ break;
+ case OMAPFB_UPDATE_WINDOW:
+ if (copy_from_user(&p.update_window, (void __user *)arg,
+ sizeof(p.update_window)))
+ r = -EFAULT;
+ else
+ r = omapfb_update_win(fbi, &p.update_window);
+ break;
+ case OMAPFB_SETUP_PLANE:
+ if (copy_from_user(&p.plane_info, (void __user *)arg,
+ sizeof(p.plane_info)))
+ r = -EFAULT;
+ else
+ r = omapfb_setup_plane(fbi, &p.plane_info);
+ break;
+ case OMAPFB_QUERY_PLANE:
+ if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0)
+ break;
+ if (copy_to_user((void __user *)arg, &p.plane_info,
+ sizeof(p.plane_info)))
+ r = -EFAULT;
+ break;
+ case OMAPFB_SETUP_MEM:
+ if (copy_from_user(&p.mem_info, (void __user *)arg,
+ sizeof(p.mem_info)))
+ r = -EFAULT;
+ else
+ r = omapfb_setup_mem(fbi, &p.mem_info);
+ break;
+ case OMAPFB_QUERY_MEM:
+ if ((r = omapfb_query_mem(fbi, &p.mem_info)) < 0)
+ break;
+ if (copy_to_user((void __user *)arg, &p.mem_info,
+ sizeof(p.mem_info)))
+ r = -EFAULT;
+ break;
+ case OMAPFB_SET_COLOR_KEY:
+ if (copy_from_user(&p.color_key, (void __user *)arg,
+ sizeof(p.color_key)))
+ r = -EFAULT;
+ else
+ r = omapfb_set_color_key(fbdev, &p.color_key);
+ break;
+ case OMAPFB_GET_COLOR_KEY:
+ if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0)
+ break;
+ if (copy_to_user((void __user *)arg, &p.color_key,
+ sizeof(p.color_key)))
+ r = -EFAULT;
+ break;
+ case OMAPFB_GET_CAPS:
+ omapfb_get_caps(fbdev, plane->idx, &p.caps);
+ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
+ r = -EFAULT;
+ break;
+ case OMAPFB_LCD_TEST:
+ {
+ int test_num;
+
+ if (get_user(test_num, (int __user *)arg)) {
+ r = -EFAULT;
+ break;
+ }
+ if (!fbdev->panel->run_test) {
+ r = -EINVAL;
+ break;
+ }
+ r = fbdev->panel->run_test(fbdev->panel, test_num);
+ break;
+ }
+ case OMAPFB_CTRL_TEST:
+ {
+ int test_num;
+
+ if (get_user(test_num, (int __user *)arg)) {
+ r = -EFAULT;
+ break;
+ }
+ if (!fbdev->ctrl->run_test) {
+ r = -EINVAL;
+ break;
+ }
+ r = fbdev->ctrl->run_test(test_num);
+ break;
+ }
+ default:
+ r = -EINVAL;
+ }
+
+ return r;
+}
+
+static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct omapfb_plane_struct *plane = info->par;
+ struct omapfb_device *fbdev = plane->fbdev;
+ int r;
+
+ omapfb_rqueue_lock(fbdev);
+ r = fbdev->ctrl->mmap(info, vma);
+ omapfb_rqueue_unlock(fbdev);
+
+ return r;
+}
+
+/*
+ * Callback table for the frame buffer framework. Some of these pointers
+ * will be changed according to the current setting of fb_info->accel_flags.
+ */
+static struct fb_ops omapfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = omapfb_open,
+ .fb_release = omapfb_release,
+ .fb_setcolreg = omapfb_setcolreg,
+ .fb_setcmap = omapfb_setcmap,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_blank = omapfb_blank,
+ .fb_ioctl = omapfb_ioctl,
+ .fb_check_var = omapfb_check_var,
+ .fb_set_par = omapfb_set_par,
+ .fb_rotate = omapfb_rotate,
+ .fb_pan_display = omapfb_pan_display,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Sysfs interface
+ * ---------------------------------------------------------------------------
+ */
+/* omapfbX sysfs entries */
+static ssize_t omapfb_show_caps_num(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+ int plane;
+ size_t size;
+ struct omapfb_caps caps;
+
+ plane = 0;
+ size = 0;
+ while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+ omapfb_get_caps(fbdev, plane, &caps);
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ "plane#%d %#010x %#010x %#010x\n",
+ plane, caps.ctrl, caps.plane_color, caps.wnd_color);
+ plane++;
+ }
+ return size;
+}
+
+static ssize_t omapfb_show_caps_text(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+ int i;
+ struct omapfb_caps caps;
+ int plane;
+ size_t size;
+
+ plane = 0;
+ size = 0;
+ while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
+ omapfb_get_caps(fbdev, plane, &caps);
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ "plane#%d:\n", plane);
+ for (i = 0; i < ARRAY_SIZE(ctrl_caps) &&
+ size < PAGE_SIZE; i++) {
+ if (ctrl_caps[i].flag & caps.ctrl)
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ " %s\n", ctrl_caps[i].name);
+ }
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ " plane colors:\n");
+ for (i = 0; i < ARRAY_SIZE(color_caps) &&
+ size < PAGE_SIZE; i++) {
+ if (color_caps[i].flag & caps.plane_color)
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ " %s\n", color_caps[i].name);
+ }
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ " window colors:\n");
+ for (i = 0; i < ARRAY_SIZE(color_caps) &&
+ size < PAGE_SIZE; i++) {
+ if (color_caps[i].flag & caps.wnd_color)
+ size += snprintf(&buf[size], PAGE_SIZE - size,
+ " %s\n", color_caps[i].name);
+ }
+
+ plane++;
+ }
+ return size;
+}
+
+static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
+static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
+
+/* panel sysfs entries */
+static ssize_t omapfb_show_panel_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
+}
+
+static ssize_t omapfb_show_bklight_level(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+ int r;
+
+ if (fbdev->panel->get_bklight_level) {
+ r = snprintf(buf, PAGE_SIZE, "%d\n",
+ fbdev->panel->get_bklight_level(fbdev->panel));
+ } else
+ r = -ENODEV;
+ return r;
+}
+
+static ssize_t omapfb_store_bklight_level(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+ int r;
+
+ if (fbdev->panel->set_bklight_level) {
+ unsigned int level;
+
+ if (sscanf(buf, "%10d", &level) == 1) {
+ r = fbdev->panel->set_bklight_level(fbdev->panel,
+ level);
+ } else
+ r = -EINVAL;
+ } else
+ r = -ENODEV;
+ return r ? r : size;
+}
+
+static ssize_t omapfb_show_bklight_max(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+ int r;
+
+ if (fbdev->panel->get_bklight_level) {
+ r = snprintf(buf, PAGE_SIZE, "%d\n",
+ fbdev->panel->get_bklight_max(fbdev->panel));
+ } else
+ r = -ENODEV;
+ return r;
+}
+
+static struct device_attribute dev_attr_panel_name =
+ __ATTR(name, 0444, omapfb_show_panel_name, NULL);
+static DEVICE_ATTR(backlight_level, 0664,
+ omapfb_show_bklight_level, omapfb_store_bklight_level);
+static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
+
+static struct attribute *panel_attrs[] = {
+ &dev_attr_panel_name.attr,
+ &dev_attr_backlight_level.attr,
+ &dev_attr_backlight_max.attr,
+ NULL,
+};
+
+static struct attribute_group panel_attr_grp = {
+ .name = "panel",
+ .attrs = panel_attrs,
+};
+
+/* ctrl sysfs entries */
+static ssize_t omapfb_show_ctrl_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
+}
+
+static struct device_attribute dev_attr_ctrl_name =
+ __ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
+
+static struct attribute *ctrl_attrs[] = {
+ &dev_attr_ctrl_name.attr,
+ NULL,
+};
+
+static struct attribute_group ctrl_attr_grp = {
+ .name = "ctrl",
+ .attrs = ctrl_attrs,
+};
+
+static int omapfb_register_sysfs(struct omapfb_device *fbdev)
+{
+ int r;
+
+ if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
+ goto fail0;
+
+ if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
+ goto fail1;
+
+ if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
+ goto fail2;
+
+ if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
+ goto fail3;
+
+ return 0;
+fail3:
+ sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+fail2:
+ device_remove_file(fbdev->dev, &dev_attr_caps_text);
+fail1:
+ device_remove_file(fbdev->dev, &dev_attr_caps_num);
+fail0:
+ dev_err(fbdev->dev, "unable to register sysfs interface\n");
+ return r;
+}
+
+static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
+{
+ sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
+ sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+ device_remove_file(fbdev->dev, &dev_attr_caps_num);
+ device_remove_file(fbdev->dev, &dev_attr_caps_text);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LDM callbacks
+ * ---------------------------------------------------------------------------
+ */
+/* Initialize system fb_info object and set the default video mode.
+ * The frame buffer memory already allocated by lcddma_init
+ */
+static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ int r = 0;
+
+ info->fbops = &omapfb_ops;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ strncpy(fix->id, MODULE_NAME, sizeof(fix->id));
+
+ info->pseudo_palette = fbdev->pseudo_palette;
+
+ var->accel_flags = def_accel ? FB_ACCELF_TEXT : 0;
+ var->xres = def_vxres;
+ var->yres = def_vyres;
+ var->xres_virtual = def_vxres;
+ var->yres_virtual = def_vyres;
+ var->rotate = def_rotate;
+ var->bits_per_pixel = fbdev->panel->bpp;
+
+ set_fb_var(info, var);
+ set_fb_fix(info);
+
+ r = fb_alloc_cmap(&info->cmap, 16, 0);
+ if (r != 0)
+ dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+ return r;
+}
+
+/* Release the fb_info object */
+static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi)
+{
+ fb_dealloc_cmap(&fbi->cmap);
+}
+
+static void planes_cleanup(struct omapfb_device *fbdev)
+{
+ int i;
+
+ for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+ if (fbdev->fb_info[i] == NULL)
+ break;
+ fbinfo_cleanup(fbdev, fbdev->fb_info[i]);
+ framebuffer_release(fbdev->fb_info[i]);
+ }
+}
+
+static int planes_init(struct omapfb_device *fbdev)
+{
+ struct fb_info *fbi;
+ int i;
+ int r;
+
+ for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+ struct omapfb_plane_struct *plane;
+ fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct),
+ fbdev->dev);
+ if (fbi == NULL) {
+ dev_err(fbdev->dev,
+ "unable to allocate memory for plane info\n");
+ planes_cleanup(fbdev);
+ return -ENOMEM;
+ }
+ plane = fbi->par;
+ plane->idx = i;
+ plane->fbdev = fbdev;
+ plane->info.mirror = def_mirror;
+ fbdev->fb_info[i] = fbi;
+
+ if ((r = fbinfo_init(fbdev, fbi)) < 0) {
+ framebuffer_release(fbi);
+ planes_cleanup(fbdev);
+ return r;
+ }
+ plane->info.out_width = fbi->var.xres;
+ plane->info.out_height = fbi->var.yres;
+ }
+ return 0;
+}
+
+/*
+ * Free driver resources. Can be called to rollback an aborted initialization
+ * sequence.
+ */
+static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
+{
+ int i;
+
+ switch (state) {
+ case OMAPFB_ACTIVE:
+ for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
+ unregister_framebuffer(fbdev->fb_info[i]);
+ case 7:
+ omapfb_unregister_sysfs(fbdev);
+ case 6:
+ fbdev->panel->disable(fbdev->panel);
+ case 5:
+ omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+ case 4:
+ planes_cleanup(fbdev);
+ case 3:
+ ctrl_cleanup(fbdev);
+ case 2:
+ fbdev->panel->cleanup(fbdev->panel);
+ case 1:
+ dev_set_drvdata(fbdev->dev, NULL);
+ kfree(fbdev);
+ case 0:
+ /* nothing to free */
+ break;
+ default:
+ BUG();
+ }
+}
+
+static int omapfb_find_ctrl(struct omapfb_device *fbdev)
+{
+ struct omapfb_platform_data *conf;
+ char name[17];
+ int i;
+
+ conf = fbdev->dev->platform_data;
+
+ fbdev->ctrl = NULL;
+
+ strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1);
+ name[sizeof(name) - 1] = '\0';
+
+ if (strcmp(name, "internal") == 0) {
+ fbdev->ctrl = fbdev->int_ctrl;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
+ dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name);
+ if (strcmp(ctrls[i]->name, name) == 0) {
+ fbdev->ctrl = ctrls[i];
+ break;
+ }
+ }
+
+ if (fbdev->ctrl == NULL) {
+ dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void check_required_callbacks(struct omapfb_device *fbdev)
+{
+#define _C(x) (fbdev->ctrl->x != NULL)
+#define _P(x) (fbdev->panel->x != NULL)
+ BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
+ BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
+ _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
+ _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
+ _P(get_caps)));
+#undef _P
+#undef _C
+}
+
+/*
+ * Called by LDM binding to probe and attach a new device.
+ * Initialization sequence:
+ * 1. allocate system omapfb_device structure
+ * 2. select controller type according to platform configuration
+ * init LCD panel
+ * 3. init LCD controller and LCD DMA
+ * 4. init system fb_info structure for all planes
+ * 5. setup video mode for first plane and enable it
+ * 6. enable LCD panel
+ * 7. register sysfs attributes
+ * OMAPFB_ACTIVE: register system fb_info structure for all planes
+ */
+static int omapfb_do_probe(struct platform_device *pdev,
+ struct lcd_panel *panel)
+{
+ struct omapfb_device *fbdev = NULL;
+ int init_state;
+ unsigned long phz, hhz, vhz;
+ unsigned long vram;
+ int i;
+ int r = 0;
+
+ init_state = 0;
+
+ if (pdev->num_resources != 0) {
+ dev_err(&pdev->dev, "probed for an unknown device\n");
+ r = -ENODEV;
+ goto cleanup;
+ }
+
+ if (pdev->dev.platform_data == NULL) {
+ dev_err(&pdev->dev, "missing platform data\n");
+ r = -ENOENT;
+ goto cleanup;
+ }
+
+ fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
+ if (fbdev == NULL) {
+ dev_err(&pdev->dev,
+ "unable to allocate memory for device info\n");
+ r = -ENOMEM;
+ goto cleanup;
+ }
+ init_state++;
+
+ fbdev->dev = &pdev->dev;
+ fbdev->panel = panel;
+ platform_set_drvdata(pdev, fbdev);
+
+ mutex_init(&fbdev->rqueue_mutex);
+
+#ifdef CONFIG_ARCH_OMAP1
+ fbdev->int_ctrl = &omap1_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ fbdev->ext_if = &omap1_ext_if;
+#endif
+#else /* OMAP2 */
+ fbdev->int_ctrl = &omap2_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ fbdev->ext_if = &omap2_ext_if;
+#endif
+#endif
+ if (omapfb_find_ctrl(fbdev) < 0) {
+ dev_err(fbdev->dev,
+ "LCD controller not found, board not supported\n");
+ r = -ENODEV;
+ goto cleanup;
+ }
+
+ r = fbdev->panel->init(fbdev->panel, fbdev);
+ if (r)
+ goto cleanup;
+
+ pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
+
+ def_vxres = def_vxres ? : fbdev->panel->x_res;
+ def_vyres = def_vyres ? : fbdev->panel->y_res;
+
+ init_state++;
+
+ r = ctrl_init(fbdev);
+ if (r)
+ goto cleanup;
+ if (fbdev->ctrl->mmap != NULL)
+ omapfb_ops.fb_mmap = omapfb_mmap;
+ init_state++;
+
+ check_required_callbacks(fbdev);
+
+ r = planes_init(fbdev);
+ if (r)
+ goto cleanup;
+ init_state++;
+
+#ifdef CONFIG_FB_OMAP_DMA_TUNE
+ /* Set DMA priority for EMIFF access to highest */
+ if (cpu_class_is_omap1())
+ omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
+#endif
+
+ r = ctrl_change_mode(fbdev->fb_info[0]);
+ if (r) {
+ dev_err(fbdev->dev, "mode setting failed\n");
+ goto cleanup;
+ }
+
+ /* GFX plane is enabled by default */
+ r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1);
+ if (r)
+ goto cleanup;
+
+ omapfb_set_update_mode(fbdev, manual_update ?
+ OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
+ init_state++;
+
+ r = fbdev->panel->enable(fbdev->panel);
+ if (r)
+ goto cleanup;
+ init_state++;
+
+ r = omapfb_register_sysfs(fbdev);
+ if (r)
+ goto cleanup;
+ init_state++;
+
+ vram = 0;
+ for (i = 0; i < fbdev->mem_desc.region_cnt; i++) {
+ r = register_framebuffer(fbdev->fb_info[i]);
+ if (r != 0) {
+ dev_err(fbdev->dev,
+ "registering framebuffer %d failed\n", i);
+ goto cleanup;
+ }
+ vram += fbdev->mem_desc.region[i].size;
+ }
+
+ fbdev->state = OMAPFB_ACTIVE;
+
+ panel = fbdev->panel;
+ phz = panel->pixel_clock * 1000;
+ hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
+ vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
+
+ omapfb_dev = fbdev;
+
+ pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
+ vram, fbdev->mem_desc.region_cnt);
+ pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
+ "vfreq %lu.%lu Hz\n",
+ phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
+
+ return 0;
+
+cleanup:
+ omapfb_free_resources(fbdev, init_state);
+
+ return r;
+}
+
+static int omapfb_probe(struct platform_device *pdev)
+{
+ BUG_ON(fbdev_pdev != NULL);
+
+ /* Delay actual initialization until the LCD is registered */
+ fbdev_pdev = pdev;
+ if (fbdev_panel != NULL)
+ omapfb_do_probe(fbdev_pdev, fbdev_panel);
+ return 0;
+}
+
+void omapfb_register_panel(struct lcd_panel *panel)
+{
+ BUG_ON(fbdev_panel != NULL);
+
+ fbdev_panel = panel;
+ if (fbdev_pdev != NULL)
+ omapfb_do_probe(fbdev_pdev, fbdev_panel);
+}
+
+/* Called when the device is being detached from the driver */
+static int omapfb_remove(struct platform_device *pdev)
+{
+ struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+ enum omapfb_state saved_state = fbdev->state;
+
+ /* FIXME: wait till completion of pending events */
+
+ fbdev->state = OMAPFB_DISABLED;
+ omapfb_free_resources(fbdev, saved_state);
+
+ return 0;
+}
+
+/* PM suspend */
+static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+ omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
+
+ return 0;
+}
+
+/* PM resume */
+static int omapfb_resume(struct platform_device *pdev)
+{
+ struct omapfb_device *fbdev = platform_get_drvdata(pdev);
+
+ omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
+ return 0;
+}
+
+static struct platform_driver omapfb_driver = {
+ .probe = omapfb_probe,
+ .remove = omapfb_remove,
+ .suspend = omapfb_suspend,
+ .resume = omapfb_resume,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+#ifndef MODULE
+
+/* Process kernel command line parameters */
+static int __init omapfb_setup(char *options)
+{
+ char *this_opt = NULL;
+ int r = 0;
+
+ pr_debug("omapfb: options %s\n", options);
+
+ if (!options || !*options)
+ return 0;
+
+ while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "accel", 5))
+ def_accel = 1;
+ else if (!strncmp(this_opt, "vram:", 5)) {
+ char *suffix;
+ unsigned long vram;
+ vram = (simple_strtoul(this_opt + 5, &suffix, 0));
+ switch (suffix[0]) {
+ case '\0':
+ break;
+ case 'm':
+ case 'M':
+ vram *= 1024;
+ /* Fall through */
+ case 'k':
+ case 'K':
+ vram *= 1024;
+ break;
+ default:
+ pr_debug("omapfb: invalid vram suffix %c\n",
+ suffix[0]);
+ r = -1;
+ }
+ def_vram[def_vram_cnt++] = vram;
+ }
+ else if (!strncmp(this_opt, "vxres:", 6))
+ def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
+ else if (!strncmp(this_opt, "vyres:", 6))
+ def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
+ else if (!strncmp(this_opt, "rotate:", 7))
+ def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
+ else if (!strncmp(this_opt, "mirror:", 7))
+ def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
+ else if (!strncmp(this_opt, "manual_update", 13))
+ manual_update = 1;
+ else {
+ pr_debug("omapfb: invalid option\n");
+ r = -1;
+ }
+ }
+
+ return r;
+}
+
+#endif
+
+/* Register both the driver and the device */
+static int __init omapfb_init(void)
+{
+#ifndef MODULE
+ char *option;
+
+ if (fb_get_options("omapfb", &option))
+ return -ENODEV;
+ omapfb_setup(option);
+#endif
+ /* Register the driver with LDM */
+ if (platform_driver_register(&omapfb_driver)) {
+ pr_debug("failed to register omapfb driver\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit omapfb_cleanup(void)
+{
+ platform_driver_unregister(&omapfb_driver);
+}
+
+module_param_named(accel, def_accel, uint, 0664);
+module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);
+module_param_named(vxres, def_vxres, long, 0664);
+module_param_named(vyres, def_vyres, long, 0664);
+module_param_named(rotate, def_rotate, uint, 0664);
+module_param_named(mirror, def_mirror, uint, 0664);
+module_param_named(manual_update, manual_update, bool, 0664);
+
+module_init(omapfb_init);
+module_exit(omapfb_cleanup);
+
+MODULE_DESCRIPTION("TI OMAP framebuffer driver");
+MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
new file mode 100644
index 000000000000..2b4269813b22
--- /dev/null
+++ b/drivers/video/omap/rfbi.c
@@ -0,0 +1,588 @@
+/*
+ * OMAP2 Remote Frame Buffer Interface support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/arch/omapfb.h>
+
+#include "dispc.h"
+
+/* To work around an RFBI transfer rate limitation */
+#define OMAP_RFBI_RATE_LIMIT 1
+
+#define RFBI_BASE 0x48050800
+#define RFBI_REVISION 0x0000
+#define RFBI_SYSCONFIG 0x0010
+#define RFBI_SYSSTATUS 0x0014
+#define RFBI_CONTROL 0x0040
+#define RFBI_PIXEL_CNT 0x0044
+#define RFBI_LINE_NUMBER 0x0048
+#define RFBI_CMD 0x004c
+#define RFBI_PARAM 0x0050
+#define RFBI_DATA 0x0054
+#define RFBI_READ 0x0058
+#define RFBI_STATUS 0x005c
+#define RFBI_CONFIG0 0x0060
+#define RFBI_ONOFF_TIME0 0x0064
+#define RFBI_CYCLE_TIME0 0x0068
+#define RFBI_DATA_CYCLE1_0 0x006c
+#define RFBI_DATA_CYCLE2_0 0x0070
+#define RFBI_DATA_CYCLE3_0 0x0074
+#define RFBI_VSYNC_WIDTH 0x0090
+#define RFBI_HSYNC_WIDTH 0x0094
+
+#define DISPC_BASE 0x48050400
+#define DISPC_CONTROL 0x0040
+
+static struct {
+ u32 base;
+ void (*lcdc_callback)(void *data);
+ void *lcdc_callback_data;
+ unsigned long l4_khz;
+ int bits_per_cycle;
+ struct omapfb_device *fbdev;
+ struct clk *dss_ick;
+ struct clk *dss1_fck;
+ unsigned tearsync_pin_cnt;
+ unsigned tearsync_mode;
+} rfbi;
+
+static inline void rfbi_write_reg(int idx, u32 val)
+{
+ __raw_writel(val, rfbi.base + idx);
+}
+
+static inline u32 rfbi_read_reg(int idx)
+{
+ return __raw_readl(rfbi.base + idx);
+}
+
+static int rfbi_get_clocks(void)
+{
+ if (IS_ERR((rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "dss_ick")))) {
+ dev_err(rfbi.fbdev->dev, "can't get dss_ick");
+ return PTR_ERR(rfbi.dss_ick);
+ }
+
+ if (IS_ERR((rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck")))) {
+ dev_err(rfbi.fbdev->dev, "can't get dss1_fck");
+ clk_put(rfbi.dss_ick);
+ return PTR_ERR(rfbi.dss1_fck);
+ }
+
+ return 0;
+}
+
+static void rfbi_put_clocks(void)
+{
+ clk_put(rfbi.dss1_fck);
+ clk_put(rfbi.dss_ick);
+}
+
+static void rfbi_enable_clocks(int enable)
+{
+ if (enable) {
+ clk_enable(rfbi.dss_ick);
+ clk_enable(rfbi.dss1_fck);
+ } else {
+ clk_disable(rfbi.dss1_fck);
+ clk_disable(rfbi.dss_ick);
+ }
+}
+
+
+#ifdef VERBOSE
+static void rfbi_print_timings(void)
+{
+ u32 l;
+ u32 time;
+
+ l = rfbi_read_reg(RFBI_CONFIG0);
+ time = 1000000000 / rfbi.l4_khz;
+ if (l & (1 << 4))
+ time *= 2;
+
+ dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
+ l = rfbi_read_reg(RFBI_ONOFF_TIME0);
+ dev_dbg(rfbi.fbdev->dev,
+ "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+ "REONTIME %d, REOFFTIME %d\n",
+ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+ (l >> 20) & 0x0f, (l >> 24) & 0x3f);
+
+ l = rfbi_read_reg(RFBI_CYCLE_TIME0);
+ dev_dbg(rfbi.fbdev->dev,
+ "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+ "ACCESSTIME %d\n",
+ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
+ (l >> 22) & 0x3f);
+}
+#else
+static void rfbi_print_timings(void) {}
+#endif
+
+static void rfbi_set_timings(const struct extif_timings *t)
+{
+ u32 l;
+
+ BUG_ON(!t->converted);
+
+ rfbi_enable_clocks(1);
+ rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
+ rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
+
+ l = rfbi_read_reg(RFBI_CONFIG0);
+ l &= ~(1 << 4);
+ l |= (t->tim[2] ? 1 : 0) << 4;
+ rfbi_write_reg(RFBI_CONFIG0, l);
+
+ rfbi_print_timings();
+ rfbi_enable_clocks(0);
+}
+
+static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+ *clk_period = 1000000000 / rfbi.l4_khz;
+ *max_clk_div = 2;
+}
+
+static int ps_to_rfbi_ticks(int time, int div)
+{
+ unsigned long tick_ps;
+ int ret;
+
+ /* Calculate in picosecs to yield more exact results */
+ tick_ps = 1000000000 / (rfbi.l4_khz) * div;
+
+ ret = (time + tick_ps - 1) / tick_ps;
+
+ return ret;
+}
+
+#ifdef OMAP_RFBI_RATE_LIMIT
+static unsigned long rfbi_get_max_tx_rate(void)
+{
+ unsigned long l4_rate, dss1_rate;
+ int min_l4_ticks = 0;
+ int i;
+
+ /* According to TI this can't be calculated so make the
+ * adjustments for a couple of known frequencies and warn for
+ * others.
+ */
+ static const struct {
+ unsigned long l4_clk; /* HZ */
+ unsigned long dss1_clk; /* HZ */
+ unsigned long min_l4_ticks;
+ } ftab[] = {
+ { 55, 132, 7, }, /* 7.86 MPix/s */
+ { 110, 110, 12, }, /* 9.16 MPix/s */
+ { 110, 132, 10, }, /* 11 Mpix/s */
+ { 120, 120, 10, }, /* 12 Mpix/s */
+ { 133, 133, 10, }, /* 13.3 Mpix/s */
+ };
+
+ l4_rate = rfbi.l4_khz / 1000;
+ dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
+
+ for (i = 0; i < ARRAY_SIZE(ftab); i++) {
+ /* Use a window instead of an exact match, to account
+ * for different DPLL multiplier / divider pairs.
+ */
+ if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
+ abs(ftab[i].dss1_clk - dss1_rate) < 3) {
+ min_l4_ticks = ftab[i].min_l4_ticks;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(ftab)) {
+ /* Can't be sure, return anyway the maximum not
+ * rate-limited. This might cause a problem only for the
+ * tearing synchronisation.
+ */
+ dev_err(rfbi.fbdev->dev,
+ "can't determine maximum RFBI transfer rate\n");
+ return rfbi.l4_khz * 1000;
+ }
+ return rfbi.l4_khz * 1000 / min_l4_ticks;
+}
+#else
+static int rfbi_get_max_tx_rate(void)
+{
+ return rfbi.l4_khz * 1000;
+}
+#endif
+
+
+static int rfbi_convert_timings(struct extif_timings *t)
+{
+ u32 l;
+ int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
+ int actim, recyc, wecyc;
+ int div = t->clk_div;
+
+ if (div <= 0 || div > 2)
+ return -1;
+
+ /* Make sure that after conversion it still holds that:
+ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
+ * csoff > cson, csoff >= max(weoff, reoff), actim > reon
+ */
+ weon = ps_to_rfbi_ticks(t->we_on_time, div);
+ weoff = ps_to_rfbi_ticks(t->we_off_time, div);
+ if (weoff <= weon)
+ weoff = weon + 1;
+ if (weon > 0x0f)
+ return -1;
+ if (weoff > 0x3f)
+ return -1;
+
+ reon = ps_to_rfbi_ticks(t->re_on_time, div);
+ reoff = ps_to_rfbi_ticks(t->re_off_time, div);
+ if (reoff <= reon)
+ reoff = reon + 1;
+ if (reon > 0x0f)
+ return -1;
+ if (reoff > 0x3f)
+ return -1;
+
+ cson = ps_to_rfbi_ticks(t->cs_on_time, div);
+ csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
+ if (csoff <= cson)
+ csoff = cson + 1;
+ if (csoff < max(weoff, reoff))
+ csoff = max(weoff, reoff);
+ if (cson > 0x0f)
+ return -1;
+ if (csoff > 0x3f)
+ return -1;
+
+ l = cson;
+ l |= csoff << 4;
+ l |= weon << 10;
+ l |= weoff << 14;
+ l |= reon << 20;
+ l |= reoff << 24;
+
+ t->tim[0] = l;
+
+ actim = ps_to_rfbi_ticks(t->access_time, div);
+ if (actim <= reon)
+ actim = reon + 1;
+ if (actim > 0x3f)
+ return -1;
+
+ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
+ if (wecyc < weoff)
+ wecyc = weoff;
+ if (wecyc > 0x3f)
+ return -1;
+
+ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
+ if (recyc < reoff)
+ recyc = reoff;
+ if (recyc > 0x3f)
+ return -1;
+
+ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
+ if (cs_pulse > 0x3f)
+ return -1;
+
+ l = wecyc;
+ l |= recyc << 6;
+ l |= cs_pulse << 12;
+ l |= actim << 22;
+
+ t->tim[1] = l;
+
+ t->tim[2] = div - 1;
+
+ t->converted = 1;
+
+ return 0;
+}
+
+static int rfbi_setup_tearsync(unsigned pin_cnt,
+ unsigned hs_pulse_time, unsigned vs_pulse_time,
+ int hs_pol_inv, int vs_pol_inv, int extif_div)
+{
+ int hs, vs;
+ int min;
+ u32 l;
+
+ if (pin_cnt != 1 && pin_cnt != 2)
+ return -EINVAL;
+
+ hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
+ vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
+ if (hs < 2)
+ return -EDOM;
+ if (pin_cnt == 2)
+ min = 2;
+ else
+ min = 4;
+ if (vs < min)
+ return -EDOM;
+ if (vs == hs)
+ return -EINVAL;
+ rfbi.tearsync_pin_cnt = pin_cnt;
+ dev_dbg(rfbi.fbdev->dev,
+ "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n",
+ pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv);
+
+ rfbi_enable_clocks(1);
+ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
+ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
+
+ l = rfbi_read_reg(RFBI_CONFIG0);
+ if (hs_pol_inv)
+ l &= ~(1 << 21);
+ else
+ l |= 1 << 21;
+ if (vs_pol_inv)
+ l &= ~(1 << 20);
+ else
+ l |= 1 << 20;
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+
+static int rfbi_enable_tearsync(int enable, unsigned line)
+{
+ u32 l;
+
+ dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n",
+ enable, line, rfbi.tearsync_mode);
+ if (line > (1 << 11) - 1)
+ return -EINVAL;
+
+ rfbi_enable_clocks(1);
+ l = rfbi_read_reg(RFBI_CONFIG0);
+ l &= ~(0x3 << 2);
+ if (enable) {
+ rfbi.tearsync_mode = rfbi.tearsync_pin_cnt;
+ l |= rfbi.tearsync_mode << 2;
+ } else
+ rfbi.tearsync_mode = 0;
+ rfbi_write_reg(RFBI_CONFIG0, l);
+ rfbi_write_reg(RFBI_LINE_NUMBER, line);
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+
+static void rfbi_write_command(const void *buf, unsigned int len)
+{
+ rfbi_enable_clocks(1);
+ if (rfbi.bits_per_cycle == 16) {
+ const u16 *w = buf;
+ BUG_ON(len & 1);
+ for (; len; len -= 2)
+ rfbi_write_reg(RFBI_CMD, *w++);
+ } else {
+ const u8 *b = buf;
+ BUG_ON(rfbi.bits_per_cycle != 8);
+ for (; len; len--)
+ rfbi_write_reg(RFBI_CMD, *b++);
+ }
+ rfbi_enable_clocks(0);
+}
+
+static void rfbi_read_data(void *buf, unsigned int len)
+{
+ rfbi_enable_clocks(1);
+ if (rfbi.bits_per_cycle == 16) {
+ u16 *w = buf;
+ BUG_ON(len & ~1);
+ for (; len; len -= 2) {
+ rfbi_write_reg(RFBI_READ, 0);
+ *w++ = rfbi_read_reg(RFBI_READ);
+ }
+ } else {
+ u8 *b = buf;
+ BUG_ON(rfbi.bits_per_cycle != 8);
+ for (; len; len--) {
+ rfbi_write_reg(RFBI_READ, 0);
+ *b++ = rfbi_read_reg(RFBI_READ);
+ }
+ }
+ rfbi_enable_clocks(0);
+}
+
+static void rfbi_write_data(const void *buf, unsigned int len)
+{
+ rfbi_enable_clocks(1);
+ if (rfbi.bits_per_cycle == 16) {
+ const u16 *w = buf;
+ BUG_ON(len & 1);
+ for (; len; len -= 2)
+ rfbi_write_reg(RFBI_PARAM, *w++);
+ } else {
+ const u8 *b = buf;
+ BUG_ON(rfbi.bits_per_cycle != 8);
+ for (; len; len--)
+ rfbi_write_reg(RFBI_PARAM, *b++);
+ }
+ rfbi_enable_clocks(0);
+}
+
+static void rfbi_transfer_area(int width, int height,
+ void (callback)(void * data), void *data)
+{
+ u32 w;
+
+ BUG_ON(callback == NULL);
+
+ rfbi_enable_clocks(1);
+ omap_dispc_set_lcd_size(width, height);
+
+ rfbi.lcdc_callback = callback;
+ rfbi.lcdc_callback_data = data;
+
+ rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+ w = rfbi_read_reg(RFBI_CONTROL);
+ w |= 1; /* enable */
+ if (!rfbi.tearsync_mode)
+ w |= 1 << 4; /* internal trigger, reset by HW */
+ rfbi_write_reg(RFBI_CONTROL, w);
+
+ omap_dispc_enable_lcd_out(1);
+}
+
+static inline void _stop_transfer(void)
+{
+ u32 w;
+
+ w = rfbi_read_reg(RFBI_CONTROL);
+ rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
+ rfbi_enable_clocks(0);
+}
+
+static void rfbi_dma_callback(void *data)
+{
+ _stop_transfer();
+ rfbi.lcdc_callback(rfbi.lcdc_callback_data);
+}
+
+static void rfbi_set_bits_per_cycle(int bpc)
+{
+ u32 l;
+
+ rfbi_enable_clocks(1);
+ l = rfbi_read_reg(RFBI_CONFIG0);
+ l &= ~(0x03 << 0);
+
+ switch (bpc) {
+ case 8:
+ break;
+ case 16:
+ l |= 3;
+ break;
+ default:
+ BUG();
+ }
+ rfbi_write_reg(RFBI_CONFIG0, l);
+ rfbi.bits_per_cycle = bpc;
+ rfbi_enable_clocks(0);
+}
+
+static int rfbi_init(struct omapfb_device *fbdev)
+{
+ u32 l;
+ int r;
+
+ rfbi.fbdev = fbdev;
+ rfbi.base = io_p2v(RFBI_BASE);
+
+ if ((r = rfbi_get_clocks()) < 0)
+ return r;
+ rfbi_enable_clocks(1);
+
+ rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
+
+ /* Reset */
+ rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
+ while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
+
+ l = rfbi_read_reg(RFBI_SYSCONFIG);
+ /* Enable autoidle and smart-idle */
+ l |= (1 << 0) | (2 << 3);
+ rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+ /* 16-bit interface, ITE trigger mode, 16-bit data */
+ l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
+ l |= (0 << 9) | (1 << 20) | (1 << 21);
+ rfbi_write_reg(RFBI_CONFIG0, l);
+
+ rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
+
+ l = rfbi_read_reg(RFBI_CONTROL);
+ /* Select CS0, clear bypass mode */
+ l = (0x01 << 2);
+ rfbi_write_reg(RFBI_CONTROL, l);
+
+ if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
+ dev_err(fbdev->dev, "can't get DISPC irq\n");
+ rfbi_enable_clocks(0);
+ return r;
+ }
+
+ l = rfbi_read_reg(RFBI_REVISION);
+ pr_info("omapfb: RFBI version %d.%d initialized\n",
+ (l >> 4) & 0x0f, l & 0x0f);
+
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+
+static void rfbi_cleanup(void)
+{
+ omap_dispc_free_irq();
+ rfbi_put_clocks();
+}
+
+const struct lcd_ctrl_extif omap2_ext_if = {
+ .init = rfbi_init,
+ .cleanup = rfbi_cleanup,
+ .get_clk_info = rfbi_get_clk_info,
+ .get_max_tx_rate = rfbi_get_max_tx_rate,
+ .set_bits_per_cycle = rfbi_set_bits_per_cycle,
+ .convert_timings = rfbi_convert_timings,
+ .set_timings = rfbi_set_timings,
+ .write_command = rfbi_write_command,
+ .read_data = rfbi_read_data,
+ .write_data = rfbi_write_data,
+ .transfer_area = rfbi_transfer_area,
+ .setup_tearsync = rfbi_setup_tearsync,
+ .enable_tearsync = rfbi_enable_tearsync,
+
+ .max_transmit_size = (u32) ~0,
+};
+
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
new file mode 100644
index 000000000000..81dbcf53cf0e
--- /dev/null
+++ b/drivers/video/omap/sossi.c
@@ -0,0 +1,686 @@
+/*
+ * OMAP1 Special OptimiSed Screen Interface support
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by 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/mm.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include "lcdc.h"
+
+#define MODULE_NAME "omapfb-sossi"
+
+#define OMAP_SOSSI_BASE 0xfffbac00
+#define SOSSI_ID_REG 0x00
+#define SOSSI_INIT1_REG 0x04
+#define SOSSI_INIT2_REG 0x08
+#define SOSSI_INIT3_REG 0x0c
+#define SOSSI_FIFO_REG 0x10
+#define SOSSI_REOTABLE_REG 0x14
+#define SOSSI_TEARING_REG 0x18
+#define SOSSI_INIT1B_REG 0x1c
+#define SOSSI_FIFOB_REG 0x20
+
+#define DMA_GSCR 0xfffedc04
+#define DMA_LCD_CCR 0xfffee3c2
+#define DMA_LCD_CTRL 0xfffee3c4
+#define DMA_LCD_LCH_CTRL 0xfffee3ea
+
+#define CONF_SOSSI_RESET_R (1 << 23)
+
+#define RD_ACCESS 0
+#define WR_ACCESS 1
+
+#define SOSSI_MAX_XMIT_BYTES (512 * 1024)
+
+static struct {
+ void __iomem *base;
+ struct clk *fck;
+ unsigned long fck_hz;
+ spinlock_t lock;
+ int bus_pick_count;
+ int bus_pick_width;
+ int tearsync_mode;
+ int tearsync_line;
+ void (*lcdc_callback)(void *data);
+ void *lcdc_callback_data;
+ int vsync_dma_pending;
+ /* timing for read and write access */
+ int clk_div;
+ u8 clk_tw0[2];
+ u8 clk_tw1[2];
+ /*
+ * if last_access is the same as current we don't have to change
+ * the timings
+ */
+ int last_access;
+
+ struct omapfb_device *fbdev;
+} sossi;
+
+static inline u32 sossi_read_reg(int reg)
+{
+ return readl(sossi.base + reg);
+}
+
+static inline u16 sossi_read_reg16(int reg)
+{
+ return readw(sossi.base + reg);
+}
+
+static inline u8 sossi_read_reg8(int reg)
+{
+ return readb(sossi.base + reg);
+}
+
+static inline void sossi_write_reg(int reg, u32 value)
+{
+ writel(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg16(int reg, u16 value)
+{
+ writew(value, sossi.base + reg);
+}
+
+static inline void sossi_write_reg8(int reg, u8 value)
+{
+ writeb(value, sossi.base + reg);
+}
+
+static void sossi_set_bits(int reg, u32 bits)
+{
+ sossi_write_reg(reg, sossi_read_reg(reg) | bits);
+}
+
+static void sossi_clear_bits(int reg, u32 bits)
+{
+ sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
+}
+
+#define HZ_TO_PS(x) (1000000000 / (x / 1000))
+
+static u32 ps_to_sossi_ticks(u32 ps, int div)
+{
+ u32 clk_period = HZ_TO_PS(sossi.fck_hz) * div;
+ return (clk_period + ps - 1) / clk_period;
+}
+
+static int calc_rd_timings(struct extif_timings *t)
+{
+ u32 tw0, tw1;
+ int reon, reoff, recyc, actim;
+ int div = t->clk_div;
+
+ /*
+ * Make sure that after conversion it still holds that:
+ * reoff > reon, recyc >= reoff, actim > reon
+ */
+ reon = ps_to_sossi_ticks(t->re_on_time, div);
+ /* reon will be exactly one sossi tick */
+ if (reon > 1)
+ return -1;
+
+ reoff = ps_to_sossi_ticks(t->re_off_time, div);
+
+ if (reoff <= reon)
+ reoff = reon + 1;
+
+ tw0 = reoff - reon;
+ if (tw0 > 0x10)
+ return -1;
+
+ recyc = ps_to_sossi_ticks(t->re_cycle_time, div);
+ if (recyc <= reoff)
+ recyc = reoff + 1;
+
+ tw1 = recyc - tw0;
+ /* values less then 3 result in the SOSSI block resetting itself */
+ if (tw1 < 3)
+ tw1 = 3;
+ if (tw1 > 0x40)
+ return -1;
+
+ actim = ps_to_sossi_ticks(t->access_time, div);
+ if (actim < reoff)
+ actim++;
+ /*
+ * access time (data hold time) will be exactly one sossi
+ * tick
+ */
+ if (actim - reoff > 1)
+ return -1;
+
+ t->tim[0] = tw0 - 1;
+ t->tim[1] = tw1 - 1;
+
+ return 0;
+}
+
+static int calc_wr_timings(struct extif_timings *t)
+{
+ u32 tw0, tw1;
+ int weon, weoff, wecyc;
+ int div = t->clk_div;
+
+ /*
+ * Make sure that after conversion it still holds that:
+ * weoff > weon, wecyc >= weoff
+ */
+ weon = ps_to_sossi_ticks(t->we_on_time, div);
+ /* weon will be exactly one sossi tick */
+ if (weon > 1)
+ return -1;
+
+ weoff = ps_to_sossi_ticks(t->we_off_time, div);
+ if (weoff <= weon)
+ weoff = weon + 1;
+ tw0 = weoff - weon;
+ if (tw0 > 0x10)
+ return -1;
+
+ wecyc = ps_to_sossi_ticks(t->we_cycle_time, div);
+ if (wecyc <= weoff)
+ wecyc = weoff + 1;
+
+ tw1 = wecyc - tw0;
+ /* values less then 3 result in the SOSSI block resetting itself */
+ if (tw1 < 3)
+ tw1 = 3;
+ if (tw1 > 0x40)
+ return -1;
+
+ t->tim[2] = tw0 - 1;
+ t->tim[3] = tw1 - 1;
+
+ return 0;
+}
+
+static void _set_timing(int div, int tw0, int tw1)
+{
+ u32 l;
+
+#ifdef VERBOSE
+ dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n",
+ tw0 + 1, tw1 + 1, div);
+#endif
+
+ clk_set_rate(sossi.fck, sossi.fck_hz / div);
+ clk_enable(sossi.fck);
+ l = sossi_read_reg(SOSSI_INIT1_REG);
+ l &= ~((0x0f << 20) | (0x3f << 24));
+ l |= (tw0 << 20) | (tw1 << 24);
+ sossi_write_reg(SOSSI_INIT1_REG, l);
+ clk_disable(sossi.fck);
+}
+
+static void _set_bits_per_cycle(int bus_pick_count, int bus_pick_width)
+{
+ u32 l;
+
+ l = sossi_read_reg(SOSSI_INIT3_REG);
+ l &= ~0x3ff;
+ l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
+ sossi_write_reg(SOSSI_INIT3_REG, l);
+}
+
+static void _set_tearsync_mode(int mode, unsigned line)
+{
+ u32 l;
+
+ l = sossi_read_reg(SOSSI_TEARING_REG);
+ l &= ~(((1 << 11) - 1) << 15);
+ l |= line << 15;
+ l &= ~(0x3 << 26);
+ l |= mode << 26;
+ sossi_write_reg(SOSSI_TEARING_REG, l);
+ if (mode)
+ sossi_set_bits(SOSSI_INIT2_REG, 1 << 6); /* TE logic */
+ else
+ sossi_clear_bits(SOSSI_INIT2_REG, 1 << 6);
+}
+
+static inline void set_timing(int access)
+{
+ if (access != sossi.last_access) {
+ sossi.last_access = access;
+ _set_timing(sossi.clk_div,
+ sossi.clk_tw0[access], sossi.clk_tw1[access]);
+ }
+}
+
+static void sossi_start_transfer(void)
+{
+ /* WE */
+ sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
+ /* CS active low */
+ sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void sossi_stop_transfer(void)
+{
+ /* WE */
+ sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
+ /* CS active low */
+ sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
+}
+
+static void wait_end_of_write(void)
+{
+ /* Before reading we must check if some writings are going on */
+ while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
+}
+
+static void send_data(const void *data, unsigned int len)
+{
+ while (len >= 4) {
+ sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
+ len -= 4;
+ data += 4;
+ }
+ while (len >= 2) {
+ sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
+ len -= 2;
+ data += 2;
+ }
+ while (len) {
+ sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
+ len--;
+ data++;
+ }
+}
+
+static void set_cycles(unsigned int len)
+{
+ unsigned long nr_cycles = len / (sossi.bus_pick_width / 8);
+
+ BUG_ON((nr_cycles - 1) & ~0x3ffff);
+
+ sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
+ sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
+}
+
+static int sossi_convert_timings(struct extif_timings *t)
+{
+ int r = 0;
+ int div = t->clk_div;
+
+ t->converted = 0;
+
+ if (div <= 0 || div > 8)
+ return -1;
+
+ /* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */
+ if ((r = calc_rd_timings(t)) < 0)
+ return r;
+
+ if ((r = calc_wr_timings(t)) < 0)
+ return r;
+
+ t->tim[4] = div;
+
+ t->converted = 1;
+
+ return 0;
+}
+
+static void sossi_set_timings(const struct extif_timings *t)
+{
+ BUG_ON(!t->converted);
+
+ sossi.clk_tw0[RD_ACCESS] = t->tim[0];
+ sossi.clk_tw1[RD_ACCESS] = t->tim[1];
+
+ sossi.clk_tw0[WR_ACCESS] = t->tim[2];
+ sossi.clk_tw1[WR_ACCESS] = t->tim[3];
+
+ sossi.clk_div = t->tim[4];
+}
+
+static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
+{
+ *clk_period = HZ_TO_PS(sossi.fck_hz);
+ *max_clk_div = 8;
+}
+
+static void sossi_set_bits_per_cycle(int bpc)
+{
+ int bus_pick_count, bus_pick_width;
+
+ /*
+ * We set explicitly the the bus_pick_count as well, although
+ * with remapping/reordering disabled it will be calculated by HW
+ * as (32 / bus_pick_width).
+ */
+ switch (bpc) {
+ case 8:
+ bus_pick_count = 4;
+ bus_pick_width = 8;
+ break;
+ case 16:
+ bus_pick_count = 2;
+ bus_pick_width = 16;
+ break;
+ default:
+ BUG();
+ return;
+ }
+ sossi.bus_pick_width = bus_pick_width;
+ sossi.bus_pick_count = bus_pick_count;
+}
+
+static int sossi_setup_tearsync(unsigned pin_cnt,
+ unsigned hs_pulse_time, unsigned vs_pulse_time,
+ int hs_pol_inv, int vs_pol_inv, int div)
+{
+ int hs, vs;
+ u32 l;
+
+ if (pin_cnt != 1 || div < 1 || div > 8)
+ return -EINVAL;
+
+ hs = ps_to_sossi_ticks(hs_pulse_time, div);
+ vs = ps_to_sossi_ticks(vs_pulse_time, div);
+ if (vs < 8 || vs <= hs || vs >= (1 << 12))
+ return -EDOM;
+ vs /= 8;
+ vs--;
+ if (hs > 8)
+ hs = 8;
+ if (hs)
+ hs--;
+
+ dev_dbg(sossi.fbdev->dev,
+ "setup_tearsync: hs %d vs %d hs_inv %d vs_inv %d\n",
+ hs, vs, hs_pol_inv, vs_pol_inv);
+
+ clk_enable(sossi.fck);
+ l = sossi_read_reg(SOSSI_TEARING_REG);
+ l &= ~((1 << 15) - 1);
+ l |= vs << 3;
+ l |= hs;
+ if (hs_pol_inv)
+ l |= 1 << 29;
+ else
+ l &= ~(1 << 29);
+ if (vs_pol_inv)
+ l |= 1 << 28;
+ else
+ l &= ~(1 << 28);
+ sossi_write_reg(SOSSI_TEARING_REG, l);
+ clk_disable(sossi.fck);
+
+ return 0;
+}
+
+static int sossi_enable_tearsync(int enable, unsigned line)
+{
+ int mode;
+
+ dev_dbg(sossi.fbdev->dev, "tearsync %d line %d\n", enable, line);
+ if (line >= 1 << 11)
+ return -EINVAL;
+ if (enable) {
+ if (line)
+ mode = 2; /* HS or VS */
+ else
+ mode = 3; /* VS only */
+ } else
+ mode = 0;
+ sossi.tearsync_line = line;
+ sossi.tearsync_mode = mode;
+
+ return 0;
+}
+
+static void sossi_write_command(const void *data, unsigned int len)
+{
+ clk_enable(sossi.fck);
+ set_timing(WR_ACCESS);
+ _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+ /* CMD#/DATA */
+ sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
+ set_cycles(len);
+ sossi_start_transfer();
+ send_data(data, len);
+ sossi_stop_transfer();
+ wait_end_of_write();
+ clk_disable(sossi.fck);
+}
+
+static void sossi_write_data(const void *data, unsigned int len)
+{
+ clk_enable(sossi.fck);
+ set_timing(WR_ACCESS);
+ _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+ /* CMD#/DATA */
+ sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+ set_cycles(len);
+ sossi_start_transfer();
+ send_data(data, len);
+ sossi_stop_transfer();
+ wait_end_of_write();
+ clk_disable(sossi.fck);
+}
+
+static void sossi_transfer_area(int width, int height,
+ void (callback)(void *data), void *data)
+{
+ BUG_ON(callback == NULL);
+
+ sossi.lcdc_callback = callback;
+ sossi.lcdc_callback_data = data;
+
+ clk_enable(sossi.fck);
+ set_timing(WR_ACCESS);
+ _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+ _set_tearsync_mode(sossi.tearsync_mode, sossi.tearsync_line);
+ /* CMD#/DATA */
+ sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+ set_cycles(width * height * sossi.bus_pick_width / 8);
+
+ sossi_start_transfer();
+ if (sossi.tearsync_mode) {
+ /*
+ * Wait for the sync signal and start the transfer only
+ * then. We can't seem to be able to use HW sync DMA for
+ * this since LCD DMA shows huge latencies, as if it
+ * would ignore some of the DMA requests from SoSSI.
+ */
+ unsigned long flags;
+
+ spin_lock_irqsave(&sossi.lock, flags);
+ sossi.vsync_dma_pending++;
+ spin_unlock_irqrestore(&sossi.lock, flags);
+ } else
+ /* Just start the transfer right away. */
+ omap_enable_lcd_dma();
+}
+
+static void sossi_dma_callback(void *data)
+{
+ omap_stop_lcd_dma();
+ sossi_stop_transfer();
+ clk_disable(sossi.fck);
+ sossi.lcdc_callback(sossi.lcdc_callback_data);
+}
+
+static void sossi_read_data(void *data, unsigned int len)
+{
+ clk_enable(sossi.fck);
+ set_timing(RD_ACCESS);
+ _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width);
+ /* CMD#/DATA */
+ sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+ set_cycles(len);
+ sossi_start_transfer();
+ while (len >= 4) {
+ *(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
+ len -= 4;
+ data += 4;
+ }
+ while (len >= 2) {
+ *(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
+ len -= 2;
+ data += 2;
+ }
+ while (len) {
+ *(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
+ len--;
+ data++;
+ }
+ sossi_stop_transfer();
+ clk_disable(sossi.fck);
+}
+
+static irqreturn_t sossi_match_irq(int irq, void *data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sossi.lock, flags);
+ if (sossi.vsync_dma_pending) {
+ sossi.vsync_dma_pending--;
+ omap_enable_lcd_dma();
+ }
+ spin_unlock_irqrestore(&sossi.lock, flags);
+ return IRQ_HANDLED;
+}
+
+static int sossi_init(struct omapfb_device *fbdev)
+{
+ u32 l, k;
+ struct clk *fck;
+ struct clk *dpll1out_ck;
+ int r;
+
+ sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
+ sossi.fbdev = fbdev;
+ spin_lock_init(&sossi.lock);
+
+ dpll1out_ck = clk_get(fbdev->dev, "ck_dpll1out");
+ if (IS_ERR(dpll1out_ck)) {
+ dev_err(fbdev->dev, "can't get DPLL1OUT clock\n");
+ return PTR_ERR(dpll1out_ck);
+ }
+ /*
+ * We need the parent clock rate, which we might divide further
+ * depending on the timing requirements of the controller. See
+ * _set_timings.
+ */
+ sossi.fck_hz = clk_get_rate(dpll1out_ck);
+ clk_put(dpll1out_ck);
+
+ fck = clk_get(fbdev->dev, "ck_sossi");
+ if (IS_ERR(fck)) {
+ dev_err(fbdev->dev, "can't get SoSSI functional clock\n");
+ return PTR_ERR(fck);
+ }
+ sossi.fck = fck;
+
+ /* Reset and enable the SoSSI module */
+ l = omap_readl(MOD_CONF_CTRL_1);
+ l |= CONF_SOSSI_RESET_R;
+ omap_writel(l, MOD_CONF_CTRL_1);
+ l &= ~CONF_SOSSI_RESET_R;
+ omap_writel(l, MOD_CONF_CTRL_1);
+
+ clk_enable(sossi.fck);
+ l = omap_readl(ARM_IDLECT2);
+ l &= ~(1 << 8); /* DMACK_REQ */
+ omap_writel(l, ARM_IDLECT2);
+
+ l = sossi_read_reg(SOSSI_INIT2_REG);
+ /* Enable and reset the SoSSI block */
+ l |= (1 << 0) | (1 << 1);
+ sossi_write_reg(SOSSI_INIT2_REG, l);
+ /* Take SoSSI out of reset */
+ l &= ~(1 << 1);
+ sossi_write_reg(SOSSI_INIT2_REG, l);
+
+ sossi_write_reg(SOSSI_ID_REG, 0);
+ l = sossi_read_reg(SOSSI_ID_REG);
+ k = sossi_read_reg(SOSSI_ID_REG);
+
+ if (l != 0x55555555 || k != 0xaaaaaaaa) {
+ dev_err(fbdev->dev,
+ "invalid SoSSI sync pattern: %08x, %08x\n", l, k);
+ r = -ENODEV;
+ goto err;
+ }
+
+ if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) {
+ dev_err(fbdev->dev, "can't get LCDC IRQ\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
+ l = sossi_read_reg(SOSSI_ID_REG);
+ dev_info(fbdev->dev, "SoSSI version %d.%d initialized\n",
+ l >> 16, l & 0xffff);
+
+ l = sossi_read_reg(SOSSI_INIT1_REG);
+ l |= (1 << 19); /* DMA_MODE */
+ l &= ~(1 << 31); /* REORDERING */
+ sossi_write_reg(SOSSI_INIT1_REG, l);
+
+ if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
+ IRQT_FALLING,
+ "sossi_match", sossi.fbdev->dev)) < 0) {
+ dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
+ goto err;
+ }
+
+ clk_disable(sossi.fck);
+ return 0;
+
+err:
+ clk_disable(sossi.fck);
+ clk_put(sossi.fck);
+ return r;
+}
+
+static void sossi_cleanup(void)
+{
+ omap_lcdc_free_dma_callback();
+ clk_put(sossi.fck);
+}
+
+struct lcd_ctrl_extif omap1_ext_if = {
+ .init = sossi_init,
+ .cleanup = sossi_cleanup,
+ .get_clk_info = sossi_get_clk_info,
+ .convert_timings = sossi_convert_timings,
+ .set_timings = sossi_set_timings,
+ .set_bits_per_cycle = sossi_set_bits_per_cycle,
+ .setup_tearsync = sossi_setup_tearsync,
+ .enable_tearsync = sossi_enable_tearsync,
+ .write_command = sossi_write_command,
+ .read_data = sossi_read_data,
+ .write_data = sossi_write_data,
+ .transfer_area = sossi_transfer_area,
+
+ .max_transmit_size = SOSSI_MAX_XMIT_BYTES,
+};
+
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index e64f8b5d0056..8503e733a172 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -52,7 +52,7 @@ struct fb_info_platinum {
struct {
__u8 red, green, blue;
} palette[256];
- u32 pseudo_palette[17];
+ u32 pseudo_palette[16];
volatile struct cmap_regs __iomem *cmap_regs;
unsigned long cmap_regs_phys;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 0a04483aa3e0..10c0cc6e93fc 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -24,7 +24,7 @@
* License. See the file COPYING in the main directory of this archive for
* more details.
*
- *
+ *
*/
#include <linux/module.h>
@@ -58,7 +58,7 @@
#endif
/*
- * Driver data
+ * Driver data
*/
static char *mode __devinitdata = NULL;
@@ -82,12 +82,12 @@ struct pm2fb_par
{
pm2type_t type; /* Board type */
unsigned char __iomem *v_regs;/* virtual address of p_regs */
- u32 memclock; /* memclock */
+ u32 memclock; /* memclock */
u32 video; /* video flags before blanking */
u32 mem_config; /* MemConfig reg at probe */
u32 mem_control; /* MemControl reg at probe */
u32 boot_address; /* BootAddress reg at probe */
- u32 palette[16];
+ u32 palette[16];
};
/*
@@ -95,12 +95,12 @@ struct pm2fb_par
* if we don't use modedb.
*/
static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
- .id = "",
+ .id = "",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.xpanstep = 1,
.ypanstep = 1,
- .ywrapstep = 0,
+ .ywrapstep = 0,
.accel = FB_ACCEL_3DLABS_PERMEDIA2,
};
@@ -109,26 +109,26 @@ static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
*/
static struct fb_var_screeninfo pm2fb_var __devinitdata = {
/* "640x480, 8 bpp @ 60 Hz */
- .xres = 640,
- .yres = 480,
- .xres_virtual = 640,
- .yres_virtual = 480,
- .bits_per_pixel =8,
- .red = {0, 8, 0},
- .blue = {0, 8, 0},
- .green = {0, 8, 0},
- .activate = FB_ACTIVATE_NOW,
- .height = -1,
- .width = -1,
- .accel_flags = 0,
- .pixclock = 39721,
- .left_margin = 40,
- .right_margin = 24,
- .upper_margin = 32,
- .lower_margin = 11,
- .hsync_len = 96,
- .vsync_len = 2,
- .vmode = FB_VMODE_NONINTERLACED
+ .xres = 640,
+ .yres = 480,
+ .xres_virtual = 640,
+ .yres_virtual = 480,
+ .bits_per_pixel = 8,
+ .red = {0, 8, 0},
+ .blue = {0, 8, 0},
+ .green = {0, 8, 0},
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .accel_flags = 0,
+ .pixclock = 39721,
+ .left_margin = 40,
+ .right_margin = 24,
+ .upper_margin = 32,
+ .lower_margin = 11,
+ .hsync_len = 96,
+ .vsync_len = 2,
+ .vmode = FB_VMODE_NONINTERLACED
};
/*
@@ -166,7 +166,7 @@ static inline u32 pm2_RDAC_RD(struct pm2fb_par* p, s32 idx)
pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
index = PM2VR_RD_INDEXED_DATA;
break;
- }
+ }
mb();
return pm2_RD(p, index);
}
@@ -182,7 +182,7 @@ static inline void pm2_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
index = PM2VR_RD_INDEXED_DATA;
break;
- }
+ }
wmb();
pm2_WR(p, index, v);
wmb();
@@ -197,7 +197,7 @@ static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
}
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
-#define WAIT_FIFO(p,a)
+#define WAIT_FIFO(p, a)
#else
static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
{
@@ -209,7 +209,7 @@ static inline void WAIT_FIFO(struct pm2fb_par* p, u32 a)
/*
* partial products for the supported horizontal resolutions.
*/
-#define PACKPP(p0,p1,p2) (((p2) << 6) | ((p1) << 3) | (p0))
+#define PACKPP(p0, p1, p2) (((p2) << 6) | ((p1) << 3) | (p0))
static const struct {
u16 width;
u16 pp;
@@ -357,7 +357,7 @@ static void reset_card(struct pm2fb_par* p)
static void reset_config(struct pm2fb_par* p)
{
WAIT_FIFO(p, 52);
- pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
+ pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG) &
~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
@@ -367,7 +367,7 @@ static void reset_config(struct pm2fb_par* p)
pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
- pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
+ pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
pm2_WR(p, PM2R_LB_READ_MODE, 0);
pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
@@ -535,7 +535,7 @@ static void set_video(struct pm2fb_par* p, u32 video) {
vsync = video;
DPRINTK("video = 0x%x\n", video);
-
+
/*
* The hardware cursor needs +vsync to recognise vert retrace.
* We may not be using the hardware cursor, but the X Glint
@@ -574,9 +574,9 @@ static void set_video(struct pm2fb_par* p, u32 video) {
*/
/**
- * pm2fb_check_var - Optional function. Validates a var passed in.
- * @var: frame buffer variable screen structure
- * @info: frame buffer structure that represents a single frame buffer
+ * pm2fb_check_var - Optional function. Validates a var passed in.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
*
* Checks to see if the hardware supports the state requested by
* var passed in.
@@ -615,23 +615,23 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
-
+
if (var->xres < 320 || var->xres > 1600) {
DPRINTK("width not supported: %u\n", var->xres);
return -EINVAL;
}
-
+
if (var->yres < 200 || var->yres > 1200) {
DPRINTK("height not supported: %u\n", var->yres);
return -EINVAL;
}
-
+
if (lpitch * var->yres_virtual > info->fix.smem_len) {
DPRINTK("no memory for screen (%ux%ux%u)\n",
var->xres, var->yres_virtual, var->bits_per_pixel);
return -EINVAL;
}
-
+
if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
return -EINVAL;
@@ -672,17 +672,17 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
}
var->height = var->width = -1;
-
+
var->accel_flags = 0; /* Can't mmap if this is on */
-
+
DPRINTK("Checking graphics mode at %dx%d depth %d\n",
var->xres, var->yres, var->bits_per_pixel);
return 0;
}
/**
- * pm2fb_set_par - Alters the hardware state.
- * @info: frame buffer structure that represents a single frame buffer
+ * pm2fb_set_par - Alters the hardware state.
+ * @info: frame buffer structure that represents a single frame buffer
*
* Using the fb_var_screeninfo in fb_info we set the resolution of the
* this particular framebuffer.
@@ -709,7 +709,7 @@ static int pm2fb_set_par(struct fb_info *info)
clear_palette(par);
if ( par->memclock )
set_memclock(par, par->memclock);
-
+
width = (info->var.xres_virtual + 7) & ~7;
height = info->var.yres_virtual;
depth = (info->var.bits_per_pixel + 7) & ~7;
@@ -722,7 +722,7 @@ static int pm2fb_set_par(struct fb_info *info)
DPRINTK("pixclock too high (%uKHz)\n", pixclock);
return -EINVAL;
}
-
+
hsstart = to3264(info->var.right_margin, depth, data64);
hsend = hsstart + to3264(info->var.hsync_len, depth, data64);
hbend = hsend + to3264(info->var.left_margin, depth, data64);
@@ -737,7 +737,7 @@ static int pm2fb_set_par(struct fb_info *info)
base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1);
if (data64)
video |= PM2F_DATA_64_ENABLE;
-
+
if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) {
if (lowhsync) {
DPRINTK("ignoring +hsync, using -hsync.\n");
@@ -778,9 +778,9 @@ static int pm2fb_set_par(struct fb_info *info)
WAIT_FIFO(par, 1);
pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0);
}
-
+
set_aperture(par, depth);
-
+
mb();
WAIT_FIFO(par, 19);
pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL,
@@ -847,22 +847,22 @@ static int pm2fb_set_par(struct fb_info *info)
set_pixclock(par, pixclock);
DPRINTK("Setting graphics mode at %dx%d depth %d\n",
info->var.xres, info->var.yres, info->var.bits_per_pixel);
- return 0;
+ return 0;
}
/**
- * pm2fb_setcolreg - Sets a color register.
- * @regno: boolean, 0 copy local, 1 get_user() function
- * @red: frame buffer colormap structure
- * @green: The green value which can be up to 16 bits wide
+ * pm2fb_setcolreg - Sets a color register.
+ * @regno: boolean, 0 copy local, 1 get_user() function
+ * @red: frame buffer colormap structure
+ * @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
- * @transp: If supported the alpha value which can be up to 16 bits wide.
- * @info: frame buffer info structure
- *
- * Set a single color register. The values supplied have a 16 bit
- * magnitude which needs to be scaled in this function for the hardware.
+ * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @info: frame buffer info structure
+ *
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude which needs to be scaled in this function for the hardware.
* Pretty much a direct lift from tdfxfb.c.
- *
+ *
* Returns negative errno on error, or zero on success.
*/
static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -906,7 +906,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
* (blue << blue.offset) | (transp << transp.offset)
* RAMDAC does not exist
*/
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16)
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
case FB_VISUAL_PSEUDOCOLOR:
@@ -916,9 +916,9 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
transp = CNVT_TOHW(transp, info->var.transp.length);
break;
case FB_VISUAL_DIRECTCOLOR:
- /* example here assumes 8 bit DAC. Might be different
- * for your hardware */
- red = CNVT_TOHW(red, 8);
+ /* example here assumes 8 bit DAC. Might be different
+ * for your hardware */
+ red = CNVT_TOHW(red, 8);
green = CNVT_TOHW(green, 8);
blue = CNVT_TOHW(blue, 8);
/* hey, there is bug in transp handling... */
@@ -940,11 +940,11 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
switch (info->var.bits_per_pixel) {
case 8:
- break;
- case 16:
+ break;
+ case 16:
case 24:
- case 32:
- par->palette[regno] = v;
+ case 32:
+ par->palette[regno] = v;
break;
}
return 0;
@@ -956,15 +956,15 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
}
/**
- * pm2fb_pan_display - Pans the display.
- * @var: frame buffer variable screen structure
- * @info: frame buffer structure that represents a single frame buffer
+ * pm2fb_pan_display - Pans the display.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
*
* Pan (or wrap, depending on the `vmode' field) the display using the
- * `xoffset' and `yoffset' fields of the `var' structure.
- * If the values don't fit, return -EINVAL.
+ * `xoffset' and `yoffset' fields of the `var' structure.
+ * If the values don't fit, return -EINVAL.
*
- * Returns negative errno on error, or zero on success.
+ * Returns negative errno on error, or zero on success.
*
*/
static int pm2fb_pan_display(struct fb_var_screeninfo *var,
@@ -980,24 +980,24 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
depth = (depth > 32) ? 32 : depth;
base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
WAIT_FIFO(p, 1);
- pm2_WR(p, PM2R_SCREEN_BASE, base);
+ pm2_WR(p, PM2R_SCREEN_BASE, base);
return 0;
}
/**
- * pm2fb_blank - Blanks the display.
- * @blank_mode: the blank mode we want.
- * @info: frame buffer structure that represents a single frame buffer
+ * pm2fb_blank - Blanks the display.
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
*
- * Blank the screen if blank_mode != 0, else unblank. Return 0 if
- * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
- * video mode which doesn't support it. Implements VESA suspend
- * and powerdown modes on hardware that supports disabling hsync/vsync:
- * blank_mode == 2: suspend vsync
- * blank_mode == 3: suspend hsync
- * blank_mode == 4: powerdown
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
*
- * Returns negative errno on error, or zero on success.
+ * Returns negative errno on error, or zero on success.
*
*/
static int pm2fb_blank(int blank_mode, struct fb_info *info)
@@ -1071,7 +1071,7 @@ static void pm2fb_block_op(struct fb_info* info, int copy,
pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x);
pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w);
wmb();
- pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE |
+ pm2_WR(par, PM2R_RENDER, PM2F_RENDER_RECTANGLE |
(x<xsrc ? PM2F_INCREASE_X : 0) |
(y<ysrc ? PM2F_INCREASE_Y : 0) |
(copy ? 0 : PM2F_RENDER_FASTFILL));
@@ -1234,7 +1234,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
DPRINTK("Adjusting register base for big-endian.\n");
#endif
DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);
-
+
/* Registers - request region and map it. */
if ( !request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,
"pm2fb regbase") ) {
@@ -1317,17 +1317,17 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
}
info->fbops = &pm2fb_ops;
- info->fix = pm2fb_fix;
+ info->fix = pm2fb_fix;
info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT |
- FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_FILLRECT;
+ FBINFO_HWACCEL_YPAN |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
if (!mode)
mode = "640x480@60";
-
- err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
+
+ err = fb_find_mode(&info->var, info, mode, NULL, 0, NULL, 8);
if (!err || err == 4)
info->var = pm2fb_var;
@@ -1348,8 +1348,8 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
return 0;
err_exit_all:
- fb_dealloc_cmap(&info->cmap);
- err_exit_both:
+ fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
iounmap(info->screen_base);
release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);
err_exit_mmio:
@@ -1374,7 +1374,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev)
struct pm2fb_par *par = info->par;
unregister_framebuffer(info);
-
+
iounmap(info->screen_base);
release_mem_region(fix->smem_start, fix->smem_len);
iounmap(par->v_regs);
@@ -1402,9 +1402,9 @@ static struct pci_device_id pm2fb_id_table[] = {
static struct pci_driver pm2fb_driver = {
.name = "pm2fb",
- .id_table = pm2fb_id_table,
- .probe = pm2fb_probe,
- .remove = __devexit_p(pm2fb_remove),
+ .id_table = pm2fb_id_table,
+ .probe = pm2fb_probe,
+ .remove = __devexit_p(pm2fb_remove),
};
MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
@@ -1423,7 +1423,7 @@ static int __init pm2fb_setup(char *options)
if (!options || !*options)
return 0;
- while ((this_opt = strsep(&options, ",")) != NULL) {
+ while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
if(!strcmp(this_opt, "lowhsync")) {
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index b52e883f0a52..5b3f54c0918e 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -77,7 +77,7 @@ static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
.xpanstep = 1,
.ypanstep = 1,
.ywrapstep = 0,
- .accel = FB_ACCEL_NONE,
+ .accel = FB_ACCEL_3DLABS_PERMEDIA3,
};
/*
@@ -185,6 +185,238 @@ static inline int pm3fb_shift_bpp(unsigned bpp, int v)
return 0;
}
+/* acceleration */
+static int pm3fb_sync(struct fb_info *info)
+{
+ struct pm3_par *par = info->par;
+
+ PM3_WAIT(par, 2);
+ PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+ PM3_WRITE_REG(par, PM3Sync, 0);
+ mb();
+ do {
+ while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0);
+ rmb();
+ } while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);
+
+ return 0;
+}
+
+static void pm3fb_init_engine(struct fb_info *info)
+{
+ struct pm3_par *par = info->par;
+ const u32 width = (info->var.xres_virtual + 7) & ~7;
+
+ PM3_WAIT(par, 50);
+ PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
+ PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
+ PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
+ PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
+ PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
+ PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
+ PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
+ PM3_WRITE_REG(par, PM3GIDMode, 0x0);
+ PM3_WRITE_REG(par, PM3DepthMode, 0x0);
+ PM3_WRITE_REG(par, PM3StencilMode, 0x0);
+ PM3_WRITE_REG(par, PM3StencilData, 0x0);
+ PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
+ PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
+ PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
+ PM3_WRITE_REG(par, PM3LUTMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
+ PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
+ PM3_WRITE_REG(par, PM3FogMode, 0x0);
+ PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
+ PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
+ PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
+ PM3_WRITE_REG(par, PM3YUVMode, 0x0);
+ PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
+ PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
+ PM3_WRITE_REG(par, PM3DitherMode, 0x0);
+ PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
+ PM3_WRITE_REG(par, PM3RouterMode, 0x0);
+ PM3_WRITE_REG(par, PM3Window, 0x0);
+
+ PM3_WRITE_REG(par, PM3Config2D, 0x0);
+
+ PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);
+
+ PM3_WRITE_REG(par, PM3XBias, 0x0);
+ PM3_WRITE_REG(par, PM3YBias, 0x0);
+ PM3_WRITE_REG(par, PM3DeltaControl, 0x0);
+
+ PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);
+
+ PM3_WRITE_REG(par, PM3FBDestReadEnables,
+ PM3FBDestReadEnables_E(0xff) |
+ PM3FBDestReadEnables_R(0xff) |
+ PM3FBDestReadEnables_ReferenceAlpha(0xff));
+ PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
+ PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
+ PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
+ PM3FBDestReadBufferWidth_Width(width));
+
+ PM3_WRITE_REG(par, PM3FBDestReadMode,
+ PM3FBDestReadMode_ReadEnable |
+ PM3FBDestReadMode_Enable0);
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
+ PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
+ PM3FBSourceReadBufferWidth_Width(width));
+ PM3_WRITE_REG(par, PM3FBSourceReadMode,
+ PM3FBSourceReadMode_Blocking |
+ PM3FBSourceReadMode_ReadEnable);
+
+ PM3_WAIT(par, 2);
+ {
+ unsigned long rm = 1;
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ PM3_WRITE_REG(par, PM3PixelSize,
+ PM3PixelSize_GLOBAL_8BIT);
+ break;
+ case 16:
+ PM3_WRITE_REG(par, PM3PixelSize,
+ PM3PixelSize_GLOBAL_16BIT);
+ break;
+ case 32:
+ PM3_WRITE_REG(par, PM3PixelSize,
+ PM3PixelSize_GLOBAL_32BIT);
+ break;
+ default:
+ DPRINTK(1, "Unsupported depth %d\n",
+ info->var.bits_per_pixel);
+ break;
+ }
+ PM3_WRITE_REG(par, PM3RasterizerMode, rm);
+ }
+
+ PM3_WAIT(par, 20);
+ PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
+ PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
+ PM3_WRITE_REG(par, PM3FBWriteMode,
+ PM3FBWriteMode_WriteEnable |
+ PM3FBWriteMode_OpaqueSpan |
+ PM3FBWriteMode_Enable0);
+ PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
+ PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
+ PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
+ PM3FBWriteBufferWidth_Width(width));
+
+ PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
+ {
+ /* size in lines of FB */
+ unsigned long sofb = info->screen_size /
+ info->fix.line_length;
+ if (sofb > 4095)
+ PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
+ else
+ PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ PM3_WRITE_REG(par, PM3DitherMode,
+ (1 << 10) | (2 << 3));
+ break;
+ case 16:
+ PM3_WRITE_REG(par, PM3DitherMode,
+ (1 << 10) | (1 << 3));
+ break;
+ case 32:
+ PM3_WRITE_REG(par, PM3DitherMode,
+ (1 << 10) | (0 << 3));
+ break;
+ default:
+ DPRINTK(1, "Unsupported depth %d\n",
+ info->current_par->depth);
+ break;
+ }
+ }
+
+ PM3_WRITE_REG(par, PM3dXDom, 0x0);
+ PM3_WRITE_REG(par, PM3dXSub, 0x0);
+ PM3_WRITE_REG(par, PM3dY, (1 << 16));
+ PM3_WRITE_REG(par, PM3StartXDom, 0x0);
+ PM3_WRITE_REG(par, PM3StartXSub, 0x0);
+ PM3_WRITE_REG(par, PM3StartY, 0x0);
+ PM3_WRITE_REG(par, PM3Count, 0x0);
+
+/* Disable LocalBuffer. better safe than sorry */
+ PM3_WRITE_REG(par, PM3LBDestReadMode, 0x0);
+ PM3_WRITE_REG(par, PM3LBDestReadEnables, 0x0);
+ PM3_WRITE_REG(par, PM3LBSourceReadMode, 0x0);
+ PM3_WRITE_REG(par, PM3LBWriteMode, 0x0);
+
+ pm3fb_sync(info);
+}
+
+static void pm3fb_fillrect (struct fb_info *info,
+ const struct fb_fillrect *region)
+{
+ struct pm3_par *par = info->par;
+ struct fb_fillrect modded;
+ int vxres, vyres;
+ u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+ ((u32*)info->pseudo_palette)[region->color] : region->color;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if ((info->flags & FBINFO_HWACCEL_DISABLED) ||
+ region->rop != ROP_COPY ) {
+ cfb_fillrect(info, region);
+ return;
+ }
+
+ vxres = info->var.xres_virtual;
+ vyres = info->var.yres_virtual;
+
+ memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+ if(!modded.width || !modded.height ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if(modded.dx + modded.width > vxres)
+ modded.width = vxres - modded.dx;
+ if(modded.dy + modded.height > vyres)
+ modded.height = vyres - modded.dy;
+
+ if(info->var.bits_per_pixel == 8)
+ color |= color << 8;
+ if(info->var.bits_per_pixel <= 16)
+ color |= color << 16;
+
+ PM3_WAIT(par, 4);
+
+ PM3_WRITE_REG(par, PM3Config2D,
+ PM3Config2D_UseConstantSource |
+ PM3Config2D_ForegroundROPEnable |
+ (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
+ PM3Config2D_FBWriteEnable);
+
+ PM3_WRITE_REG(par, PM3ForegroundColor, color);
+
+ PM3_WRITE_REG(par, PM3RectanglePosition,
+ (PM3RectanglePosition_XOffset(modded.dx)) |
+ (PM3RectanglePosition_YOffset(modded.dy)));
+
+ PM3_WRITE_REG(par, PM3Render2D,
+ PM3Render2D_XPositive |
+ PM3Render2D_YPositive |
+ PM3Render2D_Operation_Normal |
+ PM3Render2D_SpanOperation |
+ (PM3Render2D_Width(modded.width)) |
+ (PM3Render2D_Height(modded.height)));
+}
+/* end of acceleration functions */
+
/* write the mode to registers */
static void pm3fb_write_mode(struct fb_info *info)
{
@@ -380,8 +612,6 @@ static void pm3fb_write_mode(struct fb_info *info)
/*
* hardware independent functions
*/
-int pm3fb_init(void);
-
static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
u32 lpitch;
@@ -528,6 +758,7 @@ static int pm3fb_set_par(struct fb_info *info)
pm3fb_clear_colormap(par, 0, 0, 0);
PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
PM3RD_CursorMode_CURSOR_DISABLE);
+ pm3fb_init_engine(info);
pm3fb_write_mode(info);
return 0;
}
@@ -675,10 +906,11 @@ static struct fb_ops pm3fb_ops = {
.fb_set_par = pm3fb_set_par,
.fb_setcolreg = pm3fb_setcolreg,
.fb_pan_display = pm3fb_pan_display,
- .fb_fillrect = cfb_fillrect,
+ .fb_fillrect = pm3fb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = pm3fb_blank,
+ .fb_sync = pm3fb_sync,
};
/* ------------------------------------------------------------------------- */
@@ -847,7 +1079,8 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
info->fix = pm3fb_fix;
info->pseudo_palette = par->palette;
- info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/
+ info->flags = FBINFO_DEFAULT |
+ FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/
/*
* This should give a reasonable default video mode. The following is
@@ -935,35 +1168,12 @@ static struct pci_driver pm3fb_driver = {
MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
-#ifndef MODULE
- /*
- * Setup
- */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-static int __init pm3fb_setup(char *options)
+static int __init pm3fb_init(void)
{
- /* Parse user speficied options (`video=pm3fb:') */
- return 0;
-}
-#endif /* MODULE */
-
-int __init pm3fb_init(void)
-{
- /*
- * For kernel boot options (in 'video=pm3fb:<options>' format)
- */
#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("pm3fb", &option))
+ if (fb_get_options("pm3fb", NULL))
return -ENODEV;
- pm3fb_setup(option);
#endif
-
return pci_register_driver(&pm3fb_driver);
}
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 9cf92ba5d6e3..3972aa8cf859 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -27,7 +27,6 @@
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
#include <linux/console.h>
#include <linux/ioctl.h>
#include <linux/notifier.h>
@@ -46,6 +45,9 @@
#include <asm/ps3fb.h>
#include <asm/ps3.h>
+
+#define DEVICE_NAME "ps3fb"
+
#ifdef PS3FB_DEBUG
#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
#else
@@ -126,7 +128,6 @@ struct gpu_driver_info {
struct ps3fb_priv {
unsigned int irq_no;
- void *dev;
u64 context_handle, memory_handle;
void *xdr_ea;
@@ -171,7 +172,7 @@ static const struct ps3fb_res_table ps3fb_res[] = {
{ 0, 0, 0, 0 , 0} };
/* default resolution */
-#define GPU_RES_INDEX 0 /* 720 x 480 */
+#define GPU_RES_INDEX 0 /* 720 x 480 */
static const struct fb_videomode ps3fb_modedb[] = {
/* 60 Hz broadcast modes (modes "1" to "5") */
@@ -298,10 +299,9 @@ static const struct fb_videomode ps3fb_modedb[] = {
#define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
static int ps3fb_mode;
-module_param(ps3fb_mode, bool, 0);
-
-static char *mode_option __initdata;
+module_param(ps3fb_mode, int, 0);
+static char *mode_option __devinitdata;
static int ps3fb_get_res_table(u32 xres, u32 yres)
{
@@ -681,15 +681,15 @@ int ps3fb_wait_for_vsync(u32 crtc)
EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
-void ps3fb_flip_ctl(int on)
+void ps3fb_flip_ctl(int on, void *data)
{
+ struct ps3fb_priv *priv = data;
if (on)
- atomic_dec_if_positive(&ps3fb.ext_flip);
+ atomic_dec_if_positive(&priv->ext_flip);
else
- atomic_inc(&ps3fb.ext_flip);
+ atomic_inc(&priv->ext_flip);
}
-EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
/*
* ioctl
@@ -812,6 +812,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
static int ps3fbd(void *arg)
{
+ set_freezable();
while (!kthread_should_stop()) {
try_to_freeze();
set_current_state(TASK_INTERRUPTIBLE);
@@ -851,37 +852,9 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
return IRQ_HANDLED;
}
-#ifndef MODULE
-static int __init ps3fb_setup(char *options)
-{
- char *this_opt;
- int mode = 0;
-
- if (!options || !*options)
- return 0; /* no options */
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
- if (!strncmp(this_opt, "mode:", 5))
- mode = simple_strtoul(this_opt + 5, NULL, 0);
- else
- mode_option = this_opt;
- }
- return mode;
-}
-#endif /* MODULE */
-
- /*
- * Initialisation
- */
-static void ps3fb_platform_release(struct device *device)
-{
- /* This is called when the reference count goes to zero. */
-}
-
-static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
+ struct ps3_system_bus_device *dev)
{
int error;
@@ -897,7 +870,6 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
return -EINVAL;
}
- ps3fb.dev = dev;
error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
&ps3fb.irq_no);
if (error) {
@@ -907,7 +879,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
}
error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
- "ps3fb vsync", ps3fb.dev);
+ DEVICE_NAME, dev);
if (error) {
printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
error);
@@ -966,16 +938,45 @@ static struct fb_ops ps3fb_ops = {
};
static struct fb_fix_screeninfo ps3fb_fix __initdata = {
- .id = "PS3 FB",
+ .id = DEVICE_NAME,
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.accel = FB_ACCEL_NONE,
};
-static int __init ps3fb_probe(struct platform_device *dev)
+static int ps3fb_set_sync(void)
+{
+ int status;
+
+#ifdef HEAD_A
+ status = lv1_gpu_context_attribute(0x0,
+ L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+ 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+ if (status) {
+ printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC "
+ "failed: %d\n", __func__, status);
+ return -1;
+ }
+#endif
+#ifdef HEAD_B
+ status = lv1_gpu_context_attribute(0x0,
+ L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+ 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+ if (status) {
+ printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE "
+ "failed: %d\n", __func__, status);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
{
struct fb_info *info;
int retval = -ENOMEM;
+ u32 xres, yres;
u64 ddr_lpar = 0;
u64 lpar_dma_control = 0;
u64 lpar_driver_info = 0;
@@ -986,6 +987,30 @@ static int __init ps3fb_probe(struct platform_device *dev)
unsigned long offset;
struct task_struct *task;
+ status = ps3_open_hv_device(dev);
+ if (status) {
+ printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+ goto err;
+ }
+
+ if (!ps3fb_mode)
+ ps3fb_mode = ps3av_get_mode();
+ DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+
+ if (ps3fb_mode > 0 &&
+ !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
+ ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+ DPRINTK("res_index:%d\n", ps3fb.res_index);
+ } else
+ ps3fb.res_index = GPU_RES_INDEX;
+
+ atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
+ atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
+ init_waitqueue_head(&ps3fb.wait_vsync);
+ ps3fb.num_frames = 1;
+
+ ps3fb_set_sync();
+
/* get gpu context handle */
status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
&ps3fb.memory_handle, &ddr_lpar);
@@ -1029,7 +1054,7 @@ static int __init ps3fb_probe(struct platform_device *dev)
* leakage into userspace
*/
memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
- info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+ info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
if (!info)
goto err_free_irq;
@@ -1061,19 +1086,20 @@ static int __init ps3fb_probe(struct platform_device *dev)
if (retval < 0)
goto err_fb_dealloc;
- platform_set_drvdata(dev, info);
+ dev->core.driver_data = info;
printk(KERN_INFO
"fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
info->node, ps3fb_videomemory.size >> 10);
- task = kthread_run(ps3fbd, info, "ps3fbd");
+ task = kthread_run(ps3fbd, info, DEVICE_NAME);
if (IS_ERR(task)) {
retval = PTR_ERR(task);
goto err_unregister_framebuffer;
}
ps3fb.task = task;
+ ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);
return 0;
@@ -1084,7 +1110,7 @@ err_fb_dealloc:
err_framebuffer_release:
framebuffer_release(info);
err_free_irq:
- free_irq(ps3fb.irq_no, ps3fb.dev);
+ free_irq(ps3fb.irq_no, dev);
ps3_irq_plug_destroy(ps3fb.irq_no);
err_iounmap_dinfo:
iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1096,26 +1122,30 @@ err:
return retval;
}
-static void ps3fb_shutdown(struct platform_device *dev)
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
{
- ps3fb_flip_ctl(0); /* flip off */
+ int status;
+ struct fb_info *info = dev->core.driver_data;
+
+ DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+
+ ps3fb_flip_ctl(0, &ps3fb); /* flip off */
ps3fb.dinfo->irq.mask = 0;
- free_irq(ps3fb.irq_no, ps3fb.dev);
- ps3_irq_plug_destroy(ps3fb.irq_no);
- iounmap((u8 __iomem *)ps3fb.dinfo);
-}
-void ps3fb_cleanup(void)
-{
- int status;
+ if (info) {
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(info);
+ }
+ ps3av_register_flip_ctl(NULL, NULL);
if (ps3fb.task) {
struct task_struct *task = ps3fb.task;
ps3fb.task = NULL;
kthread_stop(task);
}
if (ps3fb.irq_no) {
- free_irq(ps3fb.irq_no, ps3fb.dev);
+ free_irq(ps3fb.irq_no, dev);
ps3_irq_plug_destroy(ps3fb.irq_no);
}
iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1128,134 +1158,69 @@ void ps3fb_cleanup(void)
if (status)
DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
- ps3av_dev_close();
-}
+ ps3_close_hv_device(dev);
+ DPRINTK(" <- %s:%d\n", __func__, __LINE__);
-EXPORT_SYMBOL_GPL(ps3fb_cleanup);
-
-static int ps3fb_remove(struct platform_device *dev)
-{
- struct fb_info *info = platform_get_drvdata(dev);
-
- if (info) {
- unregister_framebuffer(info);
- fb_dealloc_cmap(&info->cmap);
- framebuffer_release(info);
- }
- ps3fb_cleanup();
return 0;
}
-static struct platform_driver ps3fb_driver = {
- .probe = ps3fb_probe,
- .remove = ps3fb_remove,
- .shutdown = ps3fb_shutdown,
- .driver = { .name = "ps3fb" }
-};
-
-static struct platform_device ps3fb_device = {
- .name = "ps3fb",
- .id = 0,
- .dev = { .release = ps3fb_platform_release }
+static struct ps3_system_bus_driver ps3fb_driver = {
+ .match_id = PS3_MATCH_ID_GRAPHICS,
+ .core.name = DEVICE_NAME,
+ .core.owner = THIS_MODULE,
+ .probe = ps3fb_probe,
+ .remove = ps3fb_shutdown,
+ .shutdown = ps3fb_shutdown,
};
-int ps3fb_set_sync(void)
+static int __init ps3fb_setup(void)
{
- int status;
+ char *options;
-#ifdef HEAD_A
- status = lv1_gpu_context_attribute(0x0,
- L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
- 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
- if (status) {
- printk(KERN_ERR
- "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
- __func__, status);
- return -1;
- }
-#endif
-#ifdef HEAD_B
- status = lv1_gpu_context_attribute(0x0,
- L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
- 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
-
- if (status) {
- printk(KERN_ERR
- "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
- __func__, status);
- return -1;
- }
-#endif
+#ifdef MODULE
return 0;
-}
-
-EXPORT_SYMBOL_GPL(ps3fb_set_sync);
-
-static int __init ps3fb_init(void)
-{
- int error;
-#ifndef MODULE
- int mode;
- char *option = NULL;
-
- if (fb_get_options("ps3fb", &option))
- goto err;
#endif
- if (!ps3fb_videomemory.address)
- goto err;
-
- error = ps3av_dev_open();
- if (error) {
- printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
- goto err;
- }
+ if (fb_get_options(DEVICE_NAME, &options))
+ return -ENXIO;
- ps3fb_mode = ps3av_get_mode();
- DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
-#ifndef MODULE
- mode = ps3fb_setup(option); /* check boot option */
- if (mode)
- ps3fb_mode = mode;
-#endif
- if (ps3fb_mode > 0) {
- u32 xres, yres;
- ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
- ps3fb.res_index = ps3fb_get_res_table(xres, yres);
- DPRINTK("res_index:%d\n", ps3fb.res_index);
- } else
- ps3fb.res_index = GPU_RES_INDEX;
+ if (!options || !*options)
+ return 0;
- atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
- atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
- init_waitqueue_head(&ps3fb.wait_vsync);
- ps3fb.num_frames = 1;
+ while (1) {
+ char *this_opt = strsep(&options, ",");
- error = platform_driver_register(&ps3fb_driver);
- if (!error) {
- error = platform_device_register(&ps3fb_device);
- if (error)
- platform_driver_unregister(&ps3fb_driver);
+ if (!this_opt)
+ break;
+ if (!*this_opt)
+ continue;
+ if (!strncmp(this_opt, "mode:", 5))
+ ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+ else
+ mode_option = this_opt;
}
+ return 0;
+}
- ps3fb_set_sync();
-
- return error;
+static int __init ps3fb_init(void)
+{
+ if (!ps3fb_videomemory.address || ps3fb_setup())
+ return -ENXIO;
-err:
- return -ENXIO;
+ return ps3_system_bus_driver_register(&ps3fb_driver);
}
-module_init(ps3fb_init);
-
-#ifdef MODULE
static void __exit ps3fb_exit(void)
{
- platform_device_unregister(&ps3fb_device);
- platform_driver_unregister(&ps3fb_driver);
+ DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+ ps3_system_bus_driver_unregister(&ps3fb_driver);
+ DPRINTK(" <- %s:%d\n", __func__, __LINE__);
}
+module_init(ps3fb_init);
module_exit(ps3fb_exit);
MODULE_LICENSE("GPL");
-#endif /* MODULE */
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index df2909ae704c..0f88c30f94f8 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -115,11 +115,11 @@ enum { VO_PAL, VO_NTSC, VO_VGA };
enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
struct pvr2_params { unsigned int val; char *name; };
-static struct pvr2_params cables[] __initdata = {
+static struct pvr2_params cables[] __devinitdata = {
{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
};
-static struct pvr2_params outputs[] __initdata = {
+static struct pvr2_params outputs[] __devinitdata = {
{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
};
@@ -147,16 +147,16 @@ static struct pvr2fb_par {
static struct fb_info *fb_info;
-static struct fb_fix_screeninfo pvr2_fix __initdata = {
+static struct fb_fix_screeninfo pvr2_fix __devinitdata = {
.id = "NEC PowerVR2",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
.ypanstep = 1,
.ywrapstep = 1,
- .accel = FB_ACCEL_NONE,
+ .accel = FB_ACCEL_NONE,
};
-static struct fb_var_screeninfo pvr2_var __initdata = {
+static struct fb_var_screeninfo pvr2_var __devinitdata = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
@@ -195,10 +195,6 @@ static unsigned int shdma = PVR2_CASCADE_CHAN;
static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
#endif
-/* Interface used by the world */
-
-int pvr2fb_setup(char*);
-
static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info);
static int pvr2fb_blank(int blank, struct fb_info *info);
@@ -227,12 +223,12 @@ static struct fb_ops pvr2fb_ops = {
#ifdef CONFIG_SH_DMA
.fb_write = pvr2fb_write,
#endif
- .fb_fillrect = cfb_fillrect,
+ .fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
-static struct fb_videomode pvr2_modedb[] __initdata = {
+static struct fb_videomode pvr2_modedb[] __devinitdata = {
/*
* Broadcast video modes (PAL and NTSC). I'm unfamiliar with
* PAL-M and PAL-N, but from what I've read both modes parallel PAL and
@@ -252,7 +248,7 @@ static struct fb_videomode pvr2_modedb[] __initdata = {
/* 640x480 @ 60hz (VGA) */
"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
0, FB_VMODE_YWRAP
- },
+ },
};
#define NUM_TOTAL_MODES ARRAY_SIZE(pvr2_modedb)
@@ -262,7 +258,7 @@ static struct fb_videomode pvr2_modedb[] __initdata = {
#define DEFMODE_VGA 2
static int defmode = DEFMODE_NTSC;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
static inline void pvr2fb_set_pal_type(unsigned int type)
{
@@ -293,7 +289,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
{
switch (var->bits_per_pixel) {
case 16: /* RGB 565 */
- pvr2fb_set_pal_type(PAL_RGB565);
+ pvr2fb_set_pal_type(PAL_RGB565);
var->red.offset = 11; var->red.length = 5;
var->green.offset = 5; var->green.length = 6;
var->blue.offset = 0; var->blue.length = 5;
@@ -306,7 +302,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
var->transp.offset = 0; var->transp.length = 0;
break;
case 32: /* ARGB 8888 */
- pvr2fb_set_pal_type(PAL_ARGB8888);
+ pvr2fb_set_pal_type(PAL_ARGB8888);
var->red.offset = 16; var->red.length = 8;
var->green.offset = 8; var->green.length = 8;
var->blue.offset = 0; var->blue.length = 8;
@@ -337,24 +333,25 @@ static int pvr2fb_setcolreg(unsigned int regno, unsigned int red,
((blue & 0xf800) >> 11);
pvr2fb_set_pal_entry(par, regno, tmp);
- ((u16*)(info->pseudo_palette))[regno] = tmp;
break;
case 24: /* RGB 888 */
red >>= 8; green >>= 8; blue >>= 8;
- ((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
+ tmp = (red << 16) | (green << 8) | blue;
break;
case 32: /* ARGB 8888 */
red >>= 8; green >>= 8; blue >>= 8;
tmp = (transp << 24) | (red << 16) | (green << 8) | blue;
pvr2fb_set_pal_entry(par, regno, tmp);
- ((u32*)(info->pseudo_palette))[regno] = tmp;
break;
default:
pr_debug("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
return 1;
}
+ if (regno < 16)
+ ((u32*)(info->pseudo_palette))[regno] = tmp;
+
return 0;
}
@@ -379,13 +376,13 @@ static int pvr2fb_set_par(struct fb_info *info)
var->vmode &= FB_VMODE_MASK;
if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
par->is_interlaced = 1;
- /*
+ /*
* XXX: Need to be more creative with this (i.e. allow doublecan for
* PAL/NTSC output).
*/
if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
par->is_doublescan = 1;
-
+
par->hsync_total = var->left_margin + var->xres + var->right_margin +
var->hsync_len;
par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
@@ -408,7 +405,7 @@ static int pvr2fb_set_par(struct fb_info *info)
} else {
/* VGA mode */
/* XXX: What else needs to be checked? */
- /*
+ /*
* XXX: We have a little freedom in VGA modes, what ranges
* should be here (i.e. hsync/vsync totals, etc.)?
*/
@@ -419,8 +416,8 @@ static int pvr2fb_set_par(struct fb_info *info)
/* Calculate the remainding offsets */
par->diwstart_h = par->borderstart_h + var->left_margin;
par->diwstart_v = par->borderstart_v + var->upper_margin;
- par->borderstop_h = par->diwstart_h + var->xres +
- var->right_margin;
+ par->borderstop_h = par->diwstart_h + var->xres +
+ var->right_margin;
par->borderstop_v = par->diwstart_v + var->yres +
var->lower_margin;
@@ -465,12 +462,12 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
set_color_bitfields(var);
if (var->vmode & FB_VMODE_YWRAP) {
- if (var->xoffset || var->yoffset < 0 ||
+ if (var->xoffset || var->yoffset < 0 ||
var->yoffset >= var->yres_virtual) {
var->xoffset = var->yoffset = 0;
} else {
if (var->xoffset > var->xres_virtual - var->xres ||
- var->yoffset > var->yres_virtual - var->yres ||
+ var->yoffset > var->yres_virtual - var->yres ||
var->xoffset < 0 || var->yoffset < 0)
var->xoffset = var->yoffset = 0;
}
@@ -478,7 +475,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->xoffset = var->yoffset = 0;
}
- /*
+ /*
* XXX: Need to be more creative with this (i.e. allow doublecan for
* PAL/NTSC output).
*/
@@ -507,7 +504,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->vsync_len = par->borderstop_v +
(par->vsync_total - par->borderstop_v);
}
-
+
hsync_total = var->left_margin + var->xres + var->right_margin +
var->hsync_len;
vtotal = var->upper_margin + var->yres + var->lower_margin +
@@ -531,7 +528,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
}
}
-
+
/* Check memory sizes */
line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
if (line_length * var->yres_virtual > info->fix.smem_len)
@@ -552,7 +549,7 @@ static void pvr2_update_display(struct fb_info *info)
DISP_DIWADDRS);
}
-/*
+/*
* Initialize the video mode. Currently, the 16bpp and 24bpp modes aren't
* very stable. It's probably due to the fact that a lot of the 2D video
* registers are still undocumented.
@@ -592,18 +589,18 @@ static void pvr2_init_display(struct fb_info *info)
/* display window start position */
fb_writel(par->diwstart_h, DISP_DIWHSTRT);
fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
-
+
/* misc. settings */
fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
/* clock doubler (for VGA), scan doubler, display enable */
- fb_writel(((video_output == VO_VGA) << 23) |
+ fb_writel(((video_output == VO_VGA) << 23) |
(par->is_doublescan << 1) | 1, DISP_DIWMODE);
/* bits per pixel */
fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
- /* video enable, color sync, interlace,
+ /* video enable, color sync, interlace,
* hsync and vsync polarity (currently unused) */
fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
}
@@ -657,7 +654,7 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id)
static int pvr2_init_cable(void)
{
if (cable_type < 0) {
- fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
+ fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
PCTRA);
cable_type = (fb_readw(PDTRA) >> 8) & 3;
}
@@ -687,7 +684,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
if (!pages)
return -ENOMEM;
-
+
down_read(&current->mm->mmap_sem);
ret = get_user_pages(current, current->mm, (unsigned long)buf,
nr_pages, WRITE, 0, pages, NULL);
@@ -700,7 +697,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
}
dma_configure_channel(shdma, 0x12c1);
-
+
dst = (unsigned long)fb_info->screen_base + *ppos;
start = (unsigned long)page_address(pages[0]);
end = (unsigned long)page_address(pages[nr_pages]);
@@ -744,7 +741,7 @@ out_unmap:
kfree(pages);
return ret;
-}
+}
#endif /* CONFIG_SH_DMA */
/**
@@ -765,21 +762,21 @@ out_unmap:
* in for flexibility anyways. Who knows, maybe someone has tv-out on a
* PCI-based version of these things ;-)
*/
-static int __init pvr2fb_common_init(void)
+static int __devinit pvr2fb_common_init(void)
{
struct pvr2fb_par *par = currentpar;
unsigned long modememused, rev;
fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
pvr2_fix.smem_len);
-
+
if (!fb_info->screen_base) {
printk(KERN_ERR "pvr2fb: Failed to remap smem space\n");
goto out_err;
}
par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start,
- pvr2_fix.mmio_len);
+ pvr2_fix.mmio_len);
if (!par->mmio_base) {
printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n");
goto out_err;
@@ -820,7 +817,7 @@ static int __init pvr2fb_common_init(void)
printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n",
fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f,
modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10));
- printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
+ printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
fb_info->node, fb_info->var.xres, fb_info->var.yres,
fb_info->var.bits_per_pixel,
get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
@@ -878,8 +875,8 @@ static int __init pvr2fb_dc_init(void)
video_output = VO_NTSC;
}
}
-
- /*
+
+ /*
* Nothing exciting about the DC PVR2 .. only a measly 8MiB.
*/
pvr2_fix.smem_start = 0xa5000000; /* RAM starts here */
@@ -903,7 +900,7 @@ static int __init pvr2fb_dc_init(void)
return pvr2fb_common_init();
}
-static void pvr2fb_dc_exit(void)
+static void __exit pvr2fb_dc_exit(void)
{
if (fb_info->screen_base) {
iounmap(fb_info->screen_base);
@@ -987,13 +984,13 @@ static int __init pvr2fb_pci_init(void)
return pci_register_driver(&pvr2fb_pci_driver);
}
-static void pvr2fb_pci_exit(void)
+static void __exit pvr2fb_pci_exit(void)
{
pci_unregister_driver(&pvr2fb_pci_driver);
}
#endif /* CONFIG_PCI */
-static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
+static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s,
int val, int size)
{
int i;
@@ -1021,7 +1018,7 @@ static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
*/
#ifndef MODULE
-int __init pvr2fb_setup(char *options)
+static int __init pvr2fb_setup(char *options)
{
char *this_opt;
char cable_arg[80];
@@ -1061,7 +1058,7 @@ static struct pvr2_board {
int (*init)(void);
void (*exit)(void);
char name[16];
-} board_list[] = {
+} board_driver[] = {
#ifdef CONFIG_SH_DREAMCAST
{ pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },
#endif
@@ -1071,7 +1068,7 @@ static struct pvr2_board {
{ 0, },
};
-int __init pvr2fb_init(void)
+static int __init pvr2fb_init(void)
{
int i, ret = -ENODEV;
int size;
@@ -1095,8 +1092,8 @@ int __init pvr2fb_init(void)
currentpar = (struct pvr2fb_par *)(fb_info + 1);
- for (i = 0; i < ARRAY_SIZE(board_list); i++) {
- struct pvr2_board *pvr_board = board_list + i;
+ for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+ struct pvr2_board *pvr_board = board_driver + i;
if (!pvr_board->init)
continue;
@@ -1118,13 +1115,13 @@ static void __exit pvr2fb_exit(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(board_list); i++) {
- struct pvr2_board *pvr_board = board_list + i;
+ for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+ struct pvr2_board *pvr_board = board_driver + i;
if (pvr_board->exit)
pvr_board->exit();
}
-
+
#ifdef CONFIG_SH_STORE_QUEUES
sq_unmap(pvr2fb_map);
#endif
@@ -1139,4 +1136,3 @@ module_exit(pvr2fb_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 48536c3e58a4..4beac1df617b 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -95,7 +95,7 @@ static int __init q40fb_probe(struct platform_device *dev)
/* mapped in q40/config.c */
q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
- info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+ info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
if (!info)
return -ENOMEM;
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
index 70bfd78eca81..13307703a9f0 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/riva/riva_hw.c
@@ -1223,6 +1223,8 @@ static int CalcVClock
}
}
}
+
+ /* non-zero: M/N/P/clock values assigned. zero: error (not set) */
return (DeltaOld != 0xFFFFFFFF);
}
/*
@@ -1240,7 +1242,10 @@ int CalcStateExt
int dotClock
)
{
- int pixelDepth, VClk, m, n, p;
+ int pixelDepth;
+ int uninitialized_var(VClk),uninitialized_var(m),
+ uninitialized_var(n), uninitialized_var(p);
+
/*
* Save mode parameters.
*/
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index ebb6756aea08..4fb16240c04d 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -752,7 +752,7 @@ static int __init sgivwfb_probe(struct platform_device *dev)
struct fb_info *info;
char *monitor;
- info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+ info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 16, &dev->dev);
if (!info)
return -ENOMEM;
par = info->par;
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d5e2d9c27847..d53bf6945f0c 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -479,7 +479,7 @@ struct sis_video_info {
struct fb_var_screeninfo default_var;
struct fb_fix_screeninfo sisfb_fix;
- u32 pseudo_palette[17];
+ u32 pseudo_palette[16];
struct sisfb_monitor {
u16 hmin;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 93d07ef85276..e8ccace01252 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1405,12 +1405,18 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
}
break;
case 16:
+ if (regno >= 16)
+ break;
+
((u32 *)(info->pseudo_palette))[regno] =
(red & 0xf800) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
break;
case 32:
+ if (regno >= 16)
+ break;
+
red >>= 8;
green >>= 8;
blue >>= 8;
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 5c0dab628099..89facb73edfc 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1634,7 +1634,7 @@ tgafb_register(struct device *dev)
FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
info->fbops = &tgafb_ops;
info->screen_base = par->tga_fb_base;
- info->pseudo_palette = (void *)(par + 1);
+ info->pseudo_palette = par->palette;
/* This should give a reasonable default video mode. */
if (tga_bus_pci) {
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 55e8aa450bfa..c699864b6f4a 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -976,7 +976,7 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 1;
- if (bpp==8) {
+ if (bpp == 8) {
t_outb(0xFF,0x3C6);
t_outb(regno,0x3C8);
@@ -984,19 +984,21 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
t_outb(green>>10,0x3C9);
t_outb(blue>>10,0x3C9);
- } else if (bpp == 16) { /* RGB 565 */
- u32 col;
-
- col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
- ((blue & 0xF800) >> 11);
- col |= col << 16;
- ((u32 *)(info->pseudo_palette))[regno] = col;
- } else if (bpp == 32) /* ARGB 8888 */
- ((u32*)info->pseudo_palette)[regno] =
- ((transp & 0xFF00) <<16) |
- ((red & 0xFF00) << 8) |
- ((green & 0xFF00)) |
- ((blue & 0xFF00)>>8);
+ } else if (regno < 16) {
+ if (bpp == 16) { /* RGB 565 */
+ u32 col;
+
+ col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
+ ((blue & 0xF800) >> 11);
+ col |= col << 16;
+ ((u32 *)(info->pseudo_palette))[regno] = col;
+ } else if (bpp == 32) /* ARGB 8888 */
+ ((u32*)info->pseudo_palette)[regno] =
+ ((transp & 0xFF00) <<16) |
+ ((red & 0xFF00) << 8) |
+ ((green & 0xFF00)) |
+ ((blue & 0xFF00)>>8);
+ }
// debug("exit\n");
return 0;
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index 07389ba01eff..e6f7c78da68b 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -291,7 +291,7 @@ int __init tx3912fb_init(void)
fb_info.fbops = &tx3912fb_ops;
fb_info.var = tx3912fb_var;
fb_info.fix = tx3912fb_fix;
- fb_info.pseudo_palette = pseudo_palette;
+ fb_info.pseudo_palette = cfb8;
fb_info.flags = FBINFO_DEFAULT;
/* Clear the framebuffer */
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 30c0b948852b..4c3a63308df1 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -68,26 +68,26 @@ static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3,
/* CRT timing register sets */
-struct vga_regset vt8623_h_total_regs[] = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
-struct vga_regset vt8623_h_display_regs[] = {{0x01, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_h_blank_end_regs[] = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
-struct vga_regset vt8623_h_sync_start_regs[] = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
-struct vga_regset vt8623_h_sync_end_regs[] = {{0x05, 0, 4}, VGA_REGSET_END};
-
-struct vga_regset vt8623_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
-struct vga_regset vt8623_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
-struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
-struct vga_regset vt8623_v_blank_end_regs[] = {{0x16, 0, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
-struct vga_regset vt8623_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END};
-
-struct vga_regset vt8623_offset_regs[] = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
-struct vga_regset vt8623_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
-struct vga_regset vt8623_fetch_count_regs[] = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
-struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
-
-struct svga_timing_regs vt8623_timing_regs = {
+static struct vga_regset vt8623_h_total_regs[] = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_display_regs[] = {{0x01, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_blank_end_regs[] = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_start_regs[] = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_h_sync_end_regs[] = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static struct vga_regset vt8623_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_blank_end_regs[] = {{0x16, 0, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static struct vga_regset vt8623_offset_regs[] = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
+static struct vga_regset vt8623_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
+static struct vga_regset vt8623_fetch_count_regs[] = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
+static struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
+
+static struct svga_timing_regs vt8623_timing_regs = {
vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
@@ -903,7 +903,7 @@ static void __exit vt8623fb_cleanup(void)
/* Driver Initialisation */
-int __init vt8623fb_init(void)
+static int __init vt8623fb_init(void)
{
#ifndef MODULE
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index ca75b3ad3a2e..6854fd6b9714 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -1,8 +1,6 @@
-menu "Dallas's 1-wire bus"
- depends on HAS_IOMEM
-
-config W1
+menuconfig W1
tristate "Dallas's 1-wire support"
+ depends on HAS_IOMEM
---help---
Dallas' 1-wire bus is useful to connect slow 1-pin devices
such as iButtons and thermal sensors.
@@ -12,8 +10,10 @@ config W1
This W1 support can also be built as a module. If so, the module
will be called wire.ko.
+if W1
+
config W1_CON
- depends on CONNECTOR && W1
+ depends on CONNECTOR
bool "Userspace communication over connector"
default y
--- help ---
@@ -27,4 +27,4 @@ config W1_CON
source drivers/w1/masters/Kconfig
source drivers/w1/slaves/Kconfig
-endmenu
+endif # W1
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 8f779338f744..8236d447adf5 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -3,11 +3,10 @@
#
menu "1-wire Bus Masters"
- depends on W1
config W1_MASTER_MATROX
tristate "Matrox G400 transport layer for 1-wire"
- depends on W1 && PCI
+ depends on PCI
help
Say Y here if you want to communicate with your 1-wire devices
using Matrox's G400 GPIO pins.
@@ -17,7 +16,7 @@ config W1_MASTER_MATROX
config W1_MASTER_DS2490
tristate "DS2490 USB <-> W1 transport layer for 1-wire"
- depends on W1 && USB
+ depends on USB
help
Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges,
for example DS9490*.
@@ -27,7 +26,7 @@ config W1_MASTER_DS2490
config W1_MASTER_DS2482
tristate "Maxim DS2482 I2C to 1-Wire bridge"
- depends on I2C && W1 && EXPERIMENTAL
+ depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for the Maxim DS2482
I2C to 1-Wire bridge.
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index df95d6c2cefa..3df29a122f84 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -3,25 +3,21 @@
#
menu "1-wire Slaves"
- depends on W1
config W1_SLAVE_THERM
tristate "Thermal family implementation"
- depends on W1
help
Say Y here if you want to connect 1-wire thermal sensors to your
wire.
config W1_SLAVE_SMEM
tristate "Simple 64bit memory family implementation"
- depends on W1
help
Say Y here if you want to connect 1-wire
simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
config W1_SLAVE_DS2433
tristate "4kb EEPROM family support (DS2433)"
- depends on W1
help
Say Y here if you want to use a 1-wire
4kb EEPROM family device (DS2433).
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index f5c5b760ed7b..c6332108f1c5 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -805,6 +805,7 @@ static int w1_control(void *data)
struct w1_master *dev, *n;
int have_to_wait = 0;
+ set_freezable();
while (!kthread_should_stop() || have_to_wait) {
have_to_wait = 0;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 45c35986d49f..0a7068e30ecb 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -131,7 +131,9 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
switch (token) {
case Opt_debug:
v9ses->debug = option;
+#ifdef CONFIG_NET_9P_DEBUG
p9_debug_level = option;
+#endif
break;
case Opt_port:
v9ses->port = option;
diff --git a/fs/Kconfig b/fs/Kconfig
index 94b9d861bf9b..613df554728d 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -991,7 +991,7 @@ config TMPFS_POSIX_ACL
config HUGETLBFS
bool "HugeTLB file system support"
- depends on X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+ depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN
help
hugetlbfs is a filesystem backing for HugeTLB pages, based on
ramfs. For architectures that support it, say Y here and read
@@ -1675,6 +1675,7 @@ config NFSD_V3_ACL
config NFSD_V4
bool "Provide NFSv4 server support (EXPERIMENTAL)"
depends on NFSD_V3 && EXPERIMENTAL
+ select RPCSEC_GSS_KRB5
help
If you would like to include the NFSv4 server as well as the NFSv2
and NFSv3 servers, say Y here. This feature is experimental, and
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 73ce561f3ea0..a66671082cfb 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -8,6 +8,7 @@ kafs-objs := \
cmservice.o \
dir.o \
file.o \
+ flock.o \
fsclient.o \
inode.o \
main.o \
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index 245257948140..c548aa346f0d 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -37,6 +37,13 @@ typedef enum {
AFS_FTYPE_SYMLINK = 3,
} afs_file_type_t;
+typedef enum {
+ AFS_LOCK_READ = 0, /* read lock request */
+ AFS_LOCK_WRITE = 1, /* write lock request */
+} afs_lock_type_t;
+
+#define AFS_LOCKWAIT (5 * 60) /* time until a lock times out (seconds) */
+
/*
* AFS file identifier
*/
@@ -120,6 +127,7 @@ struct afs_file_status {
struct afs_fid parent; /* parent dir ID for non-dirs only */
time_t mtime_client; /* last time client changed data */
time_t mtime_server; /* last time server changed data */
+ s32 lock_count; /* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */
};
/*
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h
index a18c374ebe08..eb647323d8f0 100644
--- a/fs/afs/afs_fs.h
+++ b/fs/afs/afs_fs.h
@@ -31,6 +31,9 @@ enum AFS_FS_Operations {
FSGETVOLUMEINFO = 148, /* AFS Get information about a volume */
FSGETVOLUMESTATUS = 149, /* AFS Get volume status information */
FSGETROOTVOLUME = 151, /* AFS Get root volume name */
+ FSSETLOCK = 156, /* AFS Request a file lock */
+ FSEXTENDLOCK = 157, /* AFS Extend a file lock */
+ FSRELEASELOCK = 158, /* AFS Release a file lock */
FSLOOKUP = 161, /* AFS lookup file in directory */
FSFETCHDATA64 = 65537, /* AFS Fetch file data */
FSSTOREDATA64 = 65538, /* AFS Store file data */
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index bacf518c6fa8..b8243945818d 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -125,6 +125,9 @@ static void afs_break_callback(struct afs_server *server,
spin_unlock(&server->cb_lock);
queue_work(afs_callback_update_worker, &vnode->cb_broken_work);
+ if (list_empty(&vnode->granted_locks) &&
+ !list_empty(&vnode->pending_locks))
+ afs_lock_may_be_available(vnode);
spin_unlock(&vnode->lock);
}
}
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 546c59522eb1..33fe39ad4e03 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -44,6 +44,7 @@ const struct file_operations afs_dir_file_operations = {
.open = afs_dir_open,
.release = afs_release,
.readdir = afs_readdir,
+ .lock = afs_lock,
};
const struct inode_operations afs_dir_inode_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index aede7eb66dd4..525f7c56e068 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -34,6 +34,8 @@ const struct file_operations afs_file_operations = {
.mmap = generic_file_readonly_mmap,
.splice_read = generic_file_splice_read,
.fsync = afs_fsync,
+ .lock = afs_lock,
+ .flock = afs_flock,
};
const struct inode_operations afs_file_inode_operations = {
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
new file mode 100644
index 000000000000..8f07f8d1bfa9
--- /dev/null
+++ b/fs/afs/flock.c
@@ -0,0 +1,558 @@
+/* AFS file locking support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/smp_lock.h>
+#include "internal.h"
+
+#define AFS_LOCK_GRANTED 0
+#define AFS_LOCK_PENDING 1
+
+static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl);
+static void afs_fl_release_private(struct file_lock *fl);
+
+static struct workqueue_struct *afs_lock_manager;
+
+static struct file_lock_operations afs_lock_ops = {
+ .fl_copy_lock = afs_fl_copy_lock,
+ .fl_release_private = afs_fl_release_private,
+};
+
+/*
+ * initialise the lock manager thread if it isn't already running
+ */
+static int afs_init_lock_manager(void)
+{
+ if (!afs_lock_manager) {
+ afs_lock_manager = create_singlethread_workqueue("kafs_lockd");
+ if (!afs_lock_manager)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*
+ * destroy the lock manager thread if it's running
+ */
+void __exit afs_kill_lock_manager(void)
+{
+ if (afs_lock_manager)
+ destroy_workqueue(afs_lock_manager);
+}
+
+/*
+ * if the callback is broken on this vnode, then the lock may now be available
+ */
+void afs_lock_may_be_available(struct afs_vnode *vnode)
+{
+ _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+ queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0);
+}
+
+/*
+ * the lock will time out in 5 minutes unless we extend it, so schedule
+ * extension in a bit less than that time
+ */
+static void afs_schedule_lock_extension(struct afs_vnode *vnode)
+{
+ queue_delayed_work(afs_lock_manager, &vnode->lock_work,
+ AFS_LOCKWAIT * HZ / 2);
+}
+
+/*
+ * do work for a lock, including:
+ * - probing for a lock we're waiting on but didn't get immediately
+ * - extending a lock that's close to timing out
+ */
+void afs_lock_work(struct work_struct *work)
+{
+ struct afs_vnode *vnode =
+ container_of(work, struct afs_vnode, lock_work.work);
+ struct file_lock *fl;
+ afs_lock_type_t type;
+ struct key *key;
+ int ret;
+
+ _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+ spin_lock(&vnode->lock);
+
+ if (test_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) {
+ _debug("unlock");
+ spin_unlock(&vnode->lock);
+
+ /* attempt to release the server lock; if it fails, we just
+ * wait 5 minutes and it'll time out anyway */
+ ret = afs_vnode_release_lock(vnode, vnode->unlock_key);
+ if (ret < 0)
+ printk(KERN_WARNING "AFS:"
+ " Failed to release lock on {%x:%x} error %d\n",
+ vnode->fid.vid, vnode->fid.vnode, ret);
+
+ spin_lock(&vnode->lock);
+ key_put(vnode->unlock_key);
+ vnode->unlock_key = NULL;
+ clear_bit(AFS_VNODE_UNLOCKING, &vnode->flags);
+ }
+
+ /* if we've got a lock, then it must be time to extend that lock as AFS
+ * locks time out after 5 minutes */
+ if (!list_empty(&vnode->granted_locks)) {
+ _debug("extend");
+
+ if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
+ BUG();
+ fl = list_entry(vnode->granted_locks.next,
+ struct file_lock, fl_u.afs.link);
+ key = key_get(fl->fl_file->private_data);
+ spin_unlock(&vnode->lock);
+
+ ret = afs_vnode_extend_lock(vnode, key);
+ clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+ key_put(key);
+ switch (ret) {
+ case 0:
+ afs_schedule_lock_extension(vnode);
+ break;
+ default:
+ /* ummm... we failed to extend the lock - retry
+ * extension shortly */
+ printk(KERN_WARNING "AFS:"
+ " Failed to extend lock on {%x:%x} error %d\n",
+ vnode->fid.vid, vnode->fid.vnode, ret);
+ queue_delayed_work(afs_lock_manager, &vnode->lock_work,
+ HZ * 10);
+ break;
+ }
+ _leave(" [extend]");
+ return;
+ }
+
+ /* if we don't have a granted lock, then we must've been called back by
+ * the server, and so if might be possible to get a lock we're
+ * currently waiting for */
+ if (!list_empty(&vnode->pending_locks)) {
+ _debug("get");
+
+ if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags))
+ BUG();
+ fl = list_entry(vnode->pending_locks.next,
+ struct file_lock, fl_u.afs.link);
+ key = key_get(fl->fl_file->private_data);
+ type = (fl->fl_type == F_RDLCK) ?
+ AFS_LOCK_READ : AFS_LOCK_WRITE;
+ spin_unlock(&vnode->lock);
+
+ ret = afs_vnode_set_lock(vnode, key, type);
+ clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+ switch (ret) {
+ case -EWOULDBLOCK:
+ _debug("blocked");
+ break;
+ case 0:
+ _debug("acquired");
+ if (type == AFS_LOCK_READ)
+ set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+ else
+ set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+ ret = AFS_LOCK_GRANTED;
+ default:
+ spin_lock(&vnode->lock);
+ /* the pending lock may have been withdrawn due to a
+ * signal */
+ if (list_entry(vnode->pending_locks.next,
+ struct file_lock, fl_u.afs.link) == fl) {
+ fl->fl_u.afs.state = ret;
+ if (ret == AFS_LOCK_GRANTED)
+ list_move_tail(&fl->fl_u.afs.link,
+ &vnode->granted_locks);
+ else
+ list_del_init(&fl->fl_u.afs.link);
+ wake_up(&fl->fl_wait);
+ spin_unlock(&vnode->lock);
+ } else {
+ _debug("withdrawn");
+ clear_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+ clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+ spin_unlock(&vnode->lock);
+ afs_vnode_release_lock(vnode, key);
+ if (!list_empty(&vnode->pending_locks))
+ afs_lock_may_be_available(vnode);
+ }
+ break;
+ }
+ key_put(key);
+ _leave(" [pend]");
+ return;
+ }
+
+ /* looks like the lock request was withdrawn on a signal */
+ spin_unlock(&vnode->lock);
+ _leave(" [no locks]");
+}
+
+/*
+ * pass responsibility for the unlocking of a vnode on the server to the
+ * manager thread, lest a pending signal in the calling thread interrupt
+ * AF_RXRPC
+ * - the caller must hold the vnode lock
+ */
+static void afs_defer_unlock(struct afs_vnode *vnode, struct key *key)
+{
+ cancel_delayed_work(&vnode->lock_work);
+ if (!test_and_clear_bit(AFS_VNODE_READLOCKED, &vnode->flags) &&
+ !test_and_clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags))
+ BUG();
+ if (test_and_set_bit(AFS_VNODE_UNLOCKING, &vnode->flags))
+ BUG();
+ vnode->unlock_key = key_get(key);
+ afs_lock_may_be_available(vnode);
+}
+
+/*
+ * request a lock on a file on the server
+ */
+static int afs_do_setlk(struct file *file, struct file_lock *fl)
+{
+ struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+ afs_lock_type_t type;
+ struct key *key = file->private_data;
+ int ret;
+
+ _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
+
+ /* only whole-file locks are supported */
+ if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
+ return -EINVAL;
+
+ ret = afs_init_lock_manager();
+ if (ret < 0)
+ return ret;
+
+ fl->fl_ops = &afs_lock_ops;
+ INIT_LIST_HEAD(&fl->fl_u.afs.link);
+ fl->fl_u.afs.state = AFS_LOCK_PENDING;
+
+ type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
+
+ lock_kernel();
+
+ /* make sure we've got a callback on this file and that our view of the
+ * data version is up to date */
+ ret = afs_vnode_fetch_status(vnode, NULL, key);
+ if (ret < 0)
+ goto error;
+
+ if (vnode->status.lock_count != 0 && !(fl->fl_flags & FL_SLEEP)) {
+ ret = -EAGAIN;
+ goto error;
+ }
+
+ spin_lock(&vnode->lock);
+
+ if (list_empty(&vnode->pending_locks)) {
+ /* if there's no-one else with a lock on this vnode, then we
+ * need to ask the server for a lock */
+ if (list_empty(&vnode->granted_locks)) {
+ _debug("not locked");
+ ASSERTCMP(vnode->flags &
+ ((1 << AFS_VNODE_LOCKING) |
+ (1 << AFS_VNODE_READLOCKED) |
+ (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+ list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+ set_bit(AFS_VNODE_LOCKING, &vnode->flags);
+ spin_unlock(&vnode->lock);
+
+ ret = afs_vnode_set_lock(vnode, key, type);
+ clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+ switch (ret) {
+ case 0:
+ goto acquired_server_lock;
+ case -EWOULDBLOCK:
+ spin_lock(&vnode->lock);
+ ASSERT(list_empty(&vnode->granted_locks));
+ ASSERTCMP(vnode->pending_locks.next, ==,
+ &fl->fl_u.afs.link);
+ goto wait;
+ default:
+ spin_lock(&vnode->lock);
+ list_del_init(&fl->fl_u.afs.link);
+ spin_unlock(&vnode->lock);
+ goto error;
+ }
+ }
+
+ /* if we've already got a readlock on the server and no waiting
+ * writelocks, then we might be able to instantly grant another
+ * readlock */
+ if (type == AFS_LOCK_READ &&
+ vnode->flags & (1 << AFS_VNODE_READLOCKED)) {
+ _debug("instant readlock");
+ ASSERTCMP(vnode->flags &
+ ((1 << AFS_VNODE_LOCKING) |
+ (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+ ASSERT(!list_empty(&vnode->granted_locks));
+ goto sharing_existing_lock;
+ }
+ }
+
+ /* otherwise, we need to wait for a local lock to become available */
+ _debug("wait local");
+ list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+wait:
+ if (!(fl->fl_flags & FL_SLEEP)) {
+ _debug("noblock");
+ ret = -EAGAIN;
+ goto abort_attempt;
+ }
+ spin_unlock(&vnode->lock);
+
+ /* now we need to sleep and wait for the lock manager thread to get the
+ * lock from the server */
+ _debug("sleep");
+ ret = wait_event_interruptible(fl->fl_wait,
+ fl->fl_u.afs.state <= AFS_LOCK_GRANTED);
+ if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
+ ret = fl->fl_u.afs.state;
+ if (ret < 0)
+ goto error;
+ spin_lock(&vnode->lock);
+ goto given_lock;
+ }
+
+ /* we were interrupted, but someone may still be in the throes of
+ * giving us the lock */
+ _debug("intr");
+ ASSERTCMP(ret, ==, -ERESTARTSYS);
+
+ spin_lock(&vnode->lock);
+ if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) {
+ ret = fl->fl_u.afs.state;
+ if (ret < 0) {
+ spin_unlock(&vnode->lock);
+ goto error;
+ }
+ goto given_lock;
+ }
+
+abort_attempt:
+ /* we aren't going to get the lock, either because we're unwilling to
+ * wait, or because some signal happened */
+ _debug("abort");
+ if (list_empty(&vnode->granted_locks) &&
+ vnode->pending_locks.next == &fl->fl_u.afs.link) {
+ if (vnode->pending_locks.prev != &fl->fl_u.afs.link) {
+ /* kick the next pending lock into having a go */
+ list_del_init(&fl->fl_u.afs.link);
+ afs_lock_may_be_available(vnode);
+ }
+ } else {
+ list_del_init(&fl->fl_u.afs.link);
+ }
+ spin_unlock(&vnode->lock);
+ goto error;
+
+acquired_server_lock:
+ /* we've acquired a server lock, but it needs to be renewed after 5
+ * mins */
+ spin_lock(&vnode->lock);
+ afs_schedule_lock_extension(vnode);
+ if (type == AFS_LOCK_READ)
+ set_bit(AFS_VNODE_READLOCKED, &vnode->flags);
+ else
+ set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags);
+sharing_existing_lock:
+ /* the lock has been granted as far as we're concerned... */
+ fl->fl_u.afs.state = AFS_LOCK_GRANTED;
+ list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks);
+given_lock:
+ /* ... but we do still need to get the VFS's blessing */
+ ASSERT(!(vnode->flags & (1 << AFS_VNODE_LOCKING)));
+ ASSERT((vnode->flags & ((1 << AFS_VNODE_READLOCKED) |
+ (1 << AFS_VNODE_WRITELOCKED))) != 0);
+ ret = posix_lock_file(file, fl, NULL);
+ if (ret < 0)
+ goto vfs_rejected_lock;
+ spin_unlock(&vnode->lock);
+
+ /* again, make sure we've got a callback on this file and, again, make
+ * sure that our view of the data version is up to date (we ignore
+ * errors incurred here and deal with the consequences elsewhere) */
+ afs_vnode_fetch_status(vnode, NULL, key);
+
+error:
+ unlock_kernel();
+ _leave(" = %d", ret);
+ return ret;
+
+vfs_rejected_lock:
+ /* the VFS rejected the lock we just obtained, so we have to discard
+ * what we just got */
+ _debug("vfs refused %d", ret);
+ list_del_init(&fl->fl_u.afs.link);
+ if (list_empty(&vnode->granted_locks))
+ afs_defer_unlock(vnode, key);
+ spin_unlock(&vnode->lock);
+ goto abort_attempt;
+}
+
+/*
+ * unlock on a file on the server
+ */
+static int afs_do_unlk(struct file *file, struct file_lock *fl)
+{
+ struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+ struct key *key = file->private_data;
+ int ret;
+
+ _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type);
+
+ /* only whole-file unlocks are supported */
+ if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX)
+ return -EINVAL;
+
+ fl->fl_ops = &afs_lock_ops;
+ INIT_LIST_HEAD(&fl->fl_u.afs.link);
+ fl->fl_u.afs.state = AFS_LOCK_PENDING;
+
+ spin_lock(&vnode->lock);
+ ret = posix_lock_file(file, fl, NULL);
+ if (ret < 0) {
+ spin_unlock(&vnode->lock);
+ _leave(" = %d [vfs]", ret);
+ return ret;
+ }
+
+ /* discard the server lock only if all granted locks are gone */
+ if (list_empty(&vnode->granted_locks))
+ afs_defer_unlock(vnode, key);
+ spin_unlock(&vnode->lock);
+ _leave(" = 0");
+ return 0;
+}
+
+/*
+ * return information about a lock we currently hold, if indeed we hold one
+ */
+static int afs_do_getlk(struct file *file, struct file_lock *fl)
+{
+ struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host);
+ struct key *key = file->private_data;
+ int ret, lock_count;
+
+ _enter("");
+
+ fl->fl_type = F_UNLCK;
+
+ mutex_lock(&vnode->vfs_inode.i_mutex);
+
+ /* check local lock records first */
+ ret = 0;
+ if (posix_test_lock(file, fl) == 0) {
+ /* no local locks; consult the server */
+ ret = afs_vnode_fetch_status(vnode, NULL, key);
+ if (ret < 0)
+ goto error;
+ lock_count = vnode->status.lock_count;
+ if (lock_count) {
+ if (lock_count > 0)
+ fl->fl_type = F_RDLCK;
+ else
+ fl->fl_type = F_WRLCK;
+ fl->fl_start = 0;
+ fl->fl_end = OFFSET_MAX;
+ }
+ }
+
+error:
+ mutex_unlock(&vnode->vfs_inode.i_mutex);
+ _leave(" = %d [%hd]", ret, fl->fl_type);
+ return ret;
+}
+
+/*
+ * manage POSIX locks on a file
+ */
+int afs_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+ struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+
+ _enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}",
+ vnode->fid.vid, vnode->fid.vnode, cmd,
+ fl->fl_type, fl->fl_flags,
+ (long long) fl->fl_start, (long long) fl->fl_end);
+
+ /* AFS doesn't support mandatory locks */
+ if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
+ fl->fl_type != F_UNLCK)
+ return -ENOLCK;
+
+ if (IS_GETLK(cmd))
+ return afs_do_getlk(file, fl);
+ if (fl->fl_type == F_UNLCK)
+ return afs_do_unlk(file, fl);
+ return afs_do_setlk(file, fl);
+}
+
+/*
+ * manage FLOCK locks on a file
+ */
+int afs_flock(struct file *file, int cmd, struct file_lock *fl)
+{
+ struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+
+ _enter("{%x:%u},%d,{t=%x,fl=%x}",
+ vnode->fid.vid, vnode->fid.vnode, cmd,
+ fl->fl_type, fl->fl_flags);
+
+ /*
+ * No BSD flocks over NFS allowed.
+ * Note: we could try to fake a POSIX lock request here by
+ * using ((u32) filp | 0x80000000) or some such as the pid.
+ * Not sure whether that would be unique, though, or whether
+ * that would break in other places.
+ */
+ if (!(fl->fl_flags & FL_FLOCK))
+ return -ENOLCK;
+
+ /* we're simulating flock() locks using posix locks on the server */
+ fl->fl_owner = (fl_owner_t) file;
+ fl->fl_start = 0;
+ fl->fl_end = OFFSET_MAX;
+
+ if (fl->fl_type == F_UNLCK)
+ return afs_do_unlk(file, fl);
+ return afs_do_setlk(file, fl);
+}
+
+/*
+ * the POSIX lock management core VFS code copies the lock record and adds the
+ * copy into its own list, so we need to add that copy to the vnode's lock
+ * queue in the same place as the original (which will be deleted shortly
+ * after)
+ */
+static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl)
+{
+ _enter("");
+
+ list_add(&new->fl_u.afs.link, &fl->fl_u.afs.link);
+}
+
+/*
+ * need to remove this lock from the vnode queue when it's removed from the
+ * VFS's list
+ */
+static void afs_fl_release_private(struct file_lock *fl)
+{
+ _enter("");
+
+ list_del_init(&fl->fl_u.afs.link);
+}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 5dff1308b6f0..023b95b0d9d7 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -67,7 +67,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
EXTRACT(status->group);
bp++; /* sync counter */
data_version |= (u64) ntohl(*bp++) << 32;
- bp++; /* lock count */
+ EXTRACT(status->lock_count);
size |= (u64) ntohl(*bp++) << 32;
bp++; /* spare 4 */
*_bp = bp;
@@ -1748,3 +1748,156 @@ int afs_fs_get_volume_status(struct afs_server *server,
return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
}
+
+/*
+ * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
+ */
+static int afs_deliver_fs_xxxx_lock(struct afs_call *call,
+ struct sk_buff *skb, bool last)
+{
+ const __be32 *bp;
+
+ _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
+ afs_transfer_reply(call, skb);
+ if (!last)
+ return 0;
+
+ if (call->reply_size != call->reply_max)
+ return -EBADMSG;
+
+ /* unmarshall the reply once we've received all of it */
+ bp = call->buffer;
+ /* xdr_decode_AFSVolSync(&bp, call->replyX); */
+
+ _leave(" = 0 [done]");
+ return 0;
+}
+
+/*
+ * FS.SetLock operation type
+ */
+static const struct afs_call_type afs_RXFSSetLock = {
+ .name = "FS.SetLock",
+ .deliver = afs_deliver_fs_xxxx_lock,
+ .abort_to_error = afs_abort_to_error,
+ .destructor = afs_flat_call_destructor,
+};
+
+/*
+ * FS.ExtendLock operation type
+ */
+static const struct afs_call_type afs_RXFSExtendLock = {
+ .name = "FS.ExtendLock",
+ .deliver = afs_deliver_fs_xxxx_lock,
+ .abort_to_error = afs_abort_to_error,
+ .destructor = afs_flat_call_destructor,
+};
+
+/*
+ * FS.ReleaseLock operation type
+ */
+static const struct afs_call_type afs_RXFSReleaseLock = {
+ .name = "FS.ReleaseLock",
+ .deliver = afs_deliver_fs_xxxx_lock,
+ .abort_to_error = afs_abort_to_error,
+ .destructor = afs_flat_call_destructor,
+};
+
+/*
+ * get a lock on a file
+ */
+int afs_fs_set_lock(struct afs_server *server,
+ struct key *key,
+ struct afs_vnode *vnode,
+ afs_lock_type_t type,
+ const struct afs_wait_mode *wait_mode)
+{
+ struct afs_call *call;
+ __be32 *bp;
+
+ _enter("");
+
+ call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4);
+ if (!call)
+ return -ENOMEM;
+
+ call->key = key;
+ call->reply = vnode;
+ call->service_id = FS_SERVICE;
+ call->port = htons(AFS_FS_PORT);
+
+ /* marshall the parameters */
+ bp = call->request;
+ *bp++ = htonl(FSSETLOCK);
+ *bp++ = htonl(vnode->fid.vid);
+ *bp++ = htonl(vnode->fid.vnode);
+ *bp++ = htonl(vnode->fid.unique);
+ *bp++ = htonl(type);
+
+ return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * extend a lock on a file
+ */
+int afs_fs_extend_lock(struct afs_server *server,
+ struct key *key,
+ struct afs_vnode *vnode,
+ const struct afs_wait_mode *wait_mode)
+{
+ struct afs_call *call;
+ __be32 *bp;
+
+ _enter("");
+
+ call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4);
+ if (!call)
+ return -ENOMEM;
+
+ call->key = key;
+ call->reply = vnode;
+ call->service_id = FS_SERVICE;
+ call->port = htons(AFS_FS_PORT);
+
+ /* marshall the parameters */
+ bp = call->request;
+ *bp++ = htonl(FSEXTENDLOCK);
+ *bp++ = htonl(vnode->fid.vid);
+ *bp++ = htonl(vnode->fid.vnode);
+ *bp++ = htonl(vnode->fid.unique);
+
+ return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
+/*
+ * release a lock on a file
+ */
+int afs_fs_release_lock(struct afs_server *server,
+ struct key *key,
+ struct afs_vnode *vnode,
+ const struct afs_wait_mode *wait_mode)
+{
+ struct afs_call *call;
+ __be32 *bp;
+
+ _enter("");
+
+ call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4);
+ if (!call)
+ return -ENOMEM;
+
+ call->key = key;
+ call->reply = vnode;
+ call->service_id = FS_SERVICE;
+ call->port = htons(AFS_FS_PORT);
+
+ /* marshall the parameters */
+ bp = call->request;
+ *bp++ = htonl(FSRELEASELOCK);
+ *bp++ = htonl(vnode->fid.vid);
+ *bp++ = htonl(vnode->fid.vnode);
+ *bp++ = htonl(vnode->fid.unique);
+
+ return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 2c55dd94a1de..6306438f331f 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -351,10 +351,18 @@ struct afs_vnode {
#define AFS_VNODE_ZAP_DATA 3 /* set if vnode's data should be invalidated */
#define AFS_VNODE_DELETED 4 /* set if vnode deleted on server */
#define AFS_VNODE_MOUNTPOINT 5 /* set if vnode is a mountpoint symlink */
+#define AFS_VNODE_LOCKING 6 /* set if waiting for lock on vnode */
+#define AFS_VNODE_READLOCKED 7 /* set if vnode is read-locked on the server */
+#define AFS_VNODE_WRITELOCKED 8 /* set if vnode is write-locked on the server */
+#define AFS_VNODE_UNLOCKING 9 /* set if vnode is being unlocked on the server */
long acl_order; /* ACL check count (callback break count) */
struct list_head writebacks; /* alterations in pagecache that need writing */
+ struct list_head pending_locks; /* locks waiting to be granted */
+ struct list_head granted_locks; /* locks granted on this file */
+ struct delayed_work lock_work; /* work to be done in locking */
+ struct key *unlock_key; /* key to be used in unlocking */
/* outstanding callback notification on this file */
struct rb_node server_rb; /* link in server->fs_vnodes */
@@ -474,6 +482,15 @@ extern int afs_open(struct inode *, struct file *);
extern int afs_release(struct inode *, struct file *);
/*
+ * flock.c
+ */
+extern void __exit afs_kill_lock_manager(void);
+extern void afs_lock_work(struct work_struct *);
+extern void afs_lock_may_be_available(struct afs_vnode *);
+extern int afs_lock(struct file *, int, struct file_lock *);
+extern int afs_flock(struct file *, int, struct file_lock *);
+
+/*
* fsclient.c
*/
extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
@@ -513,6 +530,15 @@ extern int afs_fs_get_volume_status(struct afs_server *, struct key *,
struct afs_vnode *,
struct afs_volume_status *,
const struct afs_wait_mode *);
+extern int afs_fs_set_lock(struct afs_server *, struct key *,
+ struct afs_vnode *, afs_lock_type_t,
+ const struct afs_wait_mode *);
+extern int afs_fs_extend_lock(struct afs_server *, struct key *,
+ struct afs_vnode *,
+ const struct afs_wait_mode *);
+extern int afs_fs_release_lock(struct afs_server *, struct key *,
+ struct afs_vnode *,
+ const struct afs_wait_mode *);
/*
* inode.c
@@ -681,6 +707,10 @@ extern int afs_vnode_store_data(struct afs_writeback *, pgoff_t, pgoff_t,
extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *);
extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *,
struct afs_volume_status *);
+extern int afs_vnode_set_lock(struct afs_vnode *, struct key *,
+ afs_lock_type_t);
+extern int afs_vnode_extend_lock(struct afs_vnode *, struct key *);
+extern int afs_vnode_release_lock(struct afs_vnode *, struct key *);
/*
* volume.c
diff --git a/fs/afs/main.c b/fs/afs/main.c
index cd21195bbb24..0f60f6b35769 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -168,6 +168,7 @@ static void __exit afs_exit(void)
printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
afs_fs_exit();
+ afs_kill_lock_manager();
afs_close_socket();
afs_purge_servers();
afs_callback_update_kill();
diff --git a/fs/afs/misc.c b/fs/afs/misc.c
index d1a889c40742..2d33a5f7d218 100644
--- a/fs/afs/misc.c
+++ b/fs/afs/misc.c
@@ -35,6 +35,7 @@ int afs_abort_to_error(u32 abort_code)
case VOVERQUOTA: return -EDQUOT;
case VBUSY: return -EBUSY;
case VMOVED: return -ENXIO;
+ case 0x2f6df0a: return -EWOULDBLOCK;
case 0x2f6df0c: return -EACCES;
case 0x2f6df0f: return -EBUSY;
case 0x2f6df10: return -EEXIST;
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 13df512aea9e..6edb56683b9a 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -201,23 +201,9 @@ static int afs_proc_cells_open(struct inode *inode, struct file *file)
*/
static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
{
- struct list_head *_p;
- loff_t pos = *_pos;
-
/* lock the list against modification */
down_read(&afs_proc_cells_sem);
-
- /* allow for the header line */
- if (!pos)
- return (void *) 1;
- pos--;
-
- /* find the n'th element in the list */
- list_for_each(_p, &afs_proc_cells)
- if (!pos--)
- break;
-
- return _p != &afs_proc_cells ? _p : NULL;
+ return seq_list_start_head(&afs_proc_cells, *_pos);
}
/*
@@ -225,14 +211,7 @@ static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
*/
static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos)
{
- struct list_head *_p;
-
- (*pos)++;
-
- _p = v;
- _p = v == (void *) 1 ? afs_proc_cells.next : _p->next;
-
- return _p != &afs_proc_cells ? _p : NULL;
+ return seq_list_next(v, &afs_proc_cells, pos);
}
/*
@@ -250,7 +229,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v)
{
struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
- if (v == (void *) 1) {
+ if (v == &afs_proc_cells) {
/* display header on line 1 */
seq_puts(m, "USE NAME\n");
return 0;
@@ -503,26 +482,13 @@ static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file)
*/
static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
{
- struct list_head *_p;
struct afs_cell *cell = m->private;
- loff_t pos = *_pos;
_enter("cell=%p pos=%Ld", cell, *_pos);
/* lock the list against modification */
down_read(&cell->vl_sem);
-
- /* allow for the header line */
- if (!pos)
- return (void *) 1;
- pos--;
-
- /* find the n'th element in the list */
- list_for_each(_p, &cell->vl_list)
- if (!pos--)
- break;
-
- return _p != &cell->vl_list ? _p : NULL;
+ return seq_list_start_head(&cell->vl_list, *_pos);
}
/*
@@ -531,17 +497,10 @@ static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
loff_t *_pos)
{
- struct list_head *_p;
struct afs_cell *cell = p->private;
_enter("cell=%p pos=%Ld", cell, *_pos);
-
- (*_pos)++;
-
- _p = v;
- _p = (v == (void *) 1) ? cell->vl_list.next : _p->next;
-
- return (_p != &cell->vl_list) ? _p : NULL;
+ return seq_list_next(v, &cell->vl_list, _pos);
}
/*
@@ -569,11 +528,12 @@ const char afs_vlocation_states[][4] = {
*/
static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
{
+ struct afs_cell *cell = m->private;
struct afs_vlocation *vlocation =
list_entry(v, struct afs_vlocation, link);
/* display header on line 1 */
- if (v == (void *) 1) {
+ if (v == &cell->vl_list) {
seq_puts(m, "USE STT VLID[0] VLID[1] VLID[2] NAME\n");
return 0;
}
@@ -734,26 +694,13 @@ static int afs_proc_cell_servers_release(struct inode *inode,
static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
__acquires(m->private->servers_lock)
{
- struct list_head *_p;
struct afs_cell *cell = m->private;
- loff_t pos = *_pos;
_enter("cell=%p pos=%Ld", cell, *_pos);
/* lock the list against modification */
read_lock(&cell->servers_lock);
-
- /* allow for the header line */
- if (!pos)
- return (void *) 1;
- pos--;
-
- /* find the n'th element in the list */
- list_for_each(_p, &cell->servers)
- if (!pos--)
- break;
-
- return _p != &cell->servers ? _p : NULL;
+ return seq_list_start_head(&cell->servers, *_pos);
}
/*
@@ -762,17 +709,10 @@ static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
loff_t *_pos)
{
- struct list_head *_p;
struct afs_cell *cell = p->private;
_enter("cell=%p pos=%Ld", cell, *_pos);
-
- (*_pos)++;
-
- _p = v;
- _p = v == (void *) 1 ? cell->servers.next : _p->next;
-
- return _p != &cell->servers ? _p : NULL;
+ return seq_list_next(v, &cell->servers, _pos);
}
/*
@@ -791,11 +731,12 @@ static void afs_proc_cell_servers_stop(struct seq_file *p, void *v)
*/
static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
{
+ struct afs_cell *cell = m->private;
struct afs_server *server = list_entry(v, struct afs_server, link);
char ipaddr[20];
/* display header on line 1 */
- if (v == (void *) 1) {
+ if (v == &cell->servers) {
seq_puts(m, "USE ADDR STATE\n");
return 0;
}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 2e8496ba1205..993cdf1cce3a 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -460,6 +460,9 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
spin_lock_init(&vnode->writeback_lock);
spin_lock_init(&vnode->lock);
INIT_LIST_HEAD(&vnode->writebacks);
+ INIT_LIST_HEAD(&vnode->pending_locks);
+ INIT_LIST_HEAD(&vnode->granted_locks);
+ INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
}
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index 232c55dc245d..2f05c4fc2a70 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -561,7 +561,7 @@ no_server:
/*
* create a hard link
*/
-extern int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
+int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
struct key *key, const char *name)
{
struct afs_server *server;
@@ -887,11 +887,6 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key,
vnode->fid.unique,
key_serial(key));
- /* this op will fetch the status */
- spin_lock(&vnode->lock);
- vnode->update_cnt++;
- spin_unlock(&vnode->lock);
-
do {
/* pick a server to query */
server = afs_volume_pick_fileserver(vnode);
@@ -905,20 +900,127 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key,
} while (!afs_volume_release_fileserver(vnode, server, ret));
/* adjust the flags */
- if (ret == 0) {
- afs_vnode_finalise_status_update(vnode, server);
+ if (ret == 0)
+ afs_put_server(server);
+
+ _leave(" = %d", ret);
+ return ret;
+
+no_server:
+ return PTR_ERR(server);
+}
+
+/*
+ * get a lock on a file
+ */
+int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key,
+ afs_lock_type_t type)
+{
+ struct afs_server *server;
+ int ret;
+
+ _enter("%s{%x:%u.%u},%x,%u",
+ vnode->volume->vlocation->vldb.name,
+ vnode->fid.vid,
+ vnode->fid.vnode,
+ vnode->fid.unique,
+ key_serial(key), type);
+
+ do {
+ /* pick a server to query */
+ server = afs_volume_pick_fileserver(vnode);
+ if (IS_ERR(server))
+ goto no_server;
+
+ _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+ ret = afs_fs_set_lock(server, key, vnode, type, &afs_sync_call);
+
+ } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+ /* adjust the flags */
+ if (ret == 0)
+ afs_put_server(server);
+
+ _leave(" = %d", ret);
+ return ret;
+
+no_server:
+ return PTR_ERR(server);
+}
+
+/*
+ * extend a lock on a file
+ */
+int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key)
+{
+ struct afs_server *server;
+ int ret;
+
+ _enter("%s{%x:%u.%u},%x",
+ vnode->volume->vlocation->vldb.name,
+ vnode->fid.vid,
+ vnode->fid.vnode,
+ vnode->fid.unique,
+ key_serial(key));
+
+ do {
+ /* pick a server to query */
+ server = afs_volume_pick_fileserver(vnode);
+ if (IS_ERR(server))
+ goto no_server;
+
+ _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+ ret = afs_fs_extend_lock(server, key, vnode, &afs_sync_call);
+
+ } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+ /* adjust the flags */
+ if (ret == 0)
+ afs_put_server(server);
+
+ _leave(" = %d", ret);
+ return ret;
+
+no_server:
+ return PTR_ERR(server);
+}
+
+/*
+ * release a lock on a file
+ */
+int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key)
+{
+ struct afs_server *server;
+ int ret;
+
+ _enter("%s{%x:%u.%u},%x",
+ vnode->volume->vlocation->vldb.name,
+ vnode->fid.vid,
+ vnode->fid.vnode,
+ vnode->fid.unique,
+ key_serial(key));
+
+ do {
+ /* pick a server to query */
+ server = afs_volume_pick_fileserver(vnode);
+ if (IS_ERR(server))
+ goto no_server;
+
+ _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+ ret = afs_fs_release_lock(server, key, vnode, &afs_sync_call);
+
+ } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+ /* adjust the flags */
+ if (ret == 0)
afs_put_server(server);
- } else {
- afs_vnode_status_update_failed(vnode, ret);
- }
_leave(" = %d", ret);
return ret;
no_server:
- spin_lock(&vnode->lock);
- vnode->update_cnt--;
- ASSERTCMP(vnode->update_cnt, >=, 0);
- spin_unlock(&vnode->lock);
return PTR_ERR(server);
}
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index edc67486238f..b4a75880f6fd 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -53,7 +53,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
};
/**
- * anon_inode_getfd - creates a new file instance by hooking it up to and
+ * anon_inode_getfd - creates a new file instance by hooking it up to an
* anonymous inode, and a dentry that describe the "class"
* of the file
*
@@ -66,7 +66,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
*
* Creates a new file by hooking it on a single inode. This is useful for files
* that do not need to have a full-fledged inode in order to operate correctly.
- * All the files created with anon_inode_getfd() will share a single inode, by
+ * All the files created with anon_inode_getfd() will share a single inode,
* hence saving memory and avoiding code duplication for the file/inode/dentry
* setup.
*/
@@ -142,9 +142,9 @@ err_put_filp:
EXPORT_SYMBOL_GPL(anon_inode_getfd);
/*
- * A single inode exist for all anon_inode files. Contrary to pipes,
- * anon_inode inodes has no per-instance data associated, so we can avoid
- * the allocation of multiple of them.
+ * A single inode exists for all anon_inode files. Contrary to pipes,
+ * anon_inode inodes have no associated per-instance data, so we need
+ * only allocate one of them.
*/
static struct inode *anon_inode_mkinode(void)
{
diff --git a/fs/attr.c b/fs/attr.c
index a0a0c7b07ba3..f8dfc2269d85 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -42,7 +42,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
/* Make sure a caller can chmod. */
if (ia_valid & ATTR_MODE) {
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
goto error;
/* Also check the setgid bit! */
if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
@@ -52,7 +52,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
/* Check for setting the inode time. */
if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
- if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
goto error;
}
fine:
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 08e4414b8374..a27e42bf3400 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -45,7 +45,7 @@
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static int load_elf_library(struct file *);
-static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
/*
* If we don't support core dumping, then supply a NULL so we
@@ -80,7 +80,7 @@ static struct linux_binfmt elf_format = {
.hasvdso = 1
};
-#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
+#define BAD_ADDR(x) IS_ERR_VALUE(x)
static int set_brk(unsigned long start, unsigned long end)
{
@@ -285,33 +285,70 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
#ifndef elf_map
static unsigned long elf_map(struct file *filep, unsigned long addr,
- struct elf_phdr *eppnt, int prot, int type)
+ struct elf_phdr *eppnt, int prot, int type,
+ unsigned long total_size)
{
unsigned long map_addr;
- unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
+ unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr);
+ unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
+ addr = ELF_PAGESTART(addr);
+ size = ELF_PAGEALIGN(size);
- down_write(&current->mm->mmap_sem);
/* mmap() will return -EINVAL if given a zero size, but a
* segment with zero filesize is perfectly valid */
- if (eppnt->p_filesz + pageoffset)
- map_addr = do_mmap(filep, ELF_PAGESTART(addr),
- eppnt->p_filesz + pageoffset, prot, type,
- eppnt->p_offset - pageoffset);
- else
- map_addr = ELF_PAGESTART(addr);
+ if (!size)
+ return addr;
+
+ down_write(&current->mm->mmap_sem);
+ /*
+ * total_size is the size of the ELF (interpreter) image.
+ * The _first_ mmap needs to know the full size, otherwise
+ * randomization might put this image into an overlapping
+ * position with the ELF binary image. (since size < total_size)
+ * So we first map the 'big' image - and unmap the remainder at
+ * the end. (which unmap is needed for ELF images with holes.)
+ */
+ if (total_size) {
+ total_size = ELF_PAGEALIGN(total_size);
+ map_addr = do_mmap(filep, addr, total_size, prot, type, off);
+ if (!BAD_ADDR(map_addr))
+ do_munmap(current->mm, map_addr+size, total_size-size);
+ } else
+ map_addr = do_mmap(filep, addr, size, prot, type, off);
+
up_write(&current->mm->mmap_sem);
return(map_addr);
}
#endif /* !elf_map */
+static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
+{
+ int i, first_idx = -1, last_idx = -1;
+
+ for (i = 0; i < nr; i++) {
+ if (cmds[i].p_type == PT_LOAD) {
+ last_idx = i;
+ if (first_idx == -1)
+ first_idx = i;
+ }
+ }
+ if (first_idx == -1)
+ return 0;
+
+ return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
+ ELF_PAGESTART(cmds[first_idx].p_vaddr);
+}
+
+
/* This is much more generalized than the library routine read function,
so we keep this separate. Technically the library read function
is only provided so that we can read a.out libraries that have
an ELF header */
static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
- struct file *interpreter, unsigned long *interp_load_addr)
+ struct file *interpreter, unsigned long *interp_map_addr,
+ unsigned long no_base)
{
struct elf_phdr *elf_phdata;
struct elf_phdr *eppnt;
@@ -319,6 +356,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
int load_addr_set = 0;
unsigned long last_bss = 0, elf_bss = 0;
unsigned long error = ~0UL;
+ unsigned long total_size;
int retval, i, size;
/* First of all, some simple consistency checks */
@@ -357,6 +395,12 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
goto out_close;
}
+ total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
+ if (!total_size) {
+ error = -EINVAL;
+ goto out_close;
+ }
+
eppnt = elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
@@ -374,9 +418,14 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
vaddr = eppnt->p_vaddr;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
elf_type |= MAP_FIXED;
+ else if (no_base && interp_elf_ex->e_type == ET_DYN)
+ load_addr = -vaddr;
map_addr = elf_map(interpreter, load_addr + vaddr,
- eppnt, elf_prot, elf_type);
+ eppnt, elf_prot, elf_type, total_size);
+ total_size = 0;
+ if (!*interp_map_addr)
+ *interp_map_addr = map_addr;
error = map_addr;
if (BAD_ADDR(map_addr))
goto out_close;
@@ -442,8 +491,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
goto out_close;
}
- *interp_load_addr = load_addr;
- error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
+ error = load_addr;
out_close:
kfree(elf_phdata);
@@ -540,7 +588,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
int elf_exec_fileno;
int retval, i;
unsigned int size;
- unsigned long elf_entry, interp_load_addr = 0;
+ unsigned long elf_entry;
+ unsigned long interp_load_addr = 0;
unsigned long start_code, end_code, start_data, end_data;
unsigned long reloc_func_desc = 0;
char passed_fileno[6];
@@ -808,9 +857,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
- the correct location in memory. At this point, we assume that
- the image should be loaded at fixed address, not at a variable
- address. */
+ the correct location in memory. */
for(i = 0, elf_ppnt = elf_phdata;
i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
int elf_prot = 0, elf_flags;
@@ -864,11 +911,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
* default mmap base, as well as whatever program they
* might try to exec. This is because the brk will
* follow the loader, and is not movable. */
+#ifdef CONFIG_X86
+ load_bias = 0;
+#else
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
+#endif
}
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
- elf_prot, elf_flags);
+ elf_prot, elf_flags,0);
if (BAD_ADDR(error)) {
send_sig(SIGKILL, current, 0);
retval = IS_ERR((void *)error) ?
@@ -944,13 +995,25 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
}
if (elf_interpreter) {
- if (interpreter_type == INTERPRETER_AOUT)
+ if (interpreter_type == INTERPRETER_AOUT) {
elf_entry = load_aout_interp(&loc->interp_ex,
interpreter);
- else
+ } else {
+ unsigned long uninitialized_var(interp_map_addr);
+
elf_entry = load_elf_interp(&loc->interp_elf_ex,
interpreter,
- &interp_load_addr);
+ &interp_map_addr,
+ load_bias);
+ if (!BAD_ADDR(elf_entry)) {
+ /*
+ * load_elf_interp() returns relocation
+ * adjustment
+ */
+ interp_load_addr = elf_entry;
+ elf_entry += loc->interp_elf_ex.e_entry;
+ }
+ }
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = IS_ERR((void *)elf_entry) ?
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b3e9bfa748cf..3635315e3b99 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -588,12 +588,10 @@ EXPORT_SYMBOL(bdget);
long nr_blockdev_pages(void)
{
- struct list_head *p;
+ struct block_device *bdev;
long ret = 0;
spin_lock(&bdev_lock);
- list_for_each(p, &all_bdevs) {
- struct block_device *bdev;
- bdev = list_entry(p, struct block_device, bd_list);
+ list_for_each_entry(bdev, &all_bdevs, bd_list) {
ret += bdev->bd_inode->i_mapping->nrpages;
}
spin_unlock(&bdev_lock);
@@ -874,7 +872,7 @@ static struct bd_holder *find_bd_holder(struct block_device *bdev,
*/
static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
{
- int ret;
+ int err;
if (!bo)
return -EINVAL;
@@ -882,15 +880,18 @@ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
if (!bd_holder_grab_dirs(bdev, bo))
return -EBUSY;
- ret = add_symlink(bo->sdir, bo->sdev);
- if (ret == 0) {
- ret = add_symlink(bo->hdir, bo->hdev);
- if (ret)
- del_symlink(bo->sdir, bo->sdev);
+ err = add_symlink(bo->sdir, bo->sdev);
+ if (err)
+ return err;
+
+ err = add_symlink(bo->hdir, bo->hdev);
+ if (err) {
+ del_symlink(bo->sdir, bo->sdev);
+ return err;
}
- if (ret == 0)
- list_add_tail(&bo->list, &bdev->bd_holder_list);
- return ret;
+
+ list_add_tail(&bo->list, &bdev->bd_holder_list);
+ return 0;
}
/**
@@ -948,7 +949,7 @@ static struct bd_holder *del_bd_holder(struct block_device *bdev,
static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
struct kobject *kobj)
{
- int res;
+ int err;
struct bd_holder *bo, *found;
if (!kobj)
@@ -959,21 +960,24 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
return -ENOMEM;
mutex_lock(&bdev->bd_mutex);
- res = bd_claim(bdev, holder);
- if (res == 0) {
- found = find_bd_holder(bdev, bo);
- if (found == NULL) {
- res = add_bd_holder(bdev, bo);
- if (res)
- bd_release(bdev);
- }
- }
- if (res || found)
- free_bd_holder(bo);
- mutex_unlock(&bdev->bd_mutex);
+ err = bd_claim(bdev, holder);
+ if (err)
+ goto fail;
- return res;
+ found = find_bd_holder(bdev, bo);
+ if (found)
+ goto fail;
+
+ err = add_bd_holder(bdev, bo);
+ if (err)
+ bd_release(bdev);
+ else
+ bo = NULL;
+fail:
+ mutex_unlock(&bdev->bd_mutex);
+ free_bd_holder(bo);
+ return err;
}
/**
@@ -987,15 +991,12 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
static void bd_release_from_kobject(struct block_device *bdev,
struct kobject *kobj)
{
- struct bd_holder *bo;
-
if (!kobj)
return;
mutex_lock(&bdev->bd_mutex);
bd_release(bdev);
- if ((bo = del_bd_holder(bdev, kobj)))
- free_bd_holder(bo);
+ free_bd_holder(del_bd_holder(bdev, kobj));
mutex_unlock(&bdev->bd_mutex);
}
diff --git a/fs/buffer.c b/fs/buffer.c
index aa68206bd517..0f9006714230 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -356,7 +356,7 @@ static void free_more_memory(void)
for_each_online_pgdat(pgdat) {
zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
if (*zones)
- try_to_free_pages(zones, GFP_NOFS);
+ try_to_free_pages(zones, 0, GFP_NOFS);
}
}
@@ -676,6 +676,39 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
EXPORT_SYMBOL(mark_buffer_dirty_inode);
/*
+ * Mark the page dirty, and set it dirty in the radix tree, and mark the inode
+ * dirty.
+ *
+ * If warn is true, then emit a warning if the page is not uptodate and has
+ * not been truncated.
+ */
+static int __set_page_dirty(struct page *page,
+ struct address_space *mapping, int warn)
+{
+ if (unlikely(!mapping))
+ return !TestSetPageDirty(page);
+
+ if (TestSetPageDirty(page))
+ return 0;
+
+ write_lock_irq(&mapping->tree_lock);
+ if (page->mapping) { /* Race with truncate? */
+ WARN_ON_ONCE(warn && !PageUptodate(page));
+
+ if (mapping_cap_account_dirty(mapping)) {
+ __inc_zone_page_state(page, NR_FILE_DIRTY);
+ task_io_account_write(PAGE_CACHE_SIZE);
+ }
+ radix_tree_tag_set(&mapping->page_tree,
+ page_index(page), PAGECACHE_TAG_DIRTY);
+ }
+ write_unlock_irq(&mapping->tree_lock);
+ __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+
+ return 1;
+}
+
+/*
* Add a page to the dirty page list.
*
* It is a sad fact of life that this function is called from several places
@@ -702,7 +735,7 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode);
*/
int __set_page_dirty_buffers(struct page *page)
{
- struct address_space * const mapping = page_mapping(page);
+ struct address_space *mapping = page_mapping(page);
if (unlikely(!mapping))
return !TestSetPageDirty(page);
@@ -719,21 +752,7 @@ int __set_page_dirty_buffers(struct page *page)
}
spin_unlock(&mapping->private_lock);
- if (TestSetPageDirty(page))
- return 0;
-
- write_lock_irq(&mapping->tree_lock);
- if (page->mapping) { /* Race with truncate? */
- if (mapping_cap_account_dirty(mapping)) {
- __inc_zone_page_state(page, NR_FILE_DIRTY);
- task_io_account_write(PAGE_CACHE_SIZE);
- }
- radix_tree_tag_set(&mapping->page_tree,
- page_index(page), PAGECACHE_TAG_DIRTY);
- }
- write_unlock_irq(&mapping->tree_lock);
- __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
- return 1;
+ return __set_page_dirty(page, mapping, 1);
}
EXPORT_SYMBOL(__set_page_dirty_buffers);
@@ -982,7 +1001,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
struct buffer_head *bh;
page = find_or_create_page(inode->i_mapping, index,
- mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+ (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
if (!page)
return NULL;
@@ -1026,11 +1045,6 @@ failed:
/*
* Create buffers for the specified block device block's page. If
* that page was dirty, the buffers are set dirty also.
- *
- * Except that's a bug. Attaching dirty buffers to a dirty
- * blockdev's page can result in filesystem corruption, because
- * some of those buffers may be aliases of filesystem data.
- * grow_dev_page() will go BUG() if this happens.
*/
static int
grow_buffers(struct block_device *bdev, sector_t block, int size)
@@ -1137,8 +1151,9 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
*/
void fastcall mark_buffer_dirty(struct buffer_head *bh)
{
+ WARN_ON_ONCE(!buffer_uptodate(bh));
if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh))
- __set_page_dirty_nobuffers(bh->b_page);
+ __set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0);
}
/*
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8b0cbf4a4ad0..bd0f2f2353ce 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -849,6 +849,7 @@ static int cifs_oplock_thread(void * dummyarg)
__u16 netfid;
int rc;
+ set_freezable();
do {
if (try_to_freeze())
continue;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f4e92661b223..0a1b8bd1dfcb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -363,6 +363,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
GFP_KERNEL);
}
+ set_freezable();
while (!kthread_should_stop()) {
if (try_to_freeze())
continue;
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 1d716392c3aa..96df1d51fdc3 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -29,6 +29,7 @@
*/
#include <linux/fs.h>
+#include <linux/exportfs.h>
#ifdef CONFIG_CIFS_EXPERIMENTAL
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 6b44cdc96fac..e440a7b95d02 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -63,6 +63,7 @@
#include <linux/wireless.h>
#include <linux/atalk.h>
#include <linux/blktrace_api.h>
+#include <linux/loop.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci.h>
@@ -3489,6 +3490,9 @@ HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans)
IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
+
+/* loop */
+IGNORE_IOCTL(LOOP_CLR_FD)
};
#define IOCTL_HASHSIZE 256
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 7b48c034b312..3b0185fdf9a4 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -29,10 +29,11 @@
struct configfs_dirent {
atomic_t s_count;
+ int s_dependent_count;
struct list_head s_sibling;
struct list_head s_children;
struct list_head s_links;
- void * s_element;
+ void * s_element;
int s_type;
umode_t s_mode;
struct dentry * s_dentry;
@@ -41,8 +42,8 @@ struct configfs_dirent {
#define CONFIGFS_ROOT 0x0001
#define CONFIGFS_DIR 0x0002
-#define CONFIGFS_ITEM_ATTR 0x0004
-#define CONFIGFS_ITEM_LINK 0x0020
+#define CONFIGFS_ITEM_ATTR 0x0004
+#define CONFIGFS_ITEM_LINK 0x0020
#define CONFIGFS_USET_DIR 0x0040
#define CONFIGFS_USET_DEFAULT 0x0080
#define CONFIGFS_USET_DROPPING 0x0100
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5e6e37e58f36..2f436d4f1d6d 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -355,6 +355,10 @@ static int configfs_detach_prep(struct dentry *dentry)
/* Mark that we've taken i_mutex */
sd->s_type |= CONFIGFS_USET_DROPPING;
+ /*
+ * Yup, recursive. If there's a problem, blame
+ * deep nesting of default_groups
+ */
ret = configfs_detach_prep(sd->s_dentry);
if (!ret)
continue;
@@ -562,7 +566,7 @@ static int populate_groups(struct config_group *group)
/*
* All of link_obj/unlink_obj/link_group/unlink_group require that
- * subsys->su_sem is held.
+ * subsys->su_mutex is held.
*/
static void unlink_obj(struct config_item *item)
@@ -714,6 +718,28 @@ static void configfs_detach_group(struct config_item *item)
}
/*
+ * After the item has been detached from the filesystem view, we are
+ * ready to tear it out of the hierarchy. Notify the client before
+ * we do that so they can perform any cleanup that requires
+ * navigating the hierarchy. A client does not need to provide this
+ * callback. The subsystem semaphore MUST be held by the caller, and
+ * references must be valid for both items. It also assumes the
+ * caller has validated ci_type.
+ */
+static void client_disconnect_notify(struct config_item *parent_item,
+ struct config_item *item)
+{
+ struct config_item_type *type;
+
+ type = parent_item->ci_type;
+ BUG_ON(!type);
+
+ if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
+ type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
+ item);
+}
+
+/*
* Drop the initial reference from make_item()/make_group()
* This function assumes that reference is held on item
* and that item holds a valid reference to the parent. Also, it
@@ -733,11 +759,244 @@ static void client_drop_item(struct config_item *parent_item,
*/
if (type->ct_group_ops && type->ct_group_ops->drop_item)
type->ct_group_ops->drop_item(to_config_group(parent_item),
- item);
+ item);
else
config_item_put(item);
}
+#ifdef DEBUG
+static void configfs_dump_one(struct configfs_dirent *sd, int level)
+{
+ printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));
+
+#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);
+ type_print(CONFIGFS_ROOT);
+ type_print(CONFIGFS_DIR);
+ type_print(CONFIGFS_ITEM_ATTR);
+ type_print(CONFIGFS_ITEM_LINK);
+ type_print(CONFIGFS_USET_DIR);
+ type_print(CONFIGFS_USET_DEFAULT);
+ type_print(CONFIGFS_USET_DROPPING);
+#undef type_print
+}
+
+static int configfs_dump(struct configfs_dirent *sd, int level)
+{
+ struct configfs_dirent *child_sd;
+ int ret = 0;
+
+ configfs_dump_one(sd, level);
+
+ if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))
+ return 0;
+
+ list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+ ret = configfs_dump(child_sd, level + 2);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+#endif
+
+
+/*
+ * configfs_depend_item() and configfs_undepend_item()
+ *
+ * WARNING: Do not call these from a configfs callback!
+ *
+ * This describes these functions and their helpers.
+ *
+ * Allow another kernel system to depend on a config_item. If this
+ * happens, the item cannot go away until the dependant can live without
+ * it. The idea is to give client modules as simple an interface as
+ * possible. When a system asks them to depend on an item, they just
+ * call configfs_depend_item(). If the item is live and the client
+ * driver is in good shape, we'll happily do the work for them.
+ *
+ * Why is the locking complex? Because configfs uses the VFS to handle
+ * all locking, but this function is called outside the normal
+ * VFS->configfs path. So it must take VFS locks to prevent the
+ * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc). This is
+ * why you can't call these functions underneath configfs callbacks.
+ *
+ * Note, btw, that this can be called at *any* time, even when a configfs
+ * subsystem isn't registered, or when configfs is loading or unloading.
+ * Just like configfs_register_subsystem(). So we take the same
+ * precautions. We pin the filesystem. We lock each i_mutex _in_order_
+ * on our way down the tree. If we can find the target item in the
+ * configfs tree, it must be part of the subsystem tree as well, so we
+ * do not need the subsystem semaphore. Holding the i_mutex chain locks
+ * out mkdir() and rmdir(), who might be racing us.
+ */
+
+/*
+ * configfs_depend_prep()
+ *
+ * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are
+ * attributes. This is similar but not the same to configfs_detach_prep().
+ * Note that configfs_detach_prep() expects the parent to be locked when it
+ * is called, but we lock the parent *inside* configfs_depend_prep(). We
+ * do that so we can unlock it if we find nothing.
+ *
+ * Here we do a depth-first search of the dentry hierarchy looking for
+ * our object. We take i_mutex on each step of the way down. IT IS
+ * ESSENTIAL THAT i_mutex LOCKING IS ORDERED. If we come back up a branch,
+ * we'll drop the i_mutex.
+ *
+ * If the target is not found, -ENOENT is bubbled up and we have released
+ * all locks. If the target was found, the locks will be cleared by
+ * configfs_depend_rollback().
+ *
+ * This adds a requirement that all config_items be unique!
+ *
+ * This is recursive because the locking traversal is tricky. There isn't
+ * much on the stack, though, so folks that need this function - be careful
+ * about your stack! Patches will be accepted to make it iterative.
+ */
+static int configfs_depend_prep(struct dentry *origin,
+ struct config_item *target)
+{
+ struct configfs_dirent *child_sd, *sd = origin->d_fsdata;
+ int ret = 0;
+
+ BUG_ON(!origin || !sd);
+
+ /* Lock this guy on the way down */
+ mutex_lock(&sd->s_dentry->d_inode->i_mutex);
+ if (sd->s_element == target) /* Boo-yah */
+ goto out;
+
+ list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
+ if (child_sd->s_type & CONFIGFS_DIR) {
+ ret = configfs_depend_prep(child_sd->s_dentry,
+ target);
+ if (!ret)
+ goto out; /* Child path boo-yah */
+ }
+ }
+
+ /* We looped all our children and didn't find target */
+ mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
+ ret = -ENOENT;
+
+out:
+ return ret;
+}
+
+/*
+ * This is ONLY called if configfs_depend_prep() did its job. So we can
+ * trust the entire path from item back up to origin.
+ *
+ * We walk backwards from item, unlocking each i_mutex. We finish by
+ * unlocking origin.
+ */
+static void configfs_depend_rollback(struct dentry *origin,
+ struct config_item *item)
+{
+ struct dentry *dentry = item->ci_dentry;
+
+ while (dentry != origin) {
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ dentry = dentry->d_parent;
+ }
+
+ mutex_unlock(&origin->d_inode->i_mutex);
+}
+
+int configfs_depend_item(struct configfs_subsystem *subsys,
+ struct config_item *target)
+{
+ int ret;
+ struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
+ struct config_item *s_item = &subsys->su_group.cg_item;
+
+ /*
+ * Pin the configfs filesystem. This means we can safely access
+ * the root of the configfs filesystem.
+ */
+ ret = configfs_pin_fs();
+ if (ret)
+ return ret;
+
+ /*
+ * Next, lock the root directory. We're going to check that the
+ * subsystem is really registered, and so we need to lock out
+ * configfs_[un]register_subsystem().
+ */
+ mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
+
+ root_sd = configfs_sb->s_root->d_fsdata;
+
+ list_for_each_entry(p, &root_sd->s_children, s_sibling) {
+ if (p->s_type & CONFIGFS_DIR) {
+ if (p->s_element == s_item) {
+ subsys_sd = p;
+ break;
+ }
+ }
+ }
+
+ if (!subsys_sd) {
+ ret = -ENOENT;
+ goto out_unlock_fs;
+ }
+
+ /* Ok, now we can trust subsys/s_item */
+
+ /* Scan the tree, locking i_mutex recursively, return 0 if found */
+ ret = configfs_depend_prep(subsys_sd->s_dentry, target);
+ if (ret)
+ goto out_unlock_fs;
+
+ /* We hold all i_mutexes from the subsystem down to the target */
+ p = target->ci_dentry->d_fsdata;
+ p->s_dependent_count += 1;
+
+ configfs_depend_rollback(subsys_sd->s_dentry, target);
+
+out_unlock_fs:
+ mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
+
+ /*
+ * If we succeeded, the fs is pinned via other methods. If not,
+ * we're done with it anyway. So release_fs() is always right.
+ */
+ configfs_release_fs();
+
+ return ret;
+}
+EXPORT_SYMBOL(configfs_depend_item);
+
+/*
+ * Release the dependent linkage. This is much simpler than
+ * configfs_depend_item() because we know that that the client driver is
+ * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
+ */
+void configfs_undepend_item(struct configfs_subsystem *subsys,
+ struct config_item *target)
+{
+ struct configfs_dirent *sd;
+
+ /*
+ * Since we can trust everything is pinned, we just need i_mutex
+ * on the item.
+ */
+ mutex_lock(&target->ci_dentry->d_inode->i_mutex);
+
+ sd = target->ci_dentry->d_fsdata;
+ BUG_ON(sd->s_dependent_count < 1);
+
+ sd->s_dependent_count -= 1;
+
+ /*
+ * After this unlock, we cannot trust the item to stay alive!
+ * DO NOT REFERENCE item after this unlock.
+ */
+ mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
+}
+EXPORT_SYMBOL(configfs_undepend_item);
static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
@@ -783,7 +1042,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
- down(&subsys->su_sem);
+ mutex_lock(&subsys->su_mutex);
group = NULL;
item = NULL;
if (type->ct_group_ops->make_group) {
@@ -797,7 +1056,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (item)
link_obj(parent_item, item);
}
- up(&subsys->su_sem);
+ mutex_unlock(&subsys->su_mutex);
kfree(name);
if (!item) {
@@ -841,13 +1100,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
out_unlink:
if (ret) {
/* Tear down everything we built up */
- down(&subsys->su_sem);
+ mutex_lock(&subsys->su_mutex);
+
+ client_disconnect_notify(parent_item, item);
if (group)
unlink_group(group);
else
unlink_obj(item);
client_drop_item(parent_item, item);
- up(&subsys->su_sem);
+
+ mutex_unlock(&subsys->su_mutex);
if (module_got)
module_put(owner);
@@ -881,6 +1143,13 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
if (sd->s_type & CONFIGFS_USET_DEFAULT)
return -EPERM;
+ /*
+ * Here's where we check for dependents. We're protected by
+ * i_mutex.
+ */
+ if (sd->s_dependent_count)
+ return -EBUSY;
+
/* Get a working ref until we have the child */
parent_item = configfs_get_config_item(dentry->d_parent);
subsys = to_config_group(parent_item)->cg_subsys;
@@ -910,17 +1179,19 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
if (sd->s_type & CONFIGFS_USET_DIR) {
configfs_detach_group(item);
- down(&subsys->su_sem);
+ mutex_lock(&subsys->su_mutex);
+ client_disconnect_notify(parent_item, item);
unlink_group(to_config_group(item));
} else {
configfs_detach_item(item);
- down(&subsys->su_sem);
+ mutex_lock(&subsys->su_mutex);
+ client_disconnect_notify(parent_item, item);
unlink_obj(item);
}
client_drop_item(parent_item, item);
- up(&subsys->su_sem);
+ mutex_unlock(&subsys->su_mutex);
/* Drop our reference from above */
config_item_put(item);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 3527c7c6def8..a3658f9a082c 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -27,19 +27,26 @@
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <linux/configfs.h>
#include "configfs_internal.h"
+/*
+ * A simple attribute can only be 4096 characters. Why 4k? Because the
+ * original code limited it to PAGE_SIZE. That's a bad idea, though,
+ * because an attribute of 16k on ia64 won't work on x86. So we limit to
+ * 4k, our minimum common page size.
+ */
+#define SIMPLE_ATTR_SIZE 4096
struct configfs_buffer {
size_t count;
loff_t pos;
char * page;
struct configfs_item_operations * ops;
- struct semaphore sem;
+ struct mutex mutex;
int needs_read_fill;
};
@@ -69,7 +76,7 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
count = ops->show_attribute(item,attr,buffer->page);
buffer->needs_read_fill = 0;
- BUG_ON(count > (ssize_t)PAGE_SIZE);
+ BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
if (count >= 0)
buffer->count = count;
else
@@ -102,7 +109,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
struct configfs_buffer * buffer = file->private_data;
ssize_t retval = 0;
- down(&buffer->sem);
+ mutex_lock(&buffer->mutex);
if (buffer->needs_read_fill) {
if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
goto out;
@@ -112,7 +119,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
buffer->count);
out:
- up(&buffer->sem);
+ mutex_unlock(&buffer->mutex);
return retval;
}
@@ -137,8 +144,8 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size
if (!buffer->page)
return -ENOMEM;
- if (count >= PAGE_SIZE)
- count = PAGE_SIZE - 1;
+ if (count >= SIMPLE_ATTR_SIZE)
+ count = SIMPLE_ATTR_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
/* if buf is assumed to contain a string, terminate it by \0,
@@ -193,13 +200,13 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
struct configfs_buffer * buffer = file->private_data;
ssize_t len;
- down(&buffer->sem);
+ mutex_lock(&buffer->mutex);
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
len = flush_write_buffer(file->f_path.dentry, buffer, count);
if (len > 0)
*ppos += len;
- up(&buffer->sem);
+ mutex_unlock(&buffer->mutex);
return len;
}
@@ -253,7 +260,7 @@ static int check_perm(struct inode * inode, struct file * file)
error = -ENOMEM;
goto Enomem;
}
- init_MUTEX(&buffer->sem);
+ mutex_init(&buffer->mutex);
buffer->needs_read_fill = 1;
buffer->ops = ops;
file->private_data = buffer;
@@ -292,6 +299,7 @@ static int configfs_release(struct inode * inode, struct file * filp)
if (buffer) {
if (buffer->page)
free_page((unsigned long)buffer->page);
+ mutex_destroy(&buffer->mutex);
kfree(buffer);
}
return 0;
diff --git a/fs/configfs/item.c b/fs/configfs/item.c
index 24421209f854..76dc4c3e5d51 100644
--- a/fs/configfs/item.c
+++ b/fs/configfs/item.c
@@ -62,7 +62,6 @@ void config_item_init(struct config_item * item)
* dynamically allocated string that @item->ci_name points to.
* Otherwise, use the static @item->ci_namebuf array.
*/
-
int config_item_set_name(struct config_item * item, const char * fmt, ...)
{
int error = 0;
@@ -139,12 +138,7 @@ struct config_item * config_item_get(struct config_item * item)
return item;
}
-/**
- * config_item_cleanup - free config_item resources.
- * @item: item.
- */
-
-void config_item_cleanup(struct config_item * item)
+static void config_item_cleanup(struct config_item * item)
{
struct config_item_type * t = item->ci_type;
struct config_group * s = item->ci_group;
@@ -179,39 +173,35 @@ void config_item_put(struct config_item * item)
kref_put(&item->ci_kref, config_item_release);
}
-
/**
* config_group_init - initialize a group for use
* @k: group
*/
-
void config_group_init(struct config_group *group)
{
config_item_init(&group->cg_item);
INIT_LIST_HEAD(&group->cg_children);
}
-
/**
- * config_group_find_obj - search for item in group.
+ * config_group_find_item - search for item in group.
* @group: group we're looking in.
* @name: item's name.
*
- * Lock group via @group->cg_subsys, and iterate over @group->cg_list,
- * looking for a matching config_item. If matching item is found
- * take a reference and return the item.
+ * Iterate over @group->cg_list, looking for a matching config_item.
+ * If matching item is found take a reference and return the item.
+ * Caller must have locked group via @group->cg_subsys->su_mtx.
*/
-
-struct config_item * config_group_find_obj(struct config_group * group, const char * name)
+struct config_item *config_group_find_item(struct config_group *group,
+ const char *name)
{
struct list_head * entry;
struct config_item * ret = NULL;
- /* XXX LOCKING! */
list_for_each(entry,&group->cg_children) {
struct config_item * item = to_item(entry);
if (config_item_name(item) &&
- !strcmp(config_item_name(item), name)) {
+ !strcmp(config_item_name(item), name)) {
ret = config_item_get(item);
break;
}
@@ -219,9 +209,8 @@ struct config_item * config_group_find_obj(struct config_group * group, const ch
return ret;
}
-
EXPORT_SYMBOL(config_item_init);
EXPORT_SYMBOL(config_group_init);
EXPORT_SYMBOL(config_item_get);
EXPORT_SYMBOL(config_item_put);
-EXPORT_SYMBOL(config_group_find_obj);
+EXPORT_SYMBOL(config_group_find_item);
diff --git a/fs/dcache.c b/fs/dcache.c
index 0e73aa0a0e8b..cb9d05056b54 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -883,6 +883,11 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
}
+static struct shrinker dcache_shrinker = {
+ .shrink = shrink_dcache_memory,
+ .seeks = DEFAULT_SEEKS,
+};
+
/**
* d_alloc - allocate a dcache entry
* @parent: parent of entry to allocate
@@ -2115,7 +2120,7 @@ static void __init dcache_init(unsigned long mempages)
dentry_cache = KMEM_CACHE(dentry,
SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
- set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
+ register_shrinker(&dcache_shrinker);
/* Hash may have been set up in dcache_init_early */
if (!hashdist)
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 5069b2cb5a1f..2f8e3c81bc19 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -133,14 +133,6 @@ static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field,
return len;
}
-#define __CONFIGFS_ATTR(_name,_mode,_read,_write) { \
- .attr = { .ca_name = __stringify(_name), \
- .ca_mode = _mode, \
- .ca_owner = THIS_MODULE }, \
- .show = _read, \
- .store = _write, \
-}
-
#define CLUSTER_ATTR(name, check_zero) \
static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len) \
{ \
@@ -615,7 +607,7 @@ static struct clusters clusters_root = {
int dlm_config_init(void)
{
config_group_init(&clusters_root.subsys.su_group);
- init_MUTEX(&clusters_root.subsys.su_sem);
+ mutex_init(&clusters_root.subsys.su_mutex);
return configfs_register_subsystem(&clusters_root.subsys);
}
@@ -759,9 +751,9 @@ static struct space *get_space(char *name)
if (!space_list)
return NULL;
- down(&space_list->cg_subsys->su_sem);
- i = config_group_find_obj(space_list, name);
- up(&space_list->cg_subsys->su_sem);
+ mutex_lock(&space_list->cg_subsys->su_mutex);
+ i = config_group_find_item(space_list, name);
+ mutex_unlock(&space_list->cg_subsys->su_mutex);
return to_space(i);
}
@@ -780,7 +772,7 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr)
if (!comm_list)
return NULL;
- down(&clusters_root.subsys.su_sem);
+ mutex_lock(&clusters_root.subsys.su_mutex);
list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
cm = to_comm(i);
@@ -800,7 +792,7 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr)
break;
}
}
- up(&clusters_root.subsys.su_sem);
+ mutex_unlock(&clusters_root.subsys.su_mutex);
if (!found)
cm = NULL;
diff --git a/fs/dquot.c b/fs/dquot.c
index 8819d281500c..7e273151f589 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -538,6 +538,11 @@ static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
return (dqstats.free_dquots / 100) * sysctl_vfs_cache_pressure;
}
+static struct shrinker dqcache_shrinker = {
+ .shrink = shrink_dqcache_memory,
+ .seeks = DEFAULT_SEEKS,
+};
+
/*
* Put reference to dquot
* NOTE: If you change this function please check whether dqput_blocks() works right...
@@ -1870,7 +1875,7 @@ static int __init dquot_init(void)
printk("Dquot-cache hash table entries: %ld (order %ld, %ld bytes)\n",
nr_hash, order, (PAGE_SIZE << order));
- set_shrinker(DEFAULT_SEEKS, shrink_dqcache_memory);
+ register_shrinker(&dqcache_shrinker);
return 0;
}
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 03ea7696fe39..59375efcf39d 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -20,7 +20,7 @@ static void drop_pagecache_sb(struct super_block *sb)
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
if (inode->i_state & (I_FREEING|I_WILL_FREE))
continue;
- invalidate_mapping_pages(inode->i_mapping, 0, -1);
+ __invalidate_mapping_pages(inode->i_mapping, 0, -1, true);
}
spin_unlock(&inode_lock);
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 83e94fedd4e9..e77a2ec71aa5 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -282,7 +282,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
struct dentry *lower_dentry;
struct vfsmount *lower_mnt;
char *encoded_name;
- unsigned int encoded_namelen;
+ int encoded_namelen;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
char *page_virt = NULL;
@@ -473,7 +473,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
struct dentry *lower_dir_dentry;
umode_t mode;
char *encoded_symname;
- unsigned int encoded_symlen;
+ int encoded_symlen;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index ed4a207fe22a..5276b19423c1 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -75,6 +75,38 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei
return NULL;
}
+struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
+{
+ __u32 *objp = vobjp;
+ unsigned long ino = objp[0];
+ __u32 generation = objp[1];
+ struct inode *inode;
+ struct dentry *result;
+
+ if (ino == 0)
+ return ERR_PTR(-ESTALE);
+ inode = iget(sb, ino);
+ if (inode == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ if (is_bad_inode(inode) ||
+ (generation && inode->i_generation != generation)) {
+ result = ERR_PTR(-ESTALE);
+ goto out_iput;
+ }
+
+ result = d_alloc_anon(inode);
+ if (!result) {
+ result = ERR_PTR(-ENOMEM);
+ goto out_iput;
+ }
+ return result;
+
+ out_iput:
+ iput(inode);
+ return result;
+}
+
struct dentry *efs_get_parent(struct dentry *child)
{
struct dentry *parent;
diff --git a/fs/efs/super.c b/fs/efs/super.c
index e0a6839e68ae..d360c81f3a72 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -11,6 +11,7 @@
#include <linux/efs_fs.h>
#include <linux/efs_vh.h>
#include <linux/efs_fs_sb.h>
+#include <linux/exportfs.h>
#include <linux/slab.h>
#include <linux/buffer_head.h>
#include <linux/vfs.h>
@@ -113,6 +114,7 @@ static const struct super_operations efs_superblock_operations = {
};
static struct export_operations efs_export_ops = {
+ .get_dentry = efs_get_dentry,
.get_parent = efs_get_parent,
};
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index e98f6cd7200c..8adb32a9387a 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -1,15 +1,45 @@
+#include <linux/exportfs.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/module.h>
+#include <linux/mount.h>
#include <linux/namei.h>
-struct export_operations export_op_default;
+#define dprintk(fmt, args...) do{}while(0)
-#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-#define dprintk(fmt, args...) do{}while(0)
+static int get_name(struct dentry *dentry, char *name,
+ struct dentry *child);
+
+
+static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj)
+{
+ struct dentry *result = ERR_PTR(-ESTALE);
+
+ if (sb->s_export_op->get_dentry) {
+ result = sb->s_export_op->get_dentry(sb, obj);
+ if (!result)
+ result = ERR_PTR(-ESTALE);
+ }
+
+ return result;
+}
+
+static int exportfs_get_name(struct dentry *dir, char *name,
+ struct dentry *child)
+{
+ struct export_operations *nop = dir->d_sb->s_export_op;
+ if (nop->get_name)
+ return nop->get_name(dir, name, child);
+ else
+ return get_name(dir, name, child);
+}
+
+/*
+ * Check if the dentry or any of it's aliases is acceptable.
+ */
static struct dentry *
find_acceptable_alias(struct dentry *result,
int (*acceptable)(void *context, struct dentry *dentry),
@@ -17,6 +47,9 @@ find_acceptable_alias(struct dentry *result,
{
struct dentry *dentry, *toput = NULL;
+ if (acceptable(context, result))
+ return result;
+
spin_lock(&dcache_lock);
list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
dget_locked(dentry);
@@ -37,130 +70,50 @@ find_acceptable_alias(struct dentry *result,
return NULL;
}
-/**
- * find_exported_dentry - helper routine to implement export_operations->decode_fh
- * @sb: The &super_block identifying the filesystem
- * @obj: An opaque identifier of the object to be found - passed to
- * get_inode
- * @parent: An optional opqaue identifier of the parent of the object.
- * @acceptable: A function used to test possible &dentries to see if they are
- * acceptable
- * @context: A parameter to @acceptable so that it knows on what basis to
- * judge.
- *
- * find_exported_dentry is the central helper routine to enable file systems
- * to provide the decode_fh() export_operation. It's main task is to take
- * an &inode, find or create an appropriate &dentry structure, and possibly
- * splice this into the dcache in the correct place.
- *
- * The decode_fh() operation provided by the filesystem should call
- * find_exported_dentry() with the same parameters that it received except
- * that instead of the file handle fragment, pointers to opaque identifiers
- * for the object and optionally its parent are passed. The default decode_fh
- * routine passes one pointer to the start of the filehandle fragment, and
- * one 8 bytes into the fragment. It is expected that most filesystems will
- * take this approach, though the offset to the parent identifier may well be
- * different.
- *
- * find_exported_dentry() will call get_dentry to get an dentry pointer from
- * the file system. If any &dentry in the d_alias list is acceptable, it will
- * be returned. Otherwise find_exported_dentry() will attempt to splice a new
- * &dentry into the dcache using get_name() and get_parent() to find the
- * appropriate place.
+/*
+ * Find root of a disconnected subtree and return a reference to it.
*/
-
-struct dentry *
-find_exported_dentry(struct super_block *sb, void *obj, void *parent,
- int (*acceptable)(void *context, struct dentry *de),
- void *context)
+static struct dentry *
+find_disconnected_root(struct dentry *dentry)
{
- struct dentry *result = NULL;
- struct dentry *target_dir;
- int err;
- struct export_operations *nops = sb->s_export_op;
- struct dentry *alias;
- int noprogress;
- char nbuf[NAME_MAX+1];
-
- /*
- * Attempt to find the inode.
- */
- result = CALL(sb->s_export_op,get_dentry)(sb,obj);
- err = -ESTALE;
- if (result == NULL)
- goto err_out;
- if (IS_ERR(result)) {
- err = PTR_ERR(result);
- goto err_out;
+ dget(dentry);
+ spin_lock(&dentry->d_lock);
+ while (!IS_ROOT(dentry) &&
+ (dentry->d_parent->d_flags & DCACHE_DISCONNECTED)) {
+ struct dentry *parent = dentry->d_parent;
+ dget(parent);
+ spin_unlock(&dentry->d_lock);
+ dput(dentry);
+ dentry = parent;
+ spin_lock(&dentry->d_lock);
}
- if (S_ISDIR(result->d_inode->i_mode) &&
- (result->d_flags & DCACHE_DISCONNECTED)) {
- /* it is an unconnected directory, we must connect it */
- ;
- } else {
- if (acceptable(context, result))
- return result;
- if (S_ISDIR(result->d_inode->i_mode)) {
- err = -EACCES;
- goto err_result;
- }
+ spin_unlock(&dentry->d_lock);
+ return dentry;
+}
- alias = find_acceptable_alias(result, acceptable, context);
- if (alias)
- return alias;
- }
-
- /* It's a directory, or we are required to confirm the file's
- * location in the tree based on the parent information
- */
- dprintk("find_exported_dentry: need to look harder for %s/%d\n",sb->s_id,*(int*)obj);
- if (S_ISDIR(result->d_inode->i_mode))
- target_dir = dget(result);
- else {
- if (parent == NULL)
- goto err_result;
- target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent);
- if (IS_ERR(target_dir))
- err = PTR_ERR(target_dir);
- if (target_dir == NULL || IS_ERR(target_dir))
- goto err_result;
- }
- /*
- * Now we need to make sure that target_dir is properly connected.
- * It may already be, as the flag isn't always updated when connection
- * happens.
- * So, we walk up parent links until we find a connected directory,
- * or we run out of directories. Then we find the parent, find
- * the name of the child in that parent, and do a lookup.
- * This should connect the child into the parent
- * We then repeat.
- */
+/*
+ * Make sure target_dir is fully connected to the dentry tree.
+ *
+ * It may already be, as the flag isn't always updated when connection happens.
+ */
+static int
+reconnect_path(struct super_block *sb, struct dentry *target_dir)
+{
+ char nbuf[NAME_MAX+1];
+ int noprogress = 0;
+ int err = -ESTALE;
- /* it is possible that a confused file system might not let us complete
+ /*
+ * It is possible that a confused file system might not let us complete
* the path to the root. For example, if get_parent returns a directory
* in which we cannot find a name for the child. While this implies a
* very sick filesystem we don't want it to cause knfsd to spin. Hence
* the noprogress counter. If we go through the loop 10 times (2 is
* probably enough) without getting anywhere, we just give up
*/
- noprogress= 0;
while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
- struct dentry *pd = target_dir;
-
- dget(pd);
- spin_lock(&pd->d_lock);
- while (!IS_ROOT(pd) &&
- (pd->d_parent->d_flags&DCACHE_DISCONNECTED)) {
- struct dentry *parent = pd->d_parent;
-
- dget(parent);
- spin_unlock(&pd->d_lock);
- dput(pd);
- pd = parent;
- spin_lock(&pd->d_lock);
- }
- spin_unlock(&pd->d_lock);
+ struct dentry *pd = find_disconnected_root(target_dir);
if (!IS_ROOT(pd)) {
/* must have found a connected parent - great */
@@ -175,29 +128,40 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
spin_unlock(&pd->d_lock);
noprogress = 0;
} else {
- /* we have hit the top of a disconnected path. Try
- * to find parent and connect
- * note: racing with some other process renaming a
- * directory isn't much of a problem here. If someone
- * renames the directory, it will end up properly
- * connected, which is what we want
+ /*
+ * We have hit the top of a disconnected path, try to
+ * find parent and connect.
+ *
+ * Racing with some other process renaming a directory
+ * isn't much of a problem here. If someone renames
+ * the directory, it will end up properly connected,
+ * which is what we want
+ *
+ * Getting the parent can't be supported generically,
+ * the locking is too icky.
+ *
+ * Instead we just return EACCES. If server reboots
+ * or inodes get flushed, you lose
*/
- struct dentry *ppd;
+ struct dentry *ppd = ERR_PTR(-EACCES);
struct dentry *npd;
mutex_lock(&pd->d_inode->i_mutex);
- ppd = CALL(nops,get_parent)(pd);
+ if (sb->s_export_op->get_parent)
+ ppd = sb->s_export_op->get_parent(pd);
mutex_unlock(&pd->d_inode->i_mutex);
if (IS_ERR(ppd)) {
err = PTR_ERR(ppd);
- dprintk("find_exported_dentry: get_parent of %ld failed, err %d\n",
- pd->d_inode->i_ino, err);
+ dprintk("%s: get_parent of %ld failed, err %d\n",
+ __FUNCTION__, pd->d_inode->i_ino, err);
dput(pd);
break;
}
- dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino);
- err = CALL(nops,get_name)(ppd, nbuf, pd);
+
+ dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
+ pd->d_inode->i_ino, ppd->d_inode->i_ino);
+ err = exportfs_get_name(ppd, nbuf, pd);
if (err) {
dput(ppd);
dput(pd);
@@ -208,13 +172,14 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
continue;
break;
}
- dprintk("find_exported_dentry: found name: %s\n", nbuf);
+ dprintk("%s: found name: %s\n", __FUNCTION__, nbuf);
mutex_lock(&ppd->d_inode->i_mutex);
npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
mutex_unlock(&ppd->d_inode->i_mutex);
if (IS_ERR(npd)) {
err = PTR_ERR(npd);
- dprintk("find_exported_dentry: lookup failed: %d\n", err);
+ dprintk("%s: lookup failed: %d\n",
+ __FUNCTION__, err);
dput(ppd);
dput(pd);
break;
@@ -227,7 +192,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
if (npd == pd)
noprogress = 0;
else
- printk("find_exported_dentry: npd != pd\n");
+ printk("%s: npd != pd\n", __FUNCTION__);
dput(npd);
dput(ppd);
if (IS_ROOT(pd)) {
@@ -243,15 +208,101 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
/* something went wrong - oh-well */
if (!err)
err = -ESTALE;
- goto err_target;
+ return err;
}
- /* if we weren't after a directory, have one more step to go */
- if (result != target_dir) {
- struct dentry *nresult;
- err = CALL(nops,get_name)(target_dir, nbuf, result);
+
+ return 0;
+}
+
+/**
+ * find_exported_dentry - helper routine to implement export_operations->decode_fh
+ * @sb: The &super_block identifying the filesystem
+ * @obj: An opaque identifier of the object to be found - passed to
+ * get_inode
+ * @parent: An optional opqaue identifier of the parent of the object.
+ * @acceptable: A function used to test possible &dentries to see if they are
+ * acceptable
+ * @context: A parameter to @acceptable so that it knows on what basis to
+ * judge.
+ *
+ * find_exported_dentry is the central helper routine to enable file systems
+ * to provide the decode_fh() export_operation. It's main task is to take
+ * an &inode, find or create an appropriate &dentry structure, and possibly
+ * splice this into the dcache in the correct place.
+ *
+ * The decode_fh() operation provided by the filesystem should call
+ * find_exported_dentry() with the same parameters that it received except
+ * that instead of the file handle fragment, pointers to opaque identifiers
+ * for the object and optionally its parent are passed. The default decode_fh
+ * routine passes one pointer to the start of the filehandle fragment, and
+ * one 8 bytes into the fragment. It is expected that most filesystems will
+ * take this approach, though the offset to the parent identifier may well be
+ * different.
+ *
+ * find_exported_dentry() will call get_dentry to get an dentry pointer from
+ * the file system. If any &dentry in the d_alias list is acceptable, it will
+ * be returned. Otherwise find_exported_dentry() will attempt to splice a new
+ * &dentry into the dcache using get_name() and get_parent() to find the
+ * appropriate place.
+ */
+
+struct dentry *
+find_exported_dentry(struct super_block *sb, void *obj, void *parent,
+ int (*acceptable)(void *context, struct dentry *de),
+ void *context)
+{
+ struct dentry *result, *alias;
+ int err = -ESTALE;
+
+ /*
+ * Attempt to find the inode.
+ */
+ result = exportfs_get_dentry(sb, obj);
+ if (IS_ERR(result))
+ return result;
+
+ if (S_ISDIR(result->d_inode->i_mode)) {
+ if (!(result->d_flags & DCACHE_DISCONNECTED)) {
+ if (acceptable(context, result))
+ return result;
+ err = -EACCES;
+ goto err_result;
+ }
+
+ err = reconnect_path(sb, result);
+ if (err)
+ goto err_result;
+ } else {
+ struct dentry *target_dir, *nresult;
+ char nbuf[NAME_MAX+1];
+
+ alias = find_acceptable_alias(result, acceptable, context);
+ if (alias)
+ return alias;
+
+ if (parent == NULL)
+ goto err_result;
+
+ target_dir = exportfs_get_dentry(sb,parent);
+ if (IS_ERR(target_dir)) {
+ err = PTR_ERR(target_dir);
+ goto err_result;
+ }
+
+ err = reconnect_path(sb, target_dir);
+ if (err) {
+ dput(target_dir);
+ goto err_result;
+ }
+
+ /*
+ * As we weren't after a directory, have one more step to go.
+ */
+ err = exportfs_get_name(target_dir, nbuf, result);
if (!err) {
mutex_lock(&target_dir->d_inode->i_mutex);
- nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
+ nresult = lookup_one_len(nbuf, target_dir,
+ strlen(nbuf));
mutex_unlock(&target_dir->d_inode->i_mutex);
if (!IS_ERR(nresult)) {
if (nresult->d_inode) {
@@ -261,11 +312,8 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
dput(nresult);
}
}
+ dput(target_dir);
}
- dput(target_dir);
- /* now result is properly connected, it is our best bet */
- if (acceptable(context, result))
- return result;
alias = find_acceptable_alias(result, acceptable, context);
if (alias)
@@ -275,32 +323,16 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
dput(result);
/* It might be justifiable to return ESTALE here,
* but the filehandle at-least looks reasonable good
- * and it just be a permission problem, so returning
+ * and it may just be a permission problem, so returning
* -EACCESS is safer
*/
return ERR_PTR(-EACCES);
- err_target:
- dput(target_dir);
err_result:
dput(result);
- err_out:
return ERR_PTR(err);
}
-
-
-static struct dentry *get_parent(struct dentry *child)
-{
- /* get_parent cannot be supported generically, the locking
- * is too icky.
- * instead, we just return EACCES. If server reboots or inodes
- * get flushed, you lose
- */
- return ERR_PTR(-EACCES);
-}
-
-
struct getdents_callback {
char *name; /* name that was found. It already points to a
buffer NAME_MAX+1 is size */
@@ -390,61 +422,6 @@ out:
return error;
}
-
-static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
-{
-
- /* iget isn't really right if the inode is currently unallocated!!
- * This should really all be done inside each filesystem
- *
- * ext2fs' read_inode has been strengthed to return a bad_inode if
- * the inode had been deleted.
- *
- * Currently we don't know the generation for parent directory, so
- * a generation of 0 means "accept any"
- */
- struct inode *inode;
- struct dentry *result;
- if (ino == 0)
- return ERR_PTR(-ESTALE);
- inode = iget(sb, ino);
- if (inode == NULL)
- return ERR_PTR(-ENOMEM);
- if (is_bad_inode(inode)
- || (generation && inode->i_generation != generation)
- ) {
- /* we didn't find the right inode.. */
- dprintk("fh_verify: Inode %lu, Bad count: %d %d or version %u %u\n",
- inode->i_ino,
- inode->i_nlink, atomic_read(&inode->i_count),
- inode->i_generation,
- generation);
-
- iput(inode);
- return ERR_PTR(-ESTALE);
- }
- /* now to find a dentry.
- * If possible, get a well-connected one
- */
- result = d_alloc_anon(inode);
- if (!result) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
- return result;
-}
-
-
-static struct dentry *get_object(struct super_block *sb, void *vobjp)
-{
- __u32 *objp = vobjp;
- unsigned long ino = objp[0];
- __u32 generation = objp[1];
-
- return export_iget(sb, ino, generation);
-}
-
-
/**
* export_encode_fh - default export_operations->encode_fh function
* @dentry: the dentry to encode
@@ -517,16 +494,40 @@ static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh
acceptable, context);
}
-struct export_operations export_op_default = {
- .decode_fh = export_decode_fh,
- .encode_fh = export_encode_fh,
+int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+ int connectable)
+{
+ struct export_operations *nop = dentry->d_sb->s_export_op;
+ int error;
+
+ if (nop->encode_fh)
+ error = nop->encode_fh(dentry, fh, max_len, connectable);
+ else
+ error = export_encode_fh(dentry, fh, max_len, connectable);
- .get_name = get_name,
- .get_parent = get_parent,
- .get_dentry = get_object,
-};
+ return error;
+}
+EXPORT_SYMBOL_GPL(exportfs_encode_fh);
+
+struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len,
+ int fileid_type, int (*acceptable)(void *, struct dentry *),
+ void *context)
+{
+ struct export_operations *nop = mnt->mnt_sb->s_export_op;
+ struct dentry *result;
+
+ if (nop->decode_fh) {
+ result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
+ acceptable, context);
+ } else {
+ result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
+ acceptable, context);
+ }
+
+ return result;
+}
+EXPORT_SYMBOL_GPL(exportfs_decode_fh);
-EXPORT_SYMBOL(export_op_default);
EXPORT_SYMBOL(find_exported_dentry);
MODULE_LICENSE("GPL");
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 7c420b800c34..e58669e1b87c 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -464,7 +464,7 @@ ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
if (!test_opt(inode->i_sb, POSIX_ACL))
return -EOPNOTSUPP;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (value) {
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 04afeecaaef3..ab7961260c49 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -24,9 +24,9 @@
#include "acl.h"
/*
- * Called when an inode is released. Note that this is different
- * from ext2_open_file: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
+ * Called when filp is released. This happens when all file descriptors
+ * for a single struct file are closed. Note that different open() calls
+ * for the same file yield different struct file structures.
*/
static int ext2_release_file (struct inode * inode, struct file * filp)
{
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index e85c48218239..3bcd25422ee4 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -36,7 +36,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(flags, (int __user *) arg))
@@ -74,7 +74,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
case EXT2_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *) arg);
case EXT2_IOC_SETVERSION:
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (IS_RDONLY(inode))
return -EROFS;
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 5de5061eb331..3eefa97fe204 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -25,6 +25,7 @@
#include <linux/parser.h>
#include <linux/random.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/smp_lock.h>
#include <linux/vfs.h>
#include <linux/seq_file.h>
@@ -1099,15 +1100,18 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
struct super_block *sb = dentry->d_sb;
struct ext2_sb_info *sbi = EXT2_SB(sb);
struct ext2_super_block *es = sbi->s_es;
- unsigned long overhead;
- int i;
u64 fsid;
if (test_opt (sb, MINIX_DF))
- overhead = 0;
- else {
+ sbi->s_overhead_last = 0;
+ else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+ unsigned long i, overhead = 0;
+ smp_rmb();
+
/*
- * Compute the overhead (FS structures)
+ * Compute the overhead (FS structures). This is constant
+ * for a given filesystem unless the number of block groups
+ * changes so we cache the previous value until it does.
*/
/*
@@ -1131,17 +1135,22 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
*/
overhead += (sbi->s_groups_count *
(2 + sbi->s_itb_per_group));
+ sbi->s_overhead_last = overhead;
+ smp_wmb();
+ sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
}
buf->f_type = EXT2_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+ buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
buf->f_bfree = ext2_count_free_blocks(sb);
+ es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
buf->f_bavail = 0;
buf->f_files = le32_to_cpu(es->s_inodes_count);
buf->f_ffree = ext2_count_free_inodes(sb);
+ es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
buf->f_namelen = EXT2_NAME_LEN;
fsid = le64_to_cpup((void *)es->s_uuid) ^
le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 1e5038d9a01b..d34e9967430a 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -489,7 +489,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
if (!test_opt(inode->i_sb, POSIX_ACL))
return -EOPNOTSUPP;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (value) {
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2a85ddee4740..de4e3161e479 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -3195,7 +3195,7 @@ int ext3_change_inode_journal_flag(struct inode *inode, int val)
*/
journal = EXT3_JOURNAL(inode);
- if (is_journal_aborted(journal) || IS_RDONLY(inode))
+ if (is_journal_aborted(journal))
return -EROFS;
journal_lock_updates(journal);
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 965006dba6be..4a2a02c95bf9 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -41,7 +41,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(flags, (int __user *) arg))
@@ -122,7 +122,7 @@ flags_err:
__u32 generation;
int err;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (IS_RDONLY(inode))
return -EROFS;
@@ -181,7 +181,7 @@ flags_err:
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(rsv_window_size, (int __user *)arg))
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 9bb046df827a..1586807b8177 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1019,6 +1019,11 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
if (!inode)
return ERR_PTR(-EACCES);
+
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ return ERR_PTR(-ENOENT);
+ }
}
return d_splice_alias(inode, dentry);
}
@@ -1054,6 +1059,11 @@ struct dentry *ext3_get_parent(struct dentry *child)
if (!inode)
return ERR_PTR(-EACCES);
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ return ERR_PTR(-ENOENT);
+ }
+
parent = d_alloc_anon(inode);
if (!parent) {
iput(inode);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 6e3062913a92..4f84dc86628a 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -29,12 +29,14 @@
#include <linux/parser.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/vfs.h>
#include <linux/random.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/quotaops.h>
#include <linux/seq_file.h>
+#include <linux/log2.h>
#include <asm/uaccess.h>
@@ -459,6 +461,14 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
static void ext3_destroy_inode(struct inode *inode)
{
+ if (!list_empty(&(EXT3_I(inode)->i_orphan))) {
+ printk("EXT3 Inode %p: orphan list check failed!\n",
+ EXT3_I(inode));
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+ EXT3_I(inode), sizeof(struct ext3_inode_info),
+ false);
+ dump_stack();
+ }
kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
}
@@ -1566,7 +1576,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
- (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
+ (!is_power_of_2(sbi->s_inode_size)) ||
(sbi->s_inode_size > blocksize)) {
printk (KERN_ERR
"EXT3-fs: unsupported inode size: %d\n",
@@ -2075,6 +2085,7 @@ static int ext3_create_journal(struct super_block * sb,
unsigned int journal_inum)
{
journal_t *journal;
+ int err;
if (sb->s_flags & MS_RDONLY) {
printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to "
@@ -2082,13 +2093,15 @@ static int ext3_create_journal(struct super_block * sb,
return -EROFS;
}
- if (!(journal = ext3_get_journal(sb, journal_inum)))
+ journal = ext3_get_journal(sb, journal_inum);
+ if (!journal)
return -EINVAL;
printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
journal_inum);
- if (journal_create(journal)) {
+ err = journal_create(journal);
+ if (err) {
printk(KERN_ERR "EXT3-fs: error creating journal.\n");
journal_destroy(journal);
return -EIO;
@@ -2139,12 +2152,14 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
journal_lock_updates(journal);
journal_flush(journal);
+ lock_super(sb);
if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
sb->s_flags & MS_RDONLY) {
EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
sb->s_dirt = 0;
ext3_commit_super(sb, es, 1);
}
+ unlock_super(sb);
journal_unlock_updates(journal);
}
@@ -2333,7 +2348,13 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
(sbi->s_mount_state & EXT3_VALID_FS))
es->s_state = cpu_to_le16(sbi->s_mount_state);
+ /*
+ * We have to unlock super so that we can wait for
+ * transactions.
+ */
+ unlock_super(sb);
ext3_mark_recovery_complete(sb, es);
+ lock_super(sb);
} else {
__le32 ret;
if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
@@ -2406,19 +2427,19 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
struct super_block *sb = dentry->d_sb;
struct ext3_sb_info *sbi = EXT3_SB(sb);
struct ext3_super_block *es = sbi->s_es;
- ext3_fsblk_t overhead;
- int i;
u64 fsid;
- if (test_opt (sb, MINIX_DF))
- overhead = 0;
- else {
- unsigned long ngroups;
- ngroups = EXT3_SB(sb)->s_groups_count;
+ if (test_opt(sb, MINIX_DF)) {
+ sbi->s_overhead_last = 0;
+ } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+ unsigned long ngroups = sbi->s_groups_count, i;
+ ext3_fsblk_t overhead = 0;
smp_rmb();
/*
- * Compute the overhead (FS structures)
+ * Compute the overhead (FS structures). This is constant
+ * for a given filesystem unless the number of block groups
+ * changes so we cache the previous value until it does.
*/
/*
@@ -2442,18 +2463,23 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
* Every block group has an inode bitmap, a block
* bitmap, and an inode table.
*/
- overhead += (ngroups * (2 + EXT3_SB(sb)->s_itb_per_group));
+ overhead += ngroups * (2 + sbi->s_itb_per_group);
+ sbi->s_overhead_last = overhead;
+ smp_wmb();
+ sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
}
buf->f_type = EXT3_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+ buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+ es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
buf->f_bavail = 0;
buf->f_files = le32_to_cpu(es->s_inodes_count);
buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+ es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
buf->f_namelen = EXT3_NAME_LEN;
fsid = le64_to_cpup((void *)es->s_uuid) ^
le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 9e882546d91a..a8bae8cd1d5d 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -489,7 +489,7 @@ ext4_xattr_set_acl(struct inode *inode, int type, const void *value,
if (!test_opt(inode->i_sb, POSIX_ACL))
return -EOPNOTSUPP;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (value) {
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 3b64bb16c727..9de54ae48dee 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1585,7 +1585,7 @@ allocated:
ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
- in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+ in_range(ext4_inode_bitmap(sb, gdp), ret_block, num) ||
in_range(ret_block, ext4_inode_table(sb, gdp),
EXT4_SB(sb)->s_itb_per_group) ||
in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 500567dd53b6..7b4aa4543c83 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -40,7 +40,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(flags, (int __user *) arg))
@@ -121,7 +121,7 @@ flags_err:
__u32 generation;
int err;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (IS_RDONLY(inode))
return -EROFS;
@@ -180,7 +180,7 @@ flags_err:
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(rsv_window_size, (int __user *)arg))
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 2811e5720ad0..2de339dd7554 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1017,6 +1017,11 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str
if (!inode)
return ERR_PTR(-EACCES);
+
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ return ERR_PTR(-ENOENT);
+ }
}
return d_splice_alias(inode, dentry);
}
@@ -1052,6 +1057,11 @@ struct dentry *ext4_get_parent(struct dentry *child)
if (!inode)
return ERR_PTR(-EACCES);
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ return ERR_PTR(-ENOENT);
+ }
+
parent = d_alloc_anon(inode);
if (!parent) {
iput(inode);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 175b68c60968..b806e689c4aa 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -29,6 +29,7 @@
#include <linux/parser.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/vfs.h>
#include <linux/random.h>
#include <linux/mount.h>
@@ -510,6 +511,14 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
static void ext4_destroy_inode(struct inode *inode)
{
+ if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
+ printk("EXT4 Inode %p: orphan list check failed!\n",
+ EXT4_I(inode));
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+ EXT4_I(inode), sizeof(struct ext4_inode_info),
+ true);
+ dump_stack();
+ }
kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
}
@@ -2150,6 +2159,7 @@ static int ext4_create_journal(struct super_block * sb,
unsigned int journal_inum)
{
journal_t *journal;
+ int err;
if (sb->s_flags & MS_RDONLY) {
printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to "
@@ -2157,13 +2167,15 @@ static int ext4_create_journal(struct super_block * sb,
return -EROFS;
}
- if (!(journal = ext4_get_journal(sb, journal_inum)))
+ journal = ext4_get_journal(sb, journal_inum);
+ if (!journal)
return -EINVAL;
printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n",
journal_inum);
- if (jbd2_journal_create(journal)) {
+ err = jbd2_journal_create(journal);
+ if (err) {
printk(KERN_ERR "EXT4-fs: error creating journal.\n");
jbd2_journal_destroy(journal);
return -EIO;
@@ -2214,12 +2226,14 @@ static void ext4_mark_recovery_complete(struct super_block * sb,
jbd2_journal_lock_updates(journal);
jbd2_journal_flush(journal);
+ lock_super(sb);
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
sb->s_flags & MS_RDONLY) {
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
sb->s_dirt = 0;
ext4_commit_super(sb, es, 1);
}
+ unlock_super(sb);
jbd2_journal_unlock_updates(journal);
}
@@ -2408,7 +2422,13 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
(sbi->s_mount_state & EXT4_VALID_FS))
es->s_state = cpu_to_le16(sbi->s_mount_state);
+ /*
+ * We have to unlock super so that we can wait for
+ * transactions.
+ */
+ unlock_super(sb);
ext4_mark_recovery_complete(sb, es);
+ lock_super(sb);
} else {
__le32 ret;
if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -2481,19 +2501,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
struct super_block *sb = dentry->d_sb;
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_super_block *es = sbi->s_es;
- ext4_fsblk_t overhead;
- int i;
u64 fsid;
- if (test_opt (sb, MINIX_DF))
- overhead = 0;
- else {
- unsigned long ngroups;
- ngroups = EXT4_SB(sb)->s_groups_count;
+ if (test_opt(sb, MINIX_DF)) {
+ sbi->s_overhead_last = 0;
+ } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+ unsigned long ngroups = sbi->s_groups_count, i;
+ ext4_fsblk_t overhead = 0;
smp_rmb();
/*
- * Compute the overhead (FS structures)
+ * Compute the overhead (FS structures). This is constant
+ * for a given filesystem unless the number of block groups
+ * changes so we cache the previous value until it does.
*/
/*
@@ -2517,18 +2537,23 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
* Every block group has an inode bitmap, a block
* bitmap, and an inode table.
*/
- overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group));
+ overhead += ngroups * (2 + sbi->s_itb_per_group);
+ sbi->s_overhead_last = overhead;
+ smp_wmb();
+ sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
}
buf->f_type = EXT4_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = ext4_blocks_count(es) - overhead;
+ buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
+ es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
if (buf->f_bfree < ext4_r_blocks_count(es))
buf->f_bavail = 0;
buf->f_files = le32_to_cpu(es->s_inodes_count);
buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
+ es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
buf->f_namelen = EXT4_NAME_LEN;
fsid = le64_to_cpup((void *)es->s_uuid) ^
le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index ccf161dffb63..72cbcd61bd95 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -313,7 +313,7 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
wchar_t bufuname[14];
unsigned char xlate_len, nr_slots;
wchar_t *unicode = NULL;
- unsigned char work[8], bufname[260]; /* 256 + 4 */
+ unsigned char work[MSDOS_NAME], bufname[260]; /* 256 + 4 */
int uni_xlate = sbi->options.unicode_xlate;
int utf8 = sbi->options.utf8;
int anycase = (sbi->options.name_check != 's');
@@ -351,7 +351,8 @@ parse_record:
if (work[0] == 0x05)
work[0] = 0xE5;
for (i = 0, j = 0, last_u = 0; i < 8;) {
- if (!work[i]) break;
+ if (!work[i])
+ break;
chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
&bufuname[j++], opt_shortname,
de->lcase & CASE_LOWER_BASE);
@@ -365,13 +366,15 @@ parse_record:
}
j = last_u;
fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
- for (i = 0; i < 3;) {
- if (!de->ext[i]) break;
- chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i,
+ for (i = 8; i < MSDOS_NAME;) {
+ if (!work[i])
+ break;
+ chl = fat_shortname2uni(nls_disk, &work[i],
+ MSDOS_NAME - i,
&bufuname[j++], opt_shortname,
de->lcase & CASE_LOWER_EXT);
if (chl <= 1) {
- if (de->ext[i] != ' ')
+ if (work[i] != ' ')
last_u = j;
} else {
last_u = j;
@@ -445,7 +448,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
int fill_len;
wchar_t bufuname[14];
wchar_t *unicode = NULL;
- unsigned char c, work[8], bufname[56], *ptname = bufname;
+ unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname;
unsigned long lpos, dummy, *furrfu = &lpos;
int uni_xlate = sbi->options.unicode_xlate;
int isvfat = sbi->options.isvfat;
@@ -527,7 +530,8 @@ parse_record:
if (work[0] == 0x05)
work[0] = 0xE5;
for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {
- if (!(c = work[i])) break;
+ if (!(c = work[i]))
+ break;
chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
&bufuname[j++], opt_shortname,
de->lcase & CASE_LOWER_BASE);
@@ -549,9 +553,10 @@ parse_record:
j = last_u;
fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
ptname[i++] = '.';
- for (i2 = 0; i2 < 3;) {
- if (!(c = de->ext[i2])) break;
- chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2,
+ for (i2 = 8; i2 < MSDOS_NAME;) {
+ if (!(c = work[i2]))
+ break;
+ chl = fat_shortname2uni(nls_disk, &work[i2], MSDOS_NAME - i2,
&bufuname[j++], opt_shortname,
de->lcase & CASE_LOWER_EXT);
if (chl <= 1) {
@@ -563,8 +568,8 @@ parse_record:
}
} else {
last_u = j;
- for (chi = 0; chi < chl && i2 < 3; chi++) {
- ptname[i++] = de->ext[i2++];
+ for (chi = 0; chi < chl && i2 < MSDOS_NAME; chi++) {
+ ptname[i++] = work[i2++];
last = i;
}
}
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index ab171ea8e869..2c1b73fb82ae 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -17,6 +17,8 @@ struct fatent_operations {
int (*ent_next)(struct fat_entry *);
};
+static DEFINE_SPINLOCK(fat12_entry_lock);
+
static void fat12_ent_blocknr(struct super_block *sb, int entry,
int *offset, sector_t *blocknr)
{
@@ -116,10 +118,13 @@ static int fat12_ent_get(struct fat_entry *fatent)
u8 **ent12_p = fatent->u.ent12_p;
int next;
+ spin_lock(&fat12_entry_lock);
if (fatent->entry & 1)
next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
else
next = (*ent12_p[1] << 8) | *ent12_p[0];
+ spin_unlock(&fat12_entry_lock);
+
next &= 0x0fff;
if (next >= BAD_FAT12)
next = FAT_ENT_EOF;
@@ -151,6 +156,7 @@ static void fat12_ent_put(struct fat_entry *fatent, int new)
if (new == FAT_ENT_EOF)
new = EOF_FAT12;
+ spin_lock(&fat12_entry_lock);
if (fatent->entry & 1) {
*ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
*ent12_p[1] = new >> 4;
@@ -158,6 +164,7 @@ static void fat12_ent_put(struct fat_entry *fatent, int new)
*ent12_p[0] = new & 0xff;
*ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
}
+ spin_unlock(&fat12_entry_lock);
mark_buffer_dirty(fatent->bhs[0]);
if (fatent->nr_bhs == 2)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 479722d89667..0a7ddb39a593 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -20,6 +20,7 @@
#include <linux/pagemap.h>
#include <linux/mpage.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/parser.h>
@@ -354,8 +355,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
} else { /* not a directory */
inode->i_generation |= 1;
inode->i_mode = MSDOS_MKMODE(de->attr,
- ((sbi->options.showexec &&
- !is_exec(de->ext))
+ ((sbi->options.showexec && !is_exec(de->name + 8))
? S_IRUGO|S_IWUGO : S_IRWXUGO)
& ~sbi->options.fs_fmask) | S_IFREG;
MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 8e382a5d51bd..3f22e9f4f691 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -215,7 +215,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
/* O_NOATIME can only be set by the owner or superuser */
if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME))
- if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
/* required for strict SunOS emulation */
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index 8a4dfef1ddad..3c96d6e63978 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -80,7 +80,7 @@ struct vxfs_direct {
* a d_name with size len.
*/
#define VXFS_DIRPAD 4
-#define VXFS_NAMEMIN ((int)((struct vxfs_direct *)0)->d_name)
+#define VXFS_NAMEMIN offsetof(struct vxfs_direct, d_name)
#define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
#define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 9ccb78947171..995d63b2e747 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -78,7 +78,7 @@ generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
- if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (value) {
acl = posix_acl_from_xattr(value, size);
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 6e80844367ee..1047a8c7226a 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -74,7 +74,7 @@ int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
{
if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
return -EOPNOTSUPP;
- if (current->fsuid != ip->i_inode.i_uid && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(&ip->i_inode))
return -EPERM;
if (S_ISLNK(ip->i_inode.i_mode))
return -EOPNOTSUPP;
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c
index c1f44009853f..1ab3e9d73886 100644
--- a/fs/gfs2/eaops.c
+++ b/fs/gfs2/eaops.c
@@ -11,6 +11,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
+#include <linux/capability.h>
#include <linux/xattr.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index 99ea5659bc2c..b8312edee0e4 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -11,6 +11,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <linux/lm_interface.h>
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 90ebab753d30..050d29c0a5b5 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -62,8 +62,10 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
(head->key_type == HFSPLUS_KEY_BINARY))
tree->keycmp = hfsplus_cat_bin_cmp_key;
- else
+ else {
tree->keycmp = hfsplus_cat_case_cmp_key;
+ HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
+ }
} else {
printk(KERN_ERR "hfs: unknown B*Tree requested\n");
goto fail_page;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 80b5682a2273..1955ee61251c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -36,6 +36,8 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
u16 type;
sb = dir->i_sb;
+
+ dentry->d_op = &hfsplus_dentry_operations;
dentry->d_fsdata = NULL;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 3915635b4470..d9f5eda6d039 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -150,6 +150,7 @@ struct hfsplus_sb_info {
#define HFSPLUS_SB_NODECOMPOSE 0x0002
#define HFSPLUS_SB_FORCE 0x0004
#define HFSPLUS_SB_HFSX 0x0008
+#define HFSPLUS_SB_CASEFOLD 0x0010
struct hfsplus_inode_info {
@@ -321,6 +322,7 @@ void hfsplus_file_truncate(struct inode *);
/* inode.c */
extern const struct address_space_operations hfsplus_aops;
extern const struct address_space_operations hfsplus_btree_aops;
+extern struct dentry_operations hfsplus_dentry_operations;
void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
@@ -353,6 +355,8 @@ int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unist
int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
+int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str);
+int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2);
/* wrapper.c */
int hfsplus_read_wrapper(struct super_block *);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 409ce5429c91..6f7c662174db 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -131,6 +131,11 @@ const struct address_space_operations hfsplus_aops = {
.writepages = hfsplus_writepages,
};
+struct dentry_operations hfsplus_dentry_operations = {
+ .d_hash = hfsplus_hash_dentry,
+ .d_compare = hfsplus_compare_dentry,
+};
+
static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index 79fd10402ea3..b60c0affbec5 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -38,7 +38,7 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(flags, (int __user *)arg))
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index ebd1b380cbbc..6d87a2a9534d 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -283,11 +283,10 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
struct nls_table *nls = NULL;
int err = -EINVAL;
- sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL);
+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
- memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
sb->s_fs_info = sbi;
INIT_HLIST_HEAD(&sbi->rsrc_inodes);
hfsplus_fill_defaults(sbi);
@@ -381,6 +380,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
iput(root);
goto cleanup;
}
+ sb->s_root->d_op = &hfsplus_dentry_operations;
str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
str.name = HFSP_HIDDENDIR_NAME;
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 689c8bd721fb..9e10f9444b64 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -239,61 +239,201 @@ out:
return res;
}
-int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len)
+/*
+ * Convert one or more ASCII characters into a single unicode character.
+ * Returns the number of ASCII characters corresponding to the unicode char.
+ */
+static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
+ wchar_t *uc)
{
- struct nls_table *nls = HFSPLUS_SB(sb).nls;
- int size, off, decompose;
+ int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc);
+ if (size <= 0) {
+ *uc = '?';
+ size = 1;
+ }
+ switch (*uc) {
+ case 0x2400:
+ *uc = 0;
+ break;
+ case ':':
+ *uc = '/';
+ break;
+ }
+ return size;
+}
+
+/* Decomposes a single unicode character. */
+static inline u16 *decompose_unichar(wchar_t uc, int *size)
+{
+ int off;
+
+ off = hfsplus_decompose_table[(uc >> 12) & 0xf];
+ if (off == 0 || off == 0xffff)
+ return NULL;
+
+ off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
+ if (!off)
+ return NULL;
+
+ off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
+ if (!off)
+ return NULL;
+
+ off = hfsplus_decompose_table[off + (uc & 0xf)];
+ *size = off & 3;
+ if (*size == 0)
+ return NULL;
+ return hfsplus_decompose_table + (off / 4);
+}
+
+int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
+ const char *astr, int len)
+{
+ int size, dsize, decompose;
+ u16 *dstr, outlen = 0;
wchar_t c;
- u16 outlen = 0;
decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
-
while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
- size = nls->char2uni(astr, len, &c);
- if (size <= 0) {
- c = '?';
- size = 1;
- }
- astr += size;
- len -= size;
- switch (c) {
- case 0x2400:
- c = 0;
- break;
- case ':':
- c = '/';
- break;
- }
- if (c >= 0xc0 && decompose) {
- off = hfsplus_decompose_table[(c >> 12) & 0xf];
- if (!off)
- goto done;
- if (off == 0xffff) {
- goto done;
- }
- off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)];
- if (!off)
- goto done;
- off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)];
- if (!off)
- goto done;
- off = hfsplus_decompose_table[off + (c & 0xf)];
- size = off & 3;
- if (!size)
- goto done;
- off /= 4;
- if (outlen + size > HFSPLUS_MAX_STRLEN)
+ size = asc2unichar(sb, astr, len, &c);
+
+ if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+ if (outlen + dsize > HFSPLUS_MAX_STRLEN)
break;
do {
- ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]);
- } while (--size > 0);
- continue;
- }
- done:
- ustr->unicode[outlen++] = cpu_to_be16(c);
+ ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
+ } while (--dsize > 0);
+ } else
+ ustr->unicode[outlen++] = cpu_to_be16(c);
+
+ astr += size;
+ len -= size;
}
ustr->length = cpu_to_be16(outlen);
if (len > 0)
return -ENAMETOOLONG;
return 0;
}
+
+/*
+ * Hash a string to an integer as appropriate for the HFS+ filesystem.
+ * Composed unicode characters are decomposed and case-folding is performed
+ * if the appropriate bits are (un)set on the superblock.
+ */
+int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
+{
+ struct super_block *sb = dentry->d_sb;
+ const char *astr;
+ const u16 *dstr;
+ int casefold, decompose, size, dsize, len;
+ unsigned long hash;
+ wchar_t c;
+ u16 c2;
+
+ casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
+ decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+ hash = init_name_hash();
+ astr = str->name;
+ len = str->len;
+ while (len > 0) {
+ size = asc2unichar(sb, astr, len, &c);
+ astr += size;
+ len -= size;
+
+ if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+ do {
+ c2 = *dstr++;
+ if (!casefold || (c2 = case_fold(c2)))
+ hash = partial_name_hash(c2, hash);
+ } while (--dsize > 0);
+ } else {
+ c2 = c;
+ if (!casefold || (c2 = case_fold(c2)))
+ hash = partial_name_hash(c2, hash);
+ }
+ }
+ str->hash = end_name_hash(hash);
+
+ return 0;
+}
+
+/*
+ * Compare strings with HFS+ filename ordering.
+ * Composed unicode characters are decomposed and case-folding is performed
+ * if the appropriate bits are (un)set on the superblock.
+ */
+int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2)
+{
+ struct super_block *sb = dentry->d_sb;
+ int casefold, decompose, size;
+ int dsize1, dsize2, len1, len2;
+ const u16 *dstr1, *dstr2;
+ const char *astr1, *astr2;
+ u16 c1, c2;
+ wchar_t c;
+
+ casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
+ decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+ astr1 = s1->name;
+ len1 = s1->len;
+ astr2 = s2->name;
+ len2 = s2->len;
+ dsize1 = dsize2 = 0;
+ dstr1 = dstr2 = NULL;
+
+ while (len1 > 0 && len2 > 0) {
+ if (!dsize1) {
+ size = asc2unichar(sb, astr1, len1, &c);
+ astr1 += size;
+ len1 -= size;
+
+ if (!decompose || !(dstr1 = decompose_unichar(c, &dsize1))) {
+ c1 = c;
+ dstr1 = &c1;
+ dsize1 = 1;
+ }
+ }
+
+ if (!dsize2) {
+ size = asc2unichar(sb, astr2, len2, &c);
+ astr2 += size;
+ len2 -= size;
+
+ if (!decompose || !(dstr2 = decompose_unichar(c, &dsize2))) {
+ c2 = c;
+ dstr2 = &c2;
+ dsize2 = 1;
+ }
+ }
+
+ c1 = *dstr1;
+ c2 = *dstr2;
+ if (casefold) {
+ if (!(c1 = case_fold(c1))) {
+ dstr1++;
+ dsize1--;
+ continue;
+ }
+ if (!(c2 = case_fold(c2))) {
+ dstr2++;
+ dsize2--;
+ continue;
+ }
+ }
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+
+ dstr1++;
+ dsize1--;
+ dstr2++;
+ dsize2--;
+ }
+
+ if (len1 < len2)
+ return -1;
+ if (len1 > len2)
+ return 1;
+ return 0;
+}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e6b46b3ac2fe..d145cb79c30a 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -13,15 +13,18 @@
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/file.h>
+#include <linux/kernel.h>
#include <linux/writeback.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/capability.h>
+#include <linux/ctype.h>
#include <linux/backing-dev.h>
#include <linux/hugetlb.h>
#include <linux/pagevec.h>
+#include <linux/parser.h>
#include <linux/mman.h>
#include <linux/quotaops.h>
#include <linux/slab.h>
@@ -47,6 +50,21 @@ static struct backing_dev_info hugetlbfs_backing_dev_info = {
int sysctl_hugetlb_shm_group;
+enum {
+ Opt_size, Opt_nr_inodes,
+ Opt_mode, Opt_uid, Opt_gid,
+ Opt_err,
+};
+
+static match_table_t tokens = {
+ {Opt_size, "size=%s"},
+ {Opt_nr_inodes, "nr_inodes=%s"},
+ {Opt_mode, "mode=%o"},
+ {Opt_uid, "uid=%u"},
+ {Opt_gid, "gid=%u"},
+ {Opt_err, NULL},
+};
+
static void huge_pagevec_release(struct pagevec *pvec)
{
int i;
@@ -594,46 +612,73 @@ static const struct super_operations hugetlbfs_ops = {
static int
hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
{
- char *opt, *value, *rest;
+ char *p, *rest;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
if (!options)
return 0;
- while ((opt = strsep(&options, ",")) != NULL) {
- if (!*opt)
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ if (!*p)
continue;
- value = strchr(opt, '=');
- if (!value || !*value)
- return -EINVAL;
- else
- *value++ = '\0';
-
- if (!strcmp(opt, "uid"))
- pconfig->uid = simple_strtoul(value, &value, 0);
- else if (!strcmp(opt, "gid"))
- pconfig->gid = simple_strtoul(value, &value, 0);
- else if (!strcmp(opt, "mode"))
- pconfig->mode = simple_strtoul(value,&value,0) & 0777U;
- else if (!strcmp(opt, "size")) {
- unsigned long long size = memparse(value, &rest);
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case Opt_uid:
+ if (match_int(&args[0], &option))
+ goto bad_val;
+ pconfig->uid = option;
+ break;
+
+ case Opt_gid:
+ if (match_int(&args[0], &option))
+ goto bad_val;
+ pconfig->gid = option;
+ break;
+
+ case Opt_mode:
+ if (match_octal(&args[0], &option))
+ goto bad_val;
+ pconfig->mode = option & 0777U;
+ break;
+
+ case Opt_size: {
+ unsigned long long size;
+ /* memparse() will accept a K/M/G without a digit */
+ if (!isdigit(*args[0].from))
+ goto bad_val;
+ size = memparse(args[0].from, &rest);
if (*rest == '%') {
size <<= HPAGE_SHIFT;
size *= max_huge_pages;
do_div(size, 100);
- rest++;
}
pconfig->nr_blocks = (size >> HPAGE_SHIFT);
- value = rest;
- } else if (!strcmp(opt,"nr_inodes")) {
- pconfig->nr_inodes = memparse(value, &rest);
- value = rest;
- } else
- return -EINVAL;
+ break;
+ }
+
+ case Opt_nr_inodes:
+ /* memparse() will accept a K/M/G without a digit */
+ if (!isdigit(*args[0].from))
+ goto bad_val;
+ pconfig->nr_inodes = memparse(args[0].from, &rest);
+ break;
- if (*value)
+ default:
+ printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
+ p);
return -EINVAL;
+ break;
+ }
}
return 0;
+
+bad_val:
+ printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
+ args[0].from, p);
+ return 1;
}
static int
@@ -651,7 +696,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
config.gid = current->fsgid;
config.mode = 0755;
ret = hugetlbfs_parse_options(data, &config);
-
if (ret)
return ret;
diff --git a/fs/inode.c b/fs/inode.c
index 9a012cc5b6cd..320e088d0b28 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -145,7 +145,7 @@ static struct inode *alloc_inode(struct super_block *sb)
mapping->a_ops = &empty_aops;
mapping->host = inode;
mapping->flags = 0;
- mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+ mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE);
mapping->assoc_mapping = NULL;
mapping->backing_dev_info = &default_backing_dev_info;
@@ -462,6 +462,11 @@ static int shrink_icache_memory(int nr, gfp_t gfp_mask)
return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
}
+static struct shrinker icache_shrinker = {
+ .shrink = shrink_icache_memory,
+ .seeks = DEFAULT_SEEKS,
+};
+
static void __wait_on_freeing_inode(struct inode *inode);
/*
* Called with the inode lock held.
@@ -519,7 +524,13 @@ repeat:
* new_inode - obtain an inode
* @sb: superblock
*
- * Allocates a new inode for given superblock.
+ * Allocates a new inode for given superblock. The default gfp_mask
+ * for allocations related to inode->i_mapping is GFP_HIGHUSER_PAGECACHE.
+ * If HIGHMEM pages are unsuitable or it is known that pages allocated
+ * for the page cache are not reclaimable or migratable,
+ * mapping_set_gfp_mask() must be called with suitable flags on the
+ * newly created inode's mapping
+ *
*/
struct inode *new_inode(struct super_block *sb)
{
@@ -1379,7 +1390,7 @@ void __init inode_init(unsigned long mempages)
SLAB_MEM_SPREAD),
init_once,
NULL);
- set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
+ register_shrinker(&icache_shrinker);
/* Hash may have been set up in inode_init_early */
if (!hashdist)
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 8c90cbc903fa..c2a773e8620b 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -12,7 +12,6 @@
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/module.h>
-#include <linux/kallsyms.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -21,7 +20,6 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int error = -ENOTTY;
- void *f;
if (!filp->f_op)
goto out;
@@ -31,16 +29,10 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
if (error == -ENOIOCTLCMD)
error = -EINVAL;
goto out;
- } else if ((f = filp->f_op->ioctl)) {
+ } else if (filp->f_op->ioctl) {
lock_kernel();
- if (!filp->f_op->ioctl) {
- printk("%s: ioctl %p disappeared\n", __FUNCTION__, f);
- print_symbol("symbol: %s\n", (unsigned long)f);
- dump_stack();
- } else {
- error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
- filp, cmd, arg);
- }
+ error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
+ filp, cmd, arg);
unlock_kernel();
}
@@ -182,11 +174,3 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
out:
return error;
}
-
-/*
- * Platforms implementing 32 bit compatibility ioctl handlers in
- * modules need this exported
- */
-#ifdef CONFIG_COMPAT
-EXPORT_SYMBOL(sys_ioctl);
-#endif
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 0e94c31cad9b..1ba407c64df1 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -7,34 +7,18 @@
*
* Steve Beynon : Missing last directory entries fixed
* (stephen@askone.demon.co.uk) : 21st June 1996
- *
+ *
* isofs directory handling functions
*/
#include <linux/smp_lock.h>
#include "isofs.h"
-static int isofs_readdir(struct file *, void *, filldir_t);
-
-const struct file_operations isofs_dir_operations =
-{
- .read = generic_read_dir,
- .readdir = isofs_readdir,
-};
-
-/*
- * directories can handle most operations...
- */
-const struct inode_operations isofs_dir_inode_operations =
-{
- .lookup = isofs_lookup,
-};
-
int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode)
{
char * old = de->name;
int len = de->name_len[0];
int i;
-
+
for (i = 0; i < len; i++) {
unsigned char c = old[i];
if (!c)
@@ -62,22 +46,27 @@ int isofs_name_translate(struct iso_directory_record *de, char *new, struct inod
}
/* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */
-int get_acorn_filename(struct iso_directory_record * de,
- char * retname, struct inode * inode)
+int get_acorn_filename(struct iso_directory_record *de,
+ char *retname, struct inode *inode)
{
int std;
- unsigned char * chr;
+ unsigned char *chr;
int retnamlen = isofs_name_translate(de, retname, inode);
- if (retnamlen == 0) return 0;
+
+ if (retnamlen == 0)
+ return 0;
std = sizeof(struct iso_directory_record) + de->name_len[0];
- if (std & 1) std++;
- if ((*((unsigned char *) de) - std) != 32) return retnamlen;
+ if (std & 1)
+ std++;
+ if ((*((unsigned char *) de) - std) != 32)
+ return retnamlen;
chr = ((unsigned char *) de) + std;
- if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen;
- if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!';
+ if (strncmp(chr, "ARCHIMEDES", 10))
+ return retnamlen;
+ if ((*retname == '_') && ((chr[19] & 1) == 1))
+ *retname = '!';
if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff)
- && ((chr[12] & 0xf0) == 0xf0))
- {
+ && ((chr[12] & 0xf0) == 0xf0)) {
retname[retnamlen] = ',';
sprintf(retname+retnamlen+1, "%3.3x",
((chr[12] & 0xf) << 8) | chr[11]);
@@ -91,7 +80,7 @@ int get_acorn_filename(struct iso_directory_record * de,
*/
static int do_isofs_readdir(struct inode *inode, struct file *filp,
void *dirent, filldir_t filldir,
- char * tmpname, struct iso_directory_record * tmpde)
+ char *tmpname, struct iso_directory_record *tmpde)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
@@ -121,9 +110,11 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
de_len = *(unsigned char *) de;
- /* If the length byte is zero, we should move on to the next
- CDROM sector. If we are at the end of the directory, we
- kick out of the while loop. */
+ /*
+ * If the length byte is zero, we should move on to the next
+ * CDROM sector. If we are at the end of the directory, we
+ * kick out of the while loop.
+ */
if (de_len == 0) {
brelse(bh);
@@ -157,11 +148,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
if (first_de) {
isofs_normalize_block_and_offset(de,
- &block_saved,
- &offset_saved);
+ &block_saved,
+ &offset_saved);
inode_number = isofs_get_ino(block_saved,
- offset_saved,
- bufbits);
+ offset_saved, bufbits);
}
if (de->flags[-sbi->s_high_sierra] & 0x80) {
@@ -199,7 +189,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
*/
if ((sbi->s_hide == 'y' &&
(de->flags[-sbi->s_high_sierra] & 1)) ||
- (sbi->s_showassoc =='n' &&
+ (sbi->s_showassoc =='n' &&
(de->flags[-sbi->s_high_sierra] & 4))) {
filp->f_pos += de_len;
continue;
@@ -240,7 +230,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
continue;
}
- if (bh) brelse(bh);
+ if (bh)
+ brelse(bh);
return 0;
}
@@ -253,8 +244,8 @@ static int isofs_readdir(struct file *filp,
void *dirent, filldir_t filldir)
{
int result;
- char * tmpname;
- struct iso_directory_record * tmpde;
+ char *tmpname;
+ struct iso_directory_record *tmpde;
struct inode *inode = filp->f_path.dentry->d_inode;
tmpname = (char *)__get_free_page(GFP_KERNEL);
@@ -270,3 +261,19 @@ static int isofs_readdir(struct file *filp,
unlock_kernel();
return result;
}
+
+const struct file_operations isofs_dir_operations =
+{
+ .read = generic_read_dir,
+ .readdir = isofs_readdir,
+};
+
+/*
+ * directories can handle most operations...
+ */
+const struct inode_operations isofs_dir_inode_operations =
+{
+ .lookup = isofs_lookup,
+};
+
+
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 5c3eecf7542e..4f5418be0590 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -73,20 +73,20 @@ static void isofs_destroy_inode(struct inode *inode)
kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
}
-static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
{
struct iso_inode_info *ei = foo;
inode_init_once(&ei->vfs_inode);
}
-
+
static int init_inodecache(void)
{
isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
- sizeof(struct iso_inode_info),
- 0, (SLAB_RECLAIM_ACCOUNT|
- SLAB_MEM_SPREAD),
- init_once, NULL);
+ sizeof(struct iso_inode_info),
+ 0, (SLAB_RECLAIM_ACCOUNT|
+ SLAB_MEM_SPREAD),
+ init_once, NULL);
if (isofs_inode_cachep == NULL)
return -ENOMEM;
return 0;
@@ -150,9 +150,9 @@ struct iso9660_options{
uid_t uid;
char *iocharset;
unsigned char utf8;
- /* LVE */
- s32 session;
- s32 sbsector;
+ /* LVE */
+ s32 session;
+ s32 sbsector;
};
/*
@@ -197,7 +197,7 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
hash = init_name_hash();
while (len--) {
c = tolower(*name++);
- hash = partial_name_hash(tolower(c), hash);
+ hash = partial_name_hash(c, hash);
}
qstr->hash = end_name_hash(hash);
@@ -360,10 +360,12 @@ static int parse_options(char *options, struct iso9660_options *popt)
popt->check = 'u'; /* unset */
popt->nocompress = 0;
popt->blocksize = 1024;
- popt->mode = S_IRUGO | S_IXUGO; /* r-x for all. The disc could
- be shared with DOS machines so
- virtually anything could be
- a valid executable. */
+ popt->mode = S_IRUGO | S_IXUGO; /*
+ * r-x for all. The disc could
+ * be shared with DOS machines so
+ * virtually anything could be
+ * a valid executable.
+ */
popt->gid = 0;
popt->uid = 0;
popt->iocharset = NULL;
@@ -503,30 +505,30 @@ static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
Te.cdte_format=CDROM_LBA;
i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
if (!i) {
- printk(KERN_DEBUG "Session %d start %d type %d\n",
- session, Te.cdte_addr.lba,
- Te.cdte_ctrl&CDROM_DATA_TRACK);
+ printk(KERN_DEBUG "ISOFS: Session %d start %d type %d\n",
+ session, Te.cdte_addr.lba,
+ Te.cdte_ctrl&CDROM_DATA_TRACK);
if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
return Te.cdte_addr.lba;
}
-
- printk(KERN_ERR "Invalid session number or type of track\n");
+
+ printk(KERN_ERR "ISOFS: Invalid session number or type of track\n");
}
i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
if (session > 0)
- printk(KERN_ERR "Invalid session number\n");
+ printk(KERN_ERR "ISOFS: Invalid session number\n");
#if 0
- printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
+ printk(KERN_DEBUG "isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
if (i==0) {
- printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
- printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
+ printk(KERN_DEBUG "isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
+ printk(KERN_DEBUG "isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
}
#endif
if (i==0)
#if WE_OBEY_THE_WRITTEN_STANDARDS
- if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
+ if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
#endif
- vol_desc_start=ms_info.addr.lba;
+ vol_desc_start=ms_info.addr.lba;
return vol_desc_start;
}
@@ -538,20 +540,20 @@ static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
*/
static int isofs_fill_super(struct super_block *s, void *data, int silent)
{
- struct buffer_head * bh = NULL, *pri_bh = NULL;
- struct hs_primary_descriptor * h_pri = NULL;
- struct iso_primary_descriptor * pri = NULL;
+ struct buffer_head *bh = NULL, *pri_bh = NULL;
+ struct hs_primary_descriptor *h_pri = NULL;
+ struct iso_primary_descriptor *pri = NULL;
struct iso_supplementary_descriptor *sec = NULL;
- struct iso_directory_record * rootp;
- int joliet_level = 0;
- int iso_blknum, block;
- int orig_zonesize;
- int table;
- unsigned int vol_desc_start;
- unsigned long first_data_zone;
- struct inode * inode;
- struct iso9660_options opt;
- struct isofs_sb_info * sbi;
+ struct iso_directory_record *rootp;
+ struct inode *inode;
+ struct iso9660_options opt;
+ struct isofs_sb_info *sbi;
+ unsigned long first_data_zone;
+ int joliet_level = 0;
+ int iso_blknum, block;
+ int orig_zonesize;
+ int table;
+ unsigned int vol_desc_start;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
@@ -577,72 +579,73 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
vol_desc_start = (opt.sbsector != -1) ?
opt.sbsector : isofs_get_last_session(s,opt.session);
- for (iso_blknum = vol_desc_start+16;
- iso_blknum < vol_desc_start+100; iso_blknum++)
- {
- struct hs_volume_descriptor * hdp;
- struct iso_volume_descriptor * vdp;
-
- block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
- if (!(bh = sb_bread(s, block)))
- goto out_no_read;
-
- vdp = (struct iso_volume_descriptor *)bh->b_data;
- hdp = (struct hs_volume_descriptor *)bh->b_data;
-
- /* Due to the overlapping physical location of the descriptors,
- * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
- * proper identification in this case, we first check for ISO.
- */
- if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
- if (isonum_711 (vdp->type) == ISO_VD_END)
- break;
- if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
- if (pri == NULL) {
- pri = (struct iso_primary_descriptor *)vdp;
- /* Save the buffer in case we need it ... */
- pri_bh = bh;
- bh = NULL;
- }
- }
+ for (iso_blknum = vol_desc_start+16;
+ iso_blknum < vol_desc_start+100; iso_blknum++) {
+ struct hs_volume_descriptor *hdp;
+ struct iso_volume_descriptor *vdp;
+
+ block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
+ if (!(bh = sb_bread(s, block)))
+ goto out_no_read;
+
+ vdp = (struct iso_volume_descriptor *)bh->b_data;
+ hdp = (struct hs_volume_descriptor *)bh->b_data;
+
+ /*
+ * Due to the overlapping physical location of the descriptors,
+ * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
+ * proper identification in this case, we first check for ISO.
+ */
+ if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
+ if (isonum_711(vdp->type) == ISO_VD_END)
+ break;
+ if (isonum_711(vdp->type) == ISO_VD_PRIMARY) {
+ if (pri == NULL) {
+ pri = (struct iso_primary_descriptor *)vdp;
+ /* Save the buffer in case we need it ... */
+ pri_bh = bh;
+ bh = NULL;
+ }
+ }
#ifdef CONFIG_JOLIET
- else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
- sec = (struct iso_supplementary_descriptor *)vdp;
- if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
- if (opt.joliet == 'y') {
- if (sec->escape[2] == 0x40) {
- joliet_level = 1;
- } else if (sec->escape[2] == 0x43) {
- joliet_level = 2;
- } else if (sec->escape[2] == 0x45) {
- joliet_level = 3;
- }
- printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n",
- joliet_level);
+ else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
+ sec = (struct iso_supplementary_descriptor *)vdp;
+ if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
+ if (opt.joliet == 'y') {
+ if (sec->escape[2] == 0x40)
+ joliet_level = 1;
+ else if (sec->escape[2] == 0x43)
+ joliet_level = 2;
+ else if (sec->escape[2] == 0x45)
+ joliet_level = 3;
+
+ printk(KERN_DEBUG "ISO 9660 Extensions: "
+ "Microsoft Joliet Level %d\n",
+ joliet_level);
+ }
+ goto root_found;
+ } else {
+ /* Unknown supplementary volume descriptor */
+ sec = NULL;
+ }
}
- goto root_found;
- } else {
- /* Unknown supplementary volume descriptor */
- sec = NULL;
- }
- }
#endif
- } else {
- if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
- if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
- goto out_freebh;
-
- sbi->s_high_sierra = 1;
- opt.rock = 'n';
- h_pri = (struct hs_primary_descriptor *)vdp;
- goto root_found;
+ } else {
+ if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
+ if (isonum_711(hdp->type) != ISO_VD_PRIMARY)
+ goto out_freebh;
+
+ sbi->s_high_sierra = 1;
+ opt.rock = 'n';
+ h_pri = (struct hs_primary_descriptor *)vdp;
+ goto root_found;
+ }
}
- }
- /* Just skip any volume descriptors we don't recognize */
+ /* Just skip any volume descriptors we don't recognize */
- brelse(bh);
- bh = NULL;
+ brelse(bh);
+ bh = NULL;
}
/*
* If we fall through, either no volume descriptor was found,
@@ -657,24 +660,24 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
root_found:
if (joliet_level && (pri == NULL || opt.rock == 'n')) {
- /* This is the case of Joliet with the norock mount flag.
- * A disc with both Joliet and Rock Ridge is handled later
- */
- pri = (struct iso_primary_descriptor *) sec;
+ /* This is the case of Joliet with the norock mount flag.
+ * A disc with both Joliet and Rock Ridge is handled later
+ */
+ pri = (struct iso_primary_descriptor *) sec;
}
if(sbi->s_high_sierra){
- rootp = (struct iso_directory_record *) h_pri->root_directory_record;
- sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
- sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
- sbi->s_max_size = isonum_733(h_pri->volume_space_size);
+ rootp = (struct iso_directory_record *) h_pri->root_directory_record;
+ sbi->s_nzones = isonum_733(h_pri->volume_space_size);
+ sbi->s_log_zone_size = isonum_723(h_pri->logical_block_size);
+ sbi->s_max_size = isonum_733(h_pri->volume_space_size);
} else {
- if (!pri)
- goto out_freebh;
- rootp = (struct iso_directory_record *) pri->root_directory_record;
- sbi->s_nzones = isonum_733 (pri->volume_space_size);
- sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
- sbi->s_max_size = isonum_733(pri->volume_space_size);
+ if (!pri)
+ goto out_freebh;
+ rootp = (struct iso_directory_record *) pri->root_directory_record;
+ sbi->s_nzones = isonum_733(pri->volume_space_size);
+ sbi->s_log_zone_size = isonum_723(pri->logical_block_size);
+ sbi->s_max_size = isonum_733(pri->volume_space_size);
}
sbi->s_ninodes = 0; /* No way to figure this out easily */
@@ -687,42 +690,43 @@ root_found:
* blocks that were 512 bytes (which should only very rarely
* happen.)
*/
- if(orig_zonesize < opt.blocksize)
+ if (orig_zonesize < opt.blocksize)
goto out_bad_size;
/* RDE: convert log zone size to bit shift */
- switch (sbi->s_log_zone_size)
- { case 512: sbi->s_log_zone_size = 9; break;
- case 1024: sbi->s_log_zone_size = 10; break;
- case 2048: sbi->s_log_zone_size = 11; break;
+ switch (sbi->s_log_zone_size) {
+ case 512: sbi->s_log_zone_size = 9; break;
+ case 1024: sbi->s_log_zone_size = 10; break;
+ case 2048: sbi->s_log_zone_size = 11; break;
- default:
+ default:
goto out_bad_zone_size;
- }
+ }
s->s_magic = ISOFS_SUPER_MAGIC;
s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */
- /* The CDROM is read-only, has no nodes (devices) on it, and since
- all of the files appear to be owned by root, we really do not want
- to allow suid. (suid or devices will not show up unless we have
- Rock Ridge extensions) */
+ /*
+ * The CDROM is read-only, has no nodes (devices) on it, and since
+ * all of the files appear to be owned by root, we really do not want
+ * to allow suid. (suid or devices will not show up unless we have
+ * Rock Ridge extensions)
+ */
s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
/* Set this for reference. Its not currently used except on write
which we don't have .. */
-
- first_data_zone = isonum_733 (rootp->extent) +
- isonum_711 (rootp->ext_attr_length);
+
+ first_data_zone = isonum_733(rootp->extent) +
+ isonum_711(rootp->ext_attr_length);
sbi->s_firstdatazone = first_data_zone;
#ifndef BEQUIET
- printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
- sbi->s_max_size,
- 1UL << sbi->s_log_zone_size);
- printk(KERN_DEBUG "First datazone:%ld\n", sbi->s_firstdatazone);
+ printk(KERN_DEBUG "ISOFS: Max size:%ld Log zone size:%ld\n",
+ sbi->s_max_size, 1UL << sbi->s_log_zone_size);
+ printk(KERN_DEBUG "ISOFS: First datazone:%ld\n", sbi->s_firstdatazone);
if(sbi->s_high_sierra)
- printk(KERN_DEBUG "Disc in High Sierra format.\n");
+ printk(KERN_DEBUG "ISOFS: Disc in High Sierra format.\n");
#endif
/*
@@ -737,8 +741,8 @@ root_found:
pri = (struct iso_primary_descriptor *) sec;
rootp = (struct iso_directory_record *)
pri->root_directory_record;
- first_data_zone = isonum_733 (rootp->extent) +
- isonum_711 (rootp->ext_attr_length);
+ first_data_zone = isonum_733(rootp->extent) +
+ isonum_711(rootp->ext_attr_length);
}
/*
@@ -771,7 +775,7 @@ root_found:
#ifdef CONFIG_JOLIET
if (joliet_level && opt.utf8 == 0) {
- char * p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
+ char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
sbi->s_nls_iocharset = load_nls(p);
if (! sbi->s_nls_iocharset) {
/* Fail only if explicit charset specified */
@@ -821,7 +825,7 @@ root_found:
sbi->s_rock = 0;
if (sbi->s_firstdatazone != first_data_zone) {
sbi->s_firstdatazone = first_data_zone;
- printk(KERN_DEBUG
+ printk(KERN_DEBUG
"ISOFS: changing to secondary root\n");
iput(inode);
inode = isofs_iget(s, sbi->s_firstdatazone, 0);
@@ -830,8 +834,10 @@ root_found:
if (opt.check == 'u') {
/* Only Joliet is case insensitive by default */
- if (joliet_level) opt.check = 'r';
- else opt.check = 's';
+ if (joliet_level)
+ opt.check = 'r';
+ else
+ opt.check = 's';
}
sbi->s_joliet_level = joliet_level;
@@ -846,8 +852,10 @@ root_found:
goto out_no_root;
table = 0;
- if (joliet_level) table += 2;
- if (opt.check == 'r') table++;
+ if (joliet_level)
+ table += 2;
+ if (opt.check == 'r')
+ table++;
s->s_root->d_op = &isofs_dentry_ops[table];
kfree(opt.iocharset);
@@ -858,10 +866,10 @@ root_found:
* Display error messages and free resources.
*/
out_bad_root:
- printk(KERN_WARNING "isofs_fill_super: root inode not initialized\n");
+ printk(KERN_WARNING "%s: root inode not initialized\n", __func__);
goto out_iput;
out_no_root:
- printk(KERN_WARNING "isofs_fill_super: get root inode failed\n");
+ printk(KERN_WARNING "%s: get root inode failed\n", __func__);
out_iput:
iput(inode);
#ifdef CONFIG_JOLIET
@@ -870,21 +878,20 @@ out_iput:
#endif
goto out_freesbi;
out_no_read:
- printk(KERN_WARNING "isofs_fill_super: "
- "bread failed, dev=%s, iso_blknum=%d, block=%d\n",
- s->s_id, iso_blknum, block);
+ printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n",
+ __func__, s->s_id, iso_blknum, block);
goto out_freesbi;
out_bad_zone_size:
- printk(KERN_WARNING "Bad logical zone size %ld\n",
+ printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n",
sbi->s_log_zone_size);
goto out_freebh;
out_bad_size:
- printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
+ printk(KERN_WARNING "ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n",
orig_zonesize, opt.blocksize);
goto out_freebh;
out_unknown_format:
if (!silent)
- printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
+ printk(KERN_WARNING "ISOFS: Unable to identify CD-ROM format.\n");
out_freebh:
brelse(bh);
@@ -902,7 +909,7 @@ static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf)
buf->f_type = ISOFS_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = (ISOFS_SB(sb)->s_nzones
- << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
+ << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
buf->f_bfree = 0;
buf->f_bavail = 0;
buf->f_files = ISOFS_SB(sb)->s_ninodes;
@@ -931,20 +938,20 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
rv = 0;
if (iblock < 0 || iblock != iblock_s) {
- printk("isofs_get_blocks: block number too large\n");
+ printk(KERN_DEBUG "%s: block number too large\n", __func__);
goto abort;
}
b_off = iblock;
-
- offset = 0;
- firstext = ei->i_first_extent;
+
+ offset = 0;
+ firstext = ei->i_first_extent;
sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
- nextblk = ei->i_next_section_block;
- nextoff = ei->i_next_section_offset;
- section = 0;
+ nextblk = ei->i_next_section_block;
+ nextoff = ei->i_next_section_offset;
+ section = 0;
- while ( nblocks ) {
+ while (nblocks) {
/* If we are *way* beyond the end of the file, print a message.
* Access beyond the end of the file up to the next page boundary
* is normal, however because of the way the page cache works.
@@ -953,11 +960,11 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
* I/O errors.
*/
if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) {
- printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n",
- iblock, (unsigned long) inode->i_size);
+ printk(KERN_DEBUG "%s: block >= EOF (%ld, %ld)\n",
+ __func__, iblock, (unsigned long) inode->i_size);
goto abort;
}
-
+
/* On the last section, nextblk == 0, section size is likely to
* exceed sect_size by a partial block, and access beyond the
* end of the file will reach beyond the section size, too.
@@ -976,20 +983,21 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
iput(ninode);
if (++section > 100) {
- printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
- printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
- "nextblk=%lu nextoff=%lu\n",
- iblock, firstext, (unsigned) sect_size,
- nextblk, nextoff);
+ printk(KERN_DEBUG "%s: More than 100 file sections ?!?"
+ " aborting...\n", __func__);
+ printk(KERN_DEBUG "%s: block=%ld firstext=%u sect_size=%u "
+ "nextblk=%lu nextoff=%lu\n", __func__,
+ iblock, firstext, (unsigned) sect_size,
+ nextblk, nextoff);
goto abort;
}
}
-
- if ( *bh ) {
+
+ if (*bh) {
map_bh(*bh, inode->i_sb, firstext + b_off - offset);
} else {
*bh = sb_getblk(inode->i_sb, firstext+b_off-offset);
- if ( !*bh )
+ if (!*bh)
goto abort;
}
bh++; /* Next buffer head */
@@ -1010,7 +1018,7 @@ static int isofs_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
if (create) {
- printk("isofs_get_block: Kernel tries to allocate a block\n");
+ printk(KERN_DEBUG "%s: Kernel tries to allocate a block\n", __func__);
return -EROFS;
}
@@ -1070,11 +1078,11 @@ static int isofs_read_level3_size(struct inode *inode)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
- struct buffer_head * bh = NULL;
+ struct buffer_head *bh = NULL;
unsigned long block, offset, block_saved, offset_saved;
int i = 0;
int more_entries = 0;
- struct iso_directory_record * tmpde = NULL;
+ struct iso_directory_record *tmpde = NULL;
struct iso_inode_info *ei = ISOFS_I(inode);
inode->i_size = 0;
@@ -1089,7 +1097,7 @@ static int isofs_read_level3_size(struct inode *inode)
offset = ei->i_iget5_offset;
do {
- struct iso_directory_record * de;
+ struct iso_directory_record *de;
unsigned int de_len;
if (!bh) {
@@ -1163,10 +1171,9 @@ out_noread:
return -EIO;
out_toomany:
- printk(KERN_INFO "isofs_read_level3_size: "
- "More than 100 file sections ?!?, aborting...\n"
- "isofs_read_level3_size: inode=%lu\n",
- inode->i_ino);
+ printk(KERN_INFO "%s: More than 100 file sections ?!?, aborting...\n"
+ "isofs_read_level3_size: inode=%lu\n",
+ __func__, inode->i_ino);
goto out;
}
@@ -1177,9 +1184,9 @@ static void isofs_read_inode(struct inode *inode)
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
unsigned long block;
int high_sierra = sbi->s_high_sierra;
- struct buffer_head * bh = NULL;
- struct iso_directory_record * de;
- struct iso_directory_record * tmpde = NULL;
+ struct buffer_head *bh = NULL;
+ struct iso_directory_record *de;
+ struct iso_directory_record *tmpde = NULL;
unsigned int de_len;
unsigned long offset;
struct iso_inode_info *ei = ISOFS_I(inode);
@@ -1199,7 +1206,7 @@ static void isofs_read_inode(struct inode *inode)
tmpde = kmalloc(de_len, GFP_KERNEL);
if (tmpde == NULL) {
- printk(KERN_INFO "isofs_read_inode: out of memory\n");
+ printk(KERN_INFO "%s: out of memory\n", __func__);
goto fail;
}
memcpy(tmpde, bh->b_data + offset, frag1);
@@ -1212,24 +1219,26 @@ static void isofs_read_inode(struct inode *inode)
}
inode->i_ino = isofs_get_ino(ei->i_iget5_block,
- ei->i_iget5_offset,
- ISOFS_BUFFER_BITS(inode));
+ ei->i_iget5_offset,
+ ISOFS_BUFFER_BITS(inode));
/* Assume it is a normal-format file unless told otherwise */
ei->i_file_format = isofs_file_normal;
if (de->flags[-high_sierra] & 2) {
inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
- inode->i_nlink = 1; /* Set to 1. We know there are 2, but
- the find utility tries to optimize
- if it is 2, and it screws up. It is
- easier to give 1 which tells find to
- do it the hard way. */
+ inode->i_nlink = 1; /*
+ * Set to 1. We know there are 2, but
+ * the find utility tries to optimize
+ * if it is 2, and it screws up. It is
+ * easier to give 1 which tells find to
+ * do it the hard way.
+ */
} else {
- /* Everybody gets to read the file. */
+ /* Everybody gets to read the file. */
inode->i_mode = sbi->s_mode;
inode->i_nlink = 1;
- inode->i_mode |= S_IFREG;
+ inode->i_mode |= S_IFREG;
}
inode->i_uid = sbi->s_uid;
inode->i_gid = sbi->s_gid;
@@ -1239,13 +1248,14 @@ static void isofs_read_inode(struct inode *inode)
ei->i_format_parm[1] = 0;
ei->i_format_parm[2] = 0;
- ei->i_section_size = isonum_733 (de->size);
+ ei->i_section_size = isonum_733(de->size);
if (de->flags[-high_sierra] & 0x80) {
- if(isofs_read_level3_size(inode)) goto fail;
+ if(isofs_read_level3_size(inode))
+ goto fail;
} else {
ei->i_next_section_block = 0;
ei->i_next_section_offset = 0;
- inode->i_size = isonum_733 (de->size);
+ inode->i_size = isonum_733(de->size);
}
/*
@@ -1258,23 +1268,24 @@ static void isofs_read_inode(struct inode *inode)
inode->i_size &= 0x00ffffff;
if (de->interleave[0]) {
- printk("Interleaved files not (yet) supported.\n");
+ printk(KERN_DEBUG "ISOFS: Interleaved files not (yet) supported.\n");
inode->i_size = 0;
}
/* I have no idea what file_unit_size is used for, so
we will flag it for now */
if (de->file_unit_size[0] != 0) {
- printk("File unit size != 0 for ISO file (%ld).\n",
- inode->i_ino);
+ printk(KERN_DEBUG "ISOFS: File unit size != 0 for ISO file (%ld).\n",
+ inode->i_ino);
}
/* I have no idea what other flag bits are used for, so
we will flag it for now */
#ifdef DEBUG
if((de->flags[-high_sierra] & ~2)!= 0){
- printk("Unusual flag settings for ISO file (%ld %x).\n",
- inode->i_ino, de->flags[-high_sierra]);
+ printk(KERN_DEBUG "ISOFS: Unusual flag settings for ISO file "
+ "(%ld %x).\n",
+ inode->i_ino, de->flags[-high_sierra]);
}
#endif
@@ -1285,11 +1296,11 @@ static void isofs_read_inode(struct inode *inode)
inode->i_atime.tv_nsec =
inode->i_ctime.tv_nsec = 0;
- ei->i_first_extent = (isonum_733 (de->extent) +
- isonum_711 (de->ext_attr_length));
+ ei->i_first_extent = (isonum_733(de->extent) +
+ isonum_711(de->ext_attr_length));
/* Set the number of blocks for stat() - should be done before RR */
- inode->i_blocks = (inode->i_size + 511) >> 9;
+ inode->i_blocks = (inode->i_size + 511) >> 9;
/*
* Now test for possible Rock Ridge extensions which will override
@@ -1306,7 +1317,7 @@ static void isofs_read_inode(struct inode *inode)
/* Install the inode operations vector */
if (S_ISREG(inode->i_mode)) {
inode->i_fop = &generic_ro_fops;
- switch ( ei->i_file_format ) {
+ switch (ei->i_file_format) {
#ifdef CONFIG_ZISOFS
case isofs_file_compressed:
inode->i_data.a_ops = &zisofs_aops;
@@ -1350,7 +1361,7 @@ static int isofs_iget5_test(struct inode *ino, void *data)
struct isofs_iget5_callback_data *d =
(struct isofs_iget5_callback_data*)data;
return (i->i_iget5_block == d->block)
- && (i->i_iget5_offset == d->offset);
+ && (i->i_iget5_offset == d->offset);
}
static int isofs_iget5_set(struct inode *ino, void *data)
@@ -1384,7 +1395,7 @@ struct inode *isofs_iget(struct super_block *sb,
hashval = (block << sb->s_blocksize_bits) | offset;
inode = iget5_locked(sb, hashval, &isofs_iget5_test,
- &isofs_iget5_set, &data);
+ &isofs_iget5_set, &data);
if (inode && (inode->i_state & I_NEW)) {
sb->s_op->read_inode(inode);
@@ -1398,7 +1409,7 @@ static int isofs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super,
- mnt);
+ mnt);
}
static struct file_system_type iso9660_fs_type = {
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index efe2872cd4e3..a07e67b1ea7f 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -1,5 +1,6 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/iso_fs.h>
#include <asm/unaligned.h>
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index fb8fe7a9ddc6..92c14b850e9c 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -80,22 +80,20 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st
if (utf8) {
len = wcsntombs_be(outname, de->name,
- de->name_len[0] >> 1, PAGE_SIZE);
+ de->name_len[0] >> 1, PAGE_SIZE);
} else {
len = uni16_to_x8(outname, (__be16 *) de->name,
- de->name_len[0] >> 1, nls);
+ de->name_len[0] >> 1, nls);
}
- if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) {
+ if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1'))
len -= 2;
- }
/*
* Windows doesn't like periods at the end of a name,
* so neither do we
*/
- while (len >= 2 && (outname[len-1] == '.')) {
+ while (len >= 2 && (outname[len-1] == '.'))
len--;
- }
return len;
}
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index c04b3a14a3e9..c8c7e5138a01 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -15,7 +15,7 @@
* some sanity tests.
*/
static int
-isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
+isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
{
struct qstr qstr;
@@ -48,24 +48,24 @@ isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
*/
static unsigned long
isofs_find_entry(struct inode *dir, struct dentry *dentry,
- unsigned long *block_rv, unsigned long* offset_rv,
- char * tmpname, struct iso_directory_record * tmpde)
+ unsigned long *block_rv, unsigned long *offset_rv,
+ char *tmpname, struct iso_directory_record *tmpde)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
unsigned long block, f_pos, offset, block_saved, offset_saved;
- struct buffer_head * bh = NULL;
+ struct buffer_head *bh = NULL;
struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
if (!ISOFS_I(dir)->i_first_extent)
return 0;
-
+
f_pos = 0;
offset = 0;
block = 0;
while (f_pos < dir->i_size) {
- struct iso_directory_record * de;
+ struct iso_directory_record *de;
int de_len, match, i, dlen;
char *dpnt;
@@ -114,7 +114,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
if (sbi->s_rock &&
((i = get_rock_ridge_filename(de, tmpname, dir)))) {
- dlen = i; /* possibly -1 */
+ dlen = i; /* possibly -1 */
dpnt = tmpname;
#ifdef CONFIG_JOLIET
} else if (sbi->s_joliet_level) {
@@ -145,8 +145,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
isofs_normalize_block_and_offset(de,
&block_saved,
&offset_saved);
- *block_rv = block_saved;
- *offset_rv = offset_saved;
+ *block_rv = block_saved;
+ *offset_rv = offset_saved;
brelse(bh);
return 1;
}
@@ -155,7 +155,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
return 0;
}
-struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
int found;
unsigned long block, offset;
@@ -170,9 +170,9 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct n
lock_kernel();
found = isofs_find_entry(dir, dentry,
- &block, &offset,
- page_address(page),
- 1024 + page_address(page));
+ &block, &offset,
+ page_address(page),
+ 1024 + page_address(page));
__free_page(page);
inode = NULL;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 1facfaff97cb..a003d50edcdb 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -887,7 +887,8 @@ restart_loop:
journal->j_committing_transaction = NULL;
spin_unlock(&journal->j_state_lock);
- if (commit_transaction->t_checkpoint_list == NULL) {
+ if (commit_transaction->t_checkpoint_list == NULL &&
+ commit_transaction->t_checkpoint_io_list == NULL) {
__journal_drop_transaction(journal, commit_transaction);
} else {
if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 824e3b7d4ec1..8db2fa25170b 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -68,6 +68,7 @@
#include <linux/list.h>
#include <linux/init.h>
#endif
+#include <linux/log2.h>
static struct kmem_cache *revoke_record_cache;
static struct kmem_cache *revoke_table_cache;
@@ -211,7 +212,7 @@ int journal_init_revoke(journal_t *journal, int hash_size)
journal->j_revoke = journal->j_revoke_table[0];
/* Check that the hash_size is a power of two */
- J_ASSERT ((hash_size & (hash_size-1)) == 0);
+ J_ASSERT(is_power_of_2(hash_size));
journal->j_revoke->hash_size = hash_size;
@@ -238,7 +239,7 @@ int journal_init_revoke(journal_t *journal, int hash_size)
journal->j_revoke = journal->j_revoke_table[1];
/* Check that the hash_size is a power of two */
- J_ASSERT ((hash_size & (hash_size-1)) == 0);
+ J_ASSERT(is_power_of_2(hash_size));
journal->j_revoke->hash_size = hash_size;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 2856e1100a5f..c0f59d1b13dc 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -896,7 +896,8 @@ restart_loop:
journal->j_committing_transaction = NULL;
spin_unlock(&journal->j_state_lock);
- if (commit_transaction->t_checkpoint_list == NULL) {
+ if (commit_transaction->t_checkpoint_list == NULL &&
+ commit_transaction->t_checkpoint_io_list == NULL) {
__jbd2_journal_drop_transaction(journal, commit_transaction);
} else {
if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 9246e763da78..28cac049a56b 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -68,6 +68,7 @@
#include <linux/list.h>
#include <linux/init.h>
#endif
+#include <linux/log2.h>
static struct kmem_cache *jbd2_revoke_record_cache;
static struct kmem_cache *jbd2_revoke_table_cache;
@@ -212,7 +213,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
journal->j_revoke = journal->j_revoke_table[0];
/* Check that the hash_size is a power of two */
- J_ASSERT ((hash_size & (hash_size-1)) == 0);
+ J_ASSERT(is_power_of_2(hash_size));
journal->j_revoke->hash_size = hash_size;
@@ -239,7 +240,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
journal->j_revoke = journal->j_revoke_table[1];
/* Check that the hash_size is a power of two */
- J_ASSERT ((hash_size & (hash_size-1)) == 0);
+ J_ASSERT(is_power_of_2(hash_size));
journal->j_revoke->hash_size = hash_size;
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index a46101ee867a..65b3a1b5b88d 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -435,7 +435,7 @@ static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value,
struct posix_acl *acl;
int rc;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (value) {
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 0c82dfcfd246..143c5530caf3 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -81,6 +81,7 @@ static int jffs2_garbage_collect_thread(void *_c)
set_user_nice(current, 10);
+ set_freezable();
for (;;) {
allow_signal(SIGHUP);
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
index fe063af6fd2f..3c8663bea98c 100644
--- a/fs/jfs/ioctl.c
+++ b/fs/jfs/ioctl.c
@@ -69,7 +69,7 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EACCES;
if (get_user(flags, (int __user *) arg))
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 2374b595f2e1..f0ec72b263f1 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -32,6 +32,7 @@ extern void jfs_truncate_nolock(struct inode *, loff_t);
extern void jfs_free_zero_link(struct inode *);
extern struct dentry *jfs_get_parent(struct dentry *dentry);
extern void jfs_get_inode_flags(struct jfs_inode_info *);
+extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp);
extern void jfs_set_inode_flags(struct inode *);
extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 25161c4121e4..932797ba433b 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1477,6 +1477,38 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
return dentry;
}
+struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
+{
+ __u32 *objp = vobjp;
+ unsigned long ino = objp[0];
+ __u32 generation = objp[1];
+ struct inode *inode;
+ struct dentry *result;
+
+ if (ino == 0)
+ return ERR_PTR(-ESTALE);
+ inode = iget(sb, ino);
+ if (inode == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ if (is_bad_inode(inode) ||
+ (generation && inode->i_generation != generation)) {
+ result = ERR_PTR(-ESTALE);
+ goto out_iput;
+ }
+
+ result = d_alloc_anon(inode);
+ if (!result) {
+ result = ERR_PTR(-ENOMEM);
+ goto out_iput;
+ }
+ return result;
+
+ out_iput:
+ iput(inode);
+ return result;
+}
+
struct dentry *jfs_get_parent(struct dentry *dentry)
{
struct super_block *sb = dentry->d_inode->i_sb;
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 20e4ac1c79a3..929fceca7999 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -27,6 +27,7 @@
#include <linux/kthread.h>
#include <linux/posix_acl.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <asm/uaccess.h>
#include <linux/seq_file.h>
@@ -737,6 +738,7 @@ static const struct super_operations jfs_super_operations = {
};
static struct export_operations jfs_export_operations = {
+ .get_dentry = jfs_get_dentry,
.get_parent = jfs_get_parent,
};
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index b2375f0774b7..9b7f2cdaae0a 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -697,7 +697,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
struct posix_acl *acl;
int rc;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
/*
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 26809325469c..82e2192a0d5c 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -25,6 +25,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/stats.h>
@@ -75,18 +76,31 @@ static const int nlm_port_min = 0, nlm_port_max = 65535;
static struct ctl_table_header * nlm_sysctl_table;
-static unsigned long set_grace_period(void)
+static unsigned long get_lockd_grace_period(void)
{
- unsigned long grace_period;
-
/* Note: nlm_timeout should always be nonzero */
if (nlm_grace_period)
- grace_period = ((nlm_grace_period + nlm_timeout - 1)
- / nlm_timeout) * nlm_timeout * HZ;
+ return roundup(nlm_grace_period, nlm_timeout) * HZ;
else
- grace_period = nlm_timeout * 5 * HZ;
+ return nlm_timeout * 5 * HZ;
+}
+
+unsigned long get_nfs_grace_period(void)
+{
+ unsigned long lockdgrace = get_lockd_grace_period();
+ unsigned long nfsdgrace = 0;
+
+ if (nlmsvc_ops)
+ nfsdgrace = nlmsvc_ops->get_grace_period();
+
+ return max(lockdgrace, nfsdgrace);
+}
+EXPORT_SYMBOL(get_nfs_grace_period);
+
+static unsigned long set_grace_period(void)
+{
nlmsvc_grace_period = 1;
- return grace_period + jiffies;
+ return get_nfs_grace_period() + jiffies;
}
static inline void clear_grace_period(void)
@@ -119,6 +133,7 @@ lockd(struct svc_rqst *rqstp)
complete(&lockd_start_done);
daemonize("lockd");
+ set_freezable();
/* Process request with signals blocked, but allow SIGKILL. */
allow_signal(SIGKILL);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index deeb9dc062d9..fbb1d02f8791 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -100,7 +100,6 @@ struct mb_cache {
static LIST_HEAD(mb_cache_list);
static LIST_HEAD(mb_cache_lru_list);
static DEFINE_SPINLOCK(mb_cache_spinlock);
-static struct shrinker *mb_shrinker;
static inline int
mb_cache_indexes(struct mb_cache *cache)
@@ -118,6 +117,10 @@ mb_cache_indexes(struct mb_cache *cache)
static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask);
+static struct shrinker mb_cache_shrinker = {
+ .shrink = mb_cache_shrink_fn,
+ .seeks = DEFAULT_SEEKS,
+};
static inline int
__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
@@ -662,13 +665,13 @@ mb_cache_entry_find_next(struct mb_cache_entry *prev, int index,
static int __init init_mbcache(void)
{
- mb_shrinker = set_shrinker(DEFAULT_SEEKS, mb_cache_shrink_fn);
+ register_shrinker(&mb_cache_shrinker);
return 0;
}
static void __exit exit_mbcache(void)
{
- remove_shrinker(mb_shrinker);
+ unregister_shrinker(&mb_cache_shrinker);
}
module_init(init_mbcache)
diff --git a/fs/namei.c b/fs/namei.c
index 5e2d98d10c5d..defaa47c11d4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1576,7 +1576,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
/* O_NOATIME can only be set by the owner or superuser */
if (flag & O_NOATIME)
- if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
/*
diff --git a/fs/namespace.c b/fs/namespace.c
index b696e3a0d18f..4198003d7e18 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -28,6 +28,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include "pnode.h"
+#include "internal.h"
/* spinlock for vfsmount related operations, inplace of dcache_lock */
__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
@@ -320,22 +321,16 @@ EXPORT_SYMBOL(mnt_unpin);
static void *m_start(struct seq_file *m, loff_t *pos)
{
struct mnt_namespace *n = m->private;
- struct list_head *p;
- loff_t l = *pos;
down_read(&namespace_sem);
- list_for_each(p, &n->list)
- if (!l--)
- return list_entry(p, struct vfsmount, mnt_list);
- return NULL;
+ return seq_list_start(&n->list, *pos);
}
static void *m_next(struct seq_file *m, void *v, loff_t *pos)
{
struct mnt_namespace *n = m->private;
- struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
- (*pos)++;
- return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
+
+ return seq_list_next(v, &n->list, pos);
}
static void m_stop(struct seq_file *m, void *v)
@@ -350,7 +345,7 @@ static inline void mangle(struct seq_file *m, const char *s)
static int show_vfsmnt(struct seq_file *m, void *v)
{
- struct vfsmount *mnt = v;
+ struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
int err = 0;
static struct proc_fs_info {
int flag;
@@ -405,7 +400,7 @@ struct seq_operations mounts_op = {
static int show_vfsstat(struct seq_file *m, void *v)
{
- struct vfsmount *mnt = v;
+ struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
int err = 0;
/* device */
@@ -1457,7 +1452,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
if (!new_ns)
- return NULL;
+ return ERR_PTR(-ENOMEM);
atomic_set(&new_ns->count, 1);
INIT_LIST_HEAD(&new_ns->list);
@@ -1471,7 +1466,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
if (!new_ns->root) {
up_write(&namespace_sem);
kfree(new_ns);
- return NULL;
+ return ERR_PTR(-ENOMEM);;
}
spin_lock(&vfsmount_lock);
list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
@@ -1515,7 +1510,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
return new_ns;
}
-struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns,
+struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
struct fs_struct *new_fs)
{
struct mnt_namespace *new_ns;
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index d3152f8d95c6..2b145de45b39 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -203,7 +203,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
if (pos >= MAX_NON_LFS) {
- send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
if (count > MAX_NON_LFS - (u32)pos) {
@@ -212,7 +211,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
}
if (pos >= inode->i_sb->s_maxbytes) {
if (count || pos > inode->i_sb->s_maxbytes) {
- send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
}
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 75f309c8741a..a796be5051bf 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
#include <linux/sunrpc/svcsock.h>
#include <linux/nfs_fs.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
#include <net/inet_sock.h>
@@ -67,6 +68,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
daemonize("nfsv4-svc");
/* Process request with signals blocked, but allow SIGKILL. */
allow_signal(SIGKILL);
+ set_freezable();
complete(&nfs_callback_info.started);
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ccb455053ee4..a49f9feff776 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1206,23 +1206,9 @@ static int nfs_server_list_open(struct inode *inode, struct file *file)
*/
static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
{
- struct list_head *_p;
- loff_t pos = *_pos;
-
/* lock the list against modification */
spin_lock(&nfs_client_lock);
-
- /* allow for the header line */
- if (!pos)
- return SEQ_START_TOKEN;
- pos--;
-
- /* find the n'th element in the list */
- list_for_each(_p, &nfs_client_list)
- if (!pos--)
- break;
-
- return _p != &nfs_client_list ? _p : NULL;
+ return seq_list_start_head(&nfs_client_list, *_pos);
}
/*
@@ -1230,14 +1216,7 @@ static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
*/
static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
{
- struct list_head *_p;
-
- (*pos)++;
-
- _p = v;
- _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
-
- return _p != &nfs_client_list ? _p : NULL;
+ return seq_list_next(v, &nfs_client_list, pos);
}
/*
@@ -1256,7 +1235,7 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
struct nfs_client *clp;
/* display header on line 1 */
- if (v == SEQ_START_TOKEN) {
+ if (v == &nfs_client_list) {
seq_puts(m, "NV SERVER PORT USE HOSTNAME\n");
return 0;
}
@@ -1297,23 +1276,9 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file)
*/
static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
{
- struct list_head *_p;
- loff_t pos = *_pos;
-
/* lock the list against modification */
spin_lock(&nfs_client_lock);
-
- /* allow for the header line */
- if (!pos)
- return SEQ_START_TOKEN;
- pos--;
-
- /* find the n'th element in the list */
- list_for_each(_p, &nfs_volume_list)
- if (!pos--)
- break;
-
- return _p != &nfs_volume_list ? _p : NULL;
+ return seq_list_start_head(&nfs_volume_list, *_pos);
}
/*
@@ -1321,14 +1286,7 @@ static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
*/
static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
{
- struct list_head *_p;
-
- (*pos)++;
-
- _p = v;
- _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
-
- return _p != &nfs_volume_list ? _p : NULL;
+ return seq_list_next(v, &nfs_volume_list, pos);
}
/*
@@ -1349,7 +1307,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
char dev[8], fsid[17];
/* display header on line 1 */
- if (v == SEQ_START_TOKEN) {
+ if (v == &nfs_volume_list) {
seq_puts(m, "NV SERVER PORT DEV FSID\n");
return 0;
}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a2b1af89ca1a..adffe1615c51 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -300,7 +300,10 @@ static const struct super_operations nfs4_sops = {
};
#endif
-static struct shrinker *acl_shrinker;
+static struct shrinker acl_shrinker = {
+ .shrink = nfs_access_cache_shrinker,
+ .seeks = DEFAULT_SEEKS,
+};
/*
* Register the NFS filesystems
@@ -321,7 +324,7 @@ int __init register_nfs_fs(void)
if (ret < 0)
goto error_2;
#endif
- acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
+ register_shrinker(&acl_shrinker);
return 0;
#ifdef CONFIG_NFS_V4
@@ -339,8 +342,7 @@ error_0:
*/
void __exit unregister_nfs_fs(void)
{
- if (acl_shrinker != NULL)
- remove_shrinker(acl_shrinker);
+ unregister_shrinker(&acl_shrinker);
#ifdef CONFIG_NFS_V4
unregister_filesystem(&nfs4_fs_type);
nfs_unregister_sysctl();
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 6e92b0fe5323..cf61dc8ae942 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -12,17 +12,31 @@
#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
+static int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+{
+ struct exp_flavor_info *f;
+ struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+ for (f = exp->ex_flavors; f < end; f++) {
+ if (f->pseudoflavor == rqstp->rq_flavor)
+ return f->flags;
+ }
+ return exp->ex_flags;
+
+}
+
int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{
struct svc_cred cred = rqstp->rq_cred;
int i;
+ int flags = nfsexp_flags(rqstp, exp);
int ret;
- if (exp->ex_flags & NFSEXP_ALLSQUASH) {
+ if (flags & NFSEXP_ALLSQUASH) {
cred.cr_uid = exp->ex_anon_uid;
cred.cr_gid = exp->ex_anon_gid;
cred.cr_group_info = groups_alloc(0);
- } else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
+ } else if (flags & NFSEXP_ROOTSQUASH) {
struct group_info *gi;
if (!cred.cr_uid)
cred.cr_uid = exp->ex_anon_uid;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 79bd03b8bbf8..c7bbf460b009 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -26,12 +26,15 @@
#include <linux/mount.h>
#include <linux/hash.h>
#include <linux/module.h>
+#include <linux/exportfs.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/nfsfh.h>
#include <linux/nfsd/syscall.h>
#include <linux/lockd/bind.h>
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/sunrpc/gss_api.h>
#define NFSDDBG_FACILITY NFSDDBG_EXPORT
@@ -451,8 +454,48 @@ out_free_all:
return err;
}
+static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
+{
+ int listsize, err;
+ struct exp_flavor_info *f;
+
+ err = get_int(mesg, &listsize);
+ if (err)
+ return err;
+ if (listsize < 0 || listsize > MAX_SECINFO_LIST)
+ return -EINVAL;
+
+ for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
+ err = get_int(mesg, &f->pseudoflavor);
+ if (err)
+ return err;
+ /*
+ * Just a quick sanity check; we could also try to check
+ * whether this pseudoflavor is supported, but at worst
+ * an unsupported pseudoflavor on the export would just
+ * be a pseudoflavor that won't match the flavor of any
+ * authenticated request. The administrator will
+ * probably discover the problem when someone fails to
+ * authenticate.
+ */
+ if (f->pseudoflavor < 0)
+ return -EINVAL;
+ err = get_int(mesg, &f->flags);
+ if (err)
+ return err;
+ /* Only some flags are allowed to differ between flavors: */
+ if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
+ return -EINVAL;
+ }
+ exp->ex_nflavors = listsize;
+ return 0;
+}
+
#else /* CONFIG_NFSD_V4 */
-static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
+static inline int
+fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
+static inline int
+secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
#endif
static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
@@ -476,6 +519,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
exp.ex_uuid = NULL;
+ /* secinfo */
+ exp.ex_nflavors = 0;
+
if (mesg[mlen-1] != '\n')
return -EINVAL;
mesg[mlen-1] = 0;
@@ -553,7 +599,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
if (exp.ex_uuid == NULL)
err = -ENOMEM;
}
- } else
+ } else if (strcmp(buf, "secinfo") == 0)
+ err = secinfo_parse(&mesg, buf, &exp);
+ else
/* quietly ignore unknown words and anything
* following. Newer user-space can try to set
* new values, then see what the result was.
@@ -593,6 +641,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
static void exp_flags(struct seq_file *m, int flag, int fsid,
uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
+static void show_secinfo(struct seq_file *m, struct svc_export *exp);
static int svc_export_show(struct seq_file *m,
struct cache_detail *cd,
@@ -622,6 +671,7 @@ static int svc_export_show(struct seq_file *m,
seq_printf(m, "%02x", exp->ex_uuid[i]);
}
}
+ show_secinfo(m, exp);
}
seq_puts(m, ")\n");
return 0;
@@ -654,6 +704,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
{
struct svc_export *new = container_of(cnew, struct svc_export, h);
struct svc_export *item = container_of(citem, struct svc_export, h);
+ int i;
new->ex_flags = item->ex_flags;
new->ex_anon_uid = item->ex_anon_uid;
@@ -669,6 +720,10 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
item->ex_fslocs.locations_count = 0;
new->ex_fslocs.migrated = item->ex_fslocs.migrated;
item->ex_fslocs.migrated = 0;
+ new->ex_nflavors = item->ex_nflavors;
+ for (i = 0; i < MAX_SECINFO_LIST; i++) {
+ new->ex_flavors[i] = item->ex_flavors[i];
+ }
}
static struct cache_head *svc_export_alloc(void)
@@ -738,16 +793,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
int err;
if (!clp)
- return NULL;
+ return ERR_PTR(-ENOENT);
key.ek_client = clp;
key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
ek = svc_expkey_lookup(&key);
- if (ek != NULL)
- if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
- ek = ERR_PTR(err);
+ if (ek == NULL)
+ return ERR_PTR(-ENOMEM);
+ err = cache_check(&svc_expkey_cache, &ek->h, reqp);
+ if (err)
+ return ERR_PTR(err);
return ek;
}
@@ -808,30 +865,21 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
struct cache_req *reqp)
{
struct svc_export *exp, key;
+ int err;
if (!clp)
- return NULL;
+ return ERR_PTR(-ENOENT);
key.ex_client = clp;
key.ex_mnt = mnt;
key.ex_dentry = dentry;
exp = svc_export_lookup(&key);
- if (exp != NULL) {
- int err;
-
- err = cache_check(&svc_export_cache, &exp->h, reqp);
- switch (err) {
- case 0: break;
- case -EAGAIN:
- case -ETIMEDOUT:
- exp = ERR_PTR(err);
- break;
- default:
- exp = NULL;
- }
- }
-
+ if (exp == NULL)
+ return ERR_PTR(-ENOMEM);
+ err = cache_check(&svc_export_cache, &exp->h, reqp);
+ if (err)
+ return ERR_PTR(err);
return exp;
}
@@ -847,7 +895,7 @@ exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
dget(dentry);
exp = exp_get_by_name(clp, mnt, dentry, reqp);
- while (exp == NULL && !IS_ROOT(dentry)) {
+ while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
struct dentry *parent;
parent = dget_parent(dentry);
@@ -900,7 +948,7 @@ static void exp_fsid_unhash(struct svc_export *exp)
return;
ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
- if (ek && !IS_ERR(ek)) {
+ if (!IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1;
cache_put(&ek->h, &svc_expkey_cache);
}
@@ -938,7 +986,7 @@ static void exp_unhash(struct svc_export *exp)
struct inode *inode = exp->ex_dentry->d_inode;
ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
- if (ek && !IS_ERR(ek)) {
+ if (!IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1;
cache_put(&ek->h, &svc_expkey_cache);
}
@@ -989,13 +1037,12 @@ exp_export(struct nfsctl_export *nxp)
/* must make sure there won't be an ex_fsid clash */
if ((nxp->ex_flags & NFSEXP_FSID) &&
- (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
- !IS_ERR(fsid_key) &&
+ (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
fsid_key->ek_mnt &&
(fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
goto finish;
- if (exp) {
+ if (!IS_ERR(exp)) {
/* just a flags/id/fsid update */
exp_fsid_unhash(exp);
@@ -1104,7 +1151,7 @@ exp_unexport(struct nfsctl_export *nxp)
err = -EINVAL;
exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
path_release(&nd);
- if (!exp)
+ if (IS_ERR(exp))
goto out_domain;
exp_do_unexport(exp);
@@ -1149,10 +1196,6 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
err = PTR_ERR(exp);
goto out;
}
- if (!exp) {
- dprintk("nfsd: exp_rootfh export not found.\n");
- goto out;
- }
/*
* fh must be initialized before calling fh_compose
@@ -1176,17 +1219,130 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
{
struct svc_export *exp;
struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
- if (!ek || IS_ERR(ek))
+ if (IS_ERR(ek))
return ERR_PTR(PTR_ERR(ek));
exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
cache_put(&ek->h, &svc_expkey_cache);
- if (!exp || IS_ERR(exp))
+ if (IS_ERR(exp))
return ERR_PTR(PTR_ERR(exp));
return exp;
}
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+ struct exp_flavor_info *f;
+ struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+ /* legacy gss-only clients are always OK: */
+ if (exp->ex_client == rqstp->rq_gssclient)
+ return 0;
+ /* ip-address based client; check sec= export option: */
+ for (f = exp->ex_flavors; f < end; f++) {
+ if (f->pseudoflavor == rqstp->rq_flavor)
+ return 0;
+ }
+ /* defaults in absence of sec= options: */
+ if (exp->ex_nflavors == 0) {
+ if (rqstp->rq_flavor == RPC_AUTH_NULL ||
+ rqstp->rq_flavor == RPC_AUTH_UNIX)
+ return 0;
+ }
+ return nfserr_wrongsec;
+}
+
+/*
+ * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
+ * auth_unix client) if it's available and has secinfo information;
+ * otherwise, will try to use rq_gssclient.
+ *
+ * Called from functions that handle requests; functions that do work on
+ * behalf of mountd are passed a single client name to use, and should
+ * use exp_get_by_name() or exp_find().
+ */
+struct svc_export *
+rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ struct dentry *dentry)
+{
+ struct svc_export *gssexp, *exp = NULL;
+
+ if (rqstp->rq_client == NULL)
+ goto gss;
+
+ /* First try the auth_unix client: */
+ exp = exp_get_by_name(rqstp->rq_client, mnt, dentry,
+ &rqstp->rq_chandle);
+ if (PTR_ERR(exp) == -ENOENT)
+ goto gss;
+ if (IS_ERR(exp))
+ return exp;
+ /* If it has secinfo, assume there are no gss/... clients */
+ if (exp->ex_nflavors > 0)
+ return exp;
+gss:
+ /* Otherwise, try falling back on gss client */
+ if (rqstp->rq_gssclient == NULL)
+ return exp;
+ gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry,
+ &rqstp->rq_chandle);
+ if (PTR_ERR(gssexp) == -ENOENT)
+ return exp;
+ if (exp && !IS_ERR(exp))
+ exp_put(exp);
+ return gssexp;
+}
+
+struct svc_export *
+rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
+{
+ struct svc_export *gssexp, *exp = NULL;
+
+ if (rqstp->rq_client == NULL)
+ goto gss;
+
+ /* First try the auth_unix client: */
+ exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle);
+ if (PTR_ERR(exp) == -ENOENT)
+ goto gss;
+ if (IS_ERR(exp))
+ return exp;
+ /* If it has secinfo, assume there are no gss/... clients */
+ if (exp->ex_nflavors > 0)
+ return exp;
+gss:
+ /* Otherwise, try falling back on gss client */
+ if (rqstp->rq_gssclient == NULL)
+ return exp;
+ gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv,
+ &rqstp->rq_chandle);
+ if (PTR_ERR(gssexp) == -ENOENT)
+ return exp;
+ if (exp && !IS_ERR(exp))
+ exp_put(exp);
+ return gssexp;
+}
+
+struct svc_export *
+rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt,
+ struct dentry *dentry)
+{
+ struct svc_export *exp;
+
+ dget(dentry);
+ exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+
+ while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
+ struct dentry *parent;
+
+ parent = dget_parent(dentry);
+ dput(dentry);
+ dentry = parent;
+ exp = rqst_exp_get_by_name(rqstp, mnt, dentry);
+ }
+ dput(dentry);
+ return exp;
+}
/*
* Called when we need the filehandle for the root of the pseudofs,
@@ -1194,8 +1350,7 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
* export point with fsid==0
*/
__be32
-exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
- struct cache_req *creq)
+exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
{
struct svc_export *exp;
__be32 rv;
@@ -1203,12 +1358,16 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
- exp = exp_find(clp, FSID_NUM, fsidv, creq);
+ exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+ if (PTR_ERR(exp) == -ENOENT)
+ return nfserr_perm;
if (IS_ERR(exp))
return nfserrno(PTR_ERR(exp));
- if (exp == NULL)
- return nfserr_perm;
rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
+ if (rv)
+ goto out;
+ rv = check_nfsd_access(exp, rqstp);
+out:
exp_put(exp);
return rv;
}
@@ -1296,28 +1455,62 @@ static struct flags {
{ 0, {"", ""}}
};
-static void exp_flags(struct seq_file *m, int flag, int fsid,
- uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+static void show_expflags(struct seq_file *m, int flags, int mask)
{
- int first = 0;
struct flags *flg;
+ int state, first = 0;
for (flg = expflags; flg->flag; flg++) {
- int state = (flg->flag & flag)?0:1;
+ if (flg->flag & ~mask)
+ continue;
+ state = (flg->flag & flags) ? 0 : 1;
if (*flg->name[state])
seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
}
+}
+
+static void show_secinfo_flags(struct seq_file *m, int flags)
+{
+ seq_printf(m, ",");
+ show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
+}
+
+static void show_secinfo(struct seq_file *m, struct svc_export *exp)
+{
+ struct exp_flavor_info *f;
+ struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+ int lastflags = 0, first = 0;
+
+ if (exp->ex_nflavors == 0)
+ return;
+ for (f = exp->ex_flavors; f < end; f++) {
+ if (first || f->flags != lastflags) {
+ if (!first)
+ show_secinfo_flags(m, lastflags);
+ seq_printf(m, ",sec=%d", f->pseudoflavor);
+ lastflags = f->flags;
+ } else {
+ seq_printf(m, ":%d", f->pseudoflavor);
+ }
+ }
+ show_secinfo_flags(m, lastflags);
+}
+
+static void exp_flags(struct seq_file *m, int flag, int fsid,
+ uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
+{
+ show_expflags(m, flag, NFSEXP_ALLFLAGS);
if (flag & NFSEXP_FSID)
- seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
+ seq_printf(m, ",fsid=%d", fsid);
if (anonu != (uid_t)-2 && anonu != (0x10000-2))
- seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
+ seq_printf(m, ",sanonuid=%d", anonu);
if (anong != (gid_t)-2 && anong != (0x10000-2))
- seq_printf(m, "%sanongid=%d", first++?",":"", anong);
+ seq_printf(m, ",sanongid=%d", anong);
if (fsloc && fsloc->locations_count > 0) {
char *loctype = (fsloc->migrated) ? "refer" : "replicas";
int i;
- seq_printf(m, "%s%s=", first++?",":"", loctype);
+ seq_printf(m, ",%s=", loctype);
seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
seq_putc(m, '@');
seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 221acd1f11f6..9e4a568a5013 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -65,6 +65,7 @@ nlm_fclose(struct file *filp)
static struct nlmsvc_binding nfsd_nlm_ops = {
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
+ .get_grace_period = get_nfs4_grace_period,
};
void
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index cc3b7badd486..b6ed38380ab8 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -183,8 +183,13 @@ static void
summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
{
struct posix_acl_entry *pa, *pe;
- pas->users = 0;
- pas->groups = 0;
+
+ /*
+ * Only pas.users and pas.groups need initialization; previous
+ * posix_acl_valid() calls ensure that the other fields will be
+ * initialized in the following loop. But, just to placate gcc:
+ */
+ memset(pas, 0, sizeof(*pas));
pas->mask = 07;
pe = acl->a_entries + acl->a_count;
@@ -732,13 +737,16 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
*pacl = posix_state_to_acl(&effective_acl_state, flags);
if (IS_ERR(*pacl)) {
ret = PTR_ERR(*pacl);
+ *pacl = NULL;
goto out_dstate;
}
*dpacl = posix_state_to_acl(&default_acl_state,
flags | NFS4_ACL_TYPE_DEFAULT);
if (IS_ERR(*dpacl)) {
ret = PTR_ERR(*dpacl);
+ *dpacl = NULL;
posix_acl_release(*pacl);
+ *pacl = NULL;
goto out_dstate;
}
sort_pacl(*pacl);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 5443c52b57aa..31d6633c7fe4 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -75,7 +75,7 @@ enum nfs_cb_opnum4 {
#define op_enc_sz 1
#define op_dec_sz 2
#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2))
-#define enc_stateid_sz 16
+#define enc_stateid_sz (NFS4_STATEID_SIZE >> 2)
#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \
1 + enc_stateid_sz + \
enc_nfs4_fh_sz)
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 45aa21ce6784..2cf9a9a2d89c 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -587,6 +587,15 @@ idmap_lookup(struct svc_rqst *rqstp,
return ret;
}
+static char *
+rqst_authname(struct svc_rqst *rqstp)
+{
+ struct auth_domain *clp;
+
+ clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+ return clp->name;
+}
+
static int
idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
uid_t *id)
@@ -600,7 +609,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
return -EINVAL;
memcpy(key.name, name, namelen);
key.name[namelen] = '\0';
- strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+ strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
if (ret == -ENOENT)
ret = -ESRCH; /* nfserr_badname */
@@ -620,7 +629,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
};
int ret;
- strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+ strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
if (ret == -ENOENT)
return sprintf(name, "%u", id);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 8522729830db..3c627128e205 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -47,6 +47,7 @@
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/nfs4_acl.h>
+#include <linux/sunrpc/gss_api.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC
@@ -286,8 +287,7 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
__be32 status;
fh_put(&cstate->current_fh);
- status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
- &rqstp->rq_chandle);
+ status = exp_pseudoroot(rqstp, &cstate->current_fh);
return status;
}
@@ -474,8 +474,8 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
__be32 ret;
fh_init(&tmp_fh, NFS4_FHSIZE);
- if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
- &rqstp->rq_chandle)) != 0)
+ ret = exp_pseudoroot(rqstp, &tmp_fh);
+ if (ret)
return ret;
if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
fh_put(&tmp_fh);
@@ -611,6 +611,30 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
}
static __be32
+nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_secinfo *secinfo)
+{
+ struct svc_fh resfh;
+ struct svc_export *exp;
+ struct dentry *dentry;
+ __be32 err;
+
+ fh_init(&resfh, NFS4_FHSIZE);
+ err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
+ secinfo->si_name, secinfo->si_namelen,
+ &exp, &dentry);
+ if (err)
+ return err;
+ if (dentry->d_inode == NULL) {
+ exp_put(exp);
+ err = nfserr_noent;
+ } else
+ secinfo->si_exp = exp;
+ dput(dentry);
+ return err;
+}
+
+static __be32
nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_setattr *setattr)
{
@@ -1009,6 +1033,9 @@ static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
[OP_SAVEFH] = {
.op_func = (nfsd4op_func)nfsd4_savefh,
},
+ [OP_SECINFO] = {
+ .op_func = (nfsd4op_func)nfsd4_secinfo,
+ },
[OP_SETATTR] = {
.op_func = (nfsd4op_func)nfsd4_setattr,
},
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 8c52913d7cb6..e4a4c87ec8c6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -49,8 +49,10 @@
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/namei.h>
+#include <linux/swap.h>
#include <linux/mutex.h>
#include <linux/lockd/bind.h>
+#include <linux/module.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC
@@ -149,6 +151,7 @@ get_nfs4_file(struct nfs4_file *fi)
}
static int num_delegations;
+unsigned int max_delegations;
/*
* Open owner state (share locks)
@@ -192,7 +195,9 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
dprintk("NFSD alloc_init_deleg\n");
- if (num_delegations > STATEID_HASH_SIZE * 4)
+ if (fp->fi_had_conflict)
+ return NULL;
+ if (num_delegations > max_delegations)
return NULL;
dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
if (dp == NULL)
@@ -999,6 +1004,7 @@ alloc_init_file(struct inode *ino)
list_add(&fp->fi_hash, &file_hashtbl[hashval]);
fp->fi_inode = igrab(ino);
fp->fi_id = current_fileid++;
+ fp->fi_had_conflict = false;
return fp;
}
return NULL;
@@ -1325,6 +1331,7 @@ do_recall(void *__dp)
{
struct nfs4_delegation *dp = __dp;
+ dp->dl_file->fi_had_conflict = true;
nfsd4_cb_recall(dp);
return 0;
}
@@ -3190,20 +3197,49 @@ nfsd4_load_reboot_recovery_data(void)
printk("NFSD: Failure reading reboot recovery data\n");
}
+unsigned long
+get_nfs4_grace_period(void)
+{
+ return max(user_lease_time, lease_time) * HZ;
+}
+
+/*
+ * Since the lifetime of a delegation isn't limited to that of an open, a
+ * client may quite reasonably hang on to a delegation as long as it has
+ * the inode cached. This becomes an obvious problem the first time a
+ * client's inode cache approaches the size of the server's total memory.
+ *
+ * For now we avoid this problem by imposing a hard limit on the number
+ * of delegations, which varies according to the server's memory size.
+ */
+static void
+set_max_delegations(void)
+{
+ /*
+ * Allow at most 4 delegations per megabyte of RAM. Quick
+ * estimates suggest that in the worst case (where every delegation
+ * is for a different inode), a delegation could take about 1.5K,
+ * giving a worst case usage of about 6% of memory.
+ */
+ max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
+}
+
/* initialization to perform when the nfsd service is started: */
static void
__nfs4_state_start(void)
{
- time_t grace_time;
+ unsigned long grace_time;
boot_time = get_seconds();
- grace_time = max(user_lease_time, lease_time);
+ grace_time = get_nfs_grace_period();
lease_time = user_lease_time;
in_grace = 1;
- printk("NFSD: starting %ld-second grace period\n", grace_time);
+ printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
+ grace_time/HZ);
laundry_wq = create_singlethread_workqueue("nfsd4");
- queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
+ queue_delayed_work(laundry_wq, &laundromat_work, grace_time);
+ set_max_delegations();
}
int
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 15809dfd88a5..b3d55c6747fd 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -56,6 +56,8 @@
#include <linux/nfsd_idmap.h>
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
+#include <linux/sunrpc/gss_api.h>
+#include <linux/sunrpc/svcauth_gss.h>
#define NFSDDBG_FACILITY NFSDDBG_XDR
@@ -819,6 +821,23 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
}
static __be32
+nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
+ struct nfsd4_secinfo *secinfo)
+{
+ DECODE_HEAD;
+
+ READ_BUF(4);
+ READ32(secinfo->si_namelen);
+ READ_BUF(secinfo->si_namelen);
+ SAVEMEM(secinfo->si_name, secinfo->si_namelen);
+ status = check_filename(secinfo->si_name, secinfo->si_namelen,
+ nfserr_noent);
+ if (status)
+ return status;
+ DECODE_TAIL;
+}
+
+static __be32
nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
{
DECODE_HEAD;
@@ -1131,6 +1150,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
case OP_SAVEFH:
op->status = nfs_ok;
break;
+ case OP_SECINFO:
+ op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
+ break;
case OP_SETATTR:
op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
break;
@@ -1296,7 +1318,7 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *
char *path, *rootpath;
fh_init(&tmp_fh, NFS4_FHSIZE);
- *stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
+ *stat = exp_pseudoroot(rqstp, &tmp_fh);
if (*stat)
return NULL;
rootpath = tmp_fh.fh_export->ex_path;
@@ -1847,11 +1869,19 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
if (d_mountpoint(dentry)) {
int err;
+ /*
+ * Why the heck aren't we just using nfsd_lookup??
+ * Different "."/".." handling? Something else?
+ * At least, add a comment here to explain....
+ */
err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
if (err) {
nfserr = nfserrno(err);
goto out_put;
}
+ nfserr = check_nfsd_access(exp, cd->rd_rqstp);
+ if (nfserr)
+ goto out_put;
}
nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
@@ -2419,6 +2449,72 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
}
}
+static void
+nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, int nfserr,
+ struct nfsd4_secinfo *secinfo)
+{
+ int i = 0;
+ struct svc_export *exp = secinfo->si_exp;
+ u32 nflavs;
+ struct exp_flavor_info *flavs;
+ struct exp_flavor_info def_flavs[2];
+ ENCODE_HEAD;
+
+ if (nfserr)
+ goto out;
+ if (exp->ex_nflavors) {
+ flavs = exp->ex_flavors;
+ nflavs = exp->ex_nflavors;
+ } else { /* Handling of some defaults in absence of real secinfo: */
+ flavs = def_flavs;
+ if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
+ nflavs = 2;
+ flavs[0].pseudoflavor = RPC_AUTH_UNIX;
+ flavs[1].pseudoflavor = RPC_AUTH_NULL;
+ } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
+ nflavs = 1;
+ flavs[0].pseudoflavor
+ = svcauth_gss_flavor(exp->ex_client);
+ } else {
+ nflavs = 1;
+ flavs[0].pseudoflavor
+ = exp->ex_client->flavour->flavour;
+ }
+ }
+
+ RESERVE_SPACE(4);
+ WRITE32(nflavs);
+ ADJUST_ARGS();
+ for (i = 0; i < nflavs; i++) {
+ u32 flav = flavs[i].pseudoflavor;
+ struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+
+ if (gm) {
+ RESERVE_SPACE(4);
+ WRITE32(RPC_AUTH_GSS);
+ ADJUST_ARGS();
+ RESERVE_SPACE(4 + gm->gm_oid.len);
+ WRITE32(gm->gm_oid.len);
+ WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+ ADJUST_ARGS();
+ RESERVE_SPACE(4);
+ WRITE32(0); /* qop */
+ ADJUST_ARGS();
+ RESERVE_SPACE(4);
+ WRITE32(gss_pseudoflavor_to_service(gm, flav));
+ ADJUST_ARGS();
+ gss_mech_put(gm);
+ } else {
+ RESERVE_SPACE(4);
+ WRITE32(flav);
+ ADJUST_ARGS();
+ }
+ }
+out:
+ if (exp)
+ exp_put(exp);
+}
+
/*
* The SETATTR encode routine is special -- it always encodes a bitmap,
* regardless of the error status.
@@ -2559,6 +2655,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
break;
case OP_SAVEFH:
break;
+ case OP_SECINFO:
+ nfsd4_encode_secinfo(resp, op->status, &op->u.secinfo);
+ break;
case OP_SETATTR:
nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
break;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 71c686dc7257..baac89d917ca 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -35,7 +35,6 @@
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
-#include <linux/nfsd/interface.h>
#include <asm/uaccess.h>
@@ -245,7 +244,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
}
exp_readunlock();
if (err == 0)
- err = res->fh_size + (int)&((struct knfsd_fh*)0)->fh_base;
+ err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
out:
return err;
}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 6ca2d24fc216..0eb464a39aae 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -15,10 +15,12 @@
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/dcache.h>
+#include <linux/exportfs.h>
#include <linux/mount.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svcauth_gss.h>
#include <linux/nfsd/nfsd.h>
#define NFSDDBG_FACILITY NFSDDBG_FH
@@ -27,10 +29,6 @@
static int nfsd_nr_verified;
static int nfsd_nr_put;
-extern struct export_operations export_op_default;
-
-#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
/*
* our acceptability function.
* if NOSUBTREECHECK, accept anything
@@ -123,8 +121,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
int data_left = fh->fh_size/4;
error = nfserr_stale;
- if (rqstp->rq_client == NULL)
- goto out;
if (rqstp->rq_vers > 2)
error = nfserr_badhandle;
if (rqstp->rq_vers == 4 && fh->fh_size == 0)
@@ -148,7 +144,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
fh->fh_fsid[1] = fh->fh_fsid[2];
}
if ((data_left -= len)<0) goto out;
- exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle);
+ exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap);
datap += len;
} else {
dev_t xdev;
@@ -159,19 +155,17 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
xdev = old_decode_dev(fh->ofh_xdev);
xino = u32_to_ino_t(fh->ofh_xino);
mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
- exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
- &rqstp->rq_chandle);
+ exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
}
- if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
- || PTR_ERR(exp) == -ETIMEDOUT)) {
- error = nfserrno(PTR_ERR(exp));
+ error = nfserr_stale;
+ if (PTR_ERR(exp) == -ENOENT)
goto out;
- }
- error = nfserr_stale;
- if (!exp || IS_ERR(exp))
+ if (IS_ERR(exp)) {
+ error = nfserrno(PTR_ERR(exp));
goto out;
+ }
/* Check if the request originated from a secure port. */
error = nfserr_perm;
@@ -211,11 +205,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
if (fileid_type == 0)
dentry = dget(exp->ex_dentry);
else {
- struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
- dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
- datap, data_left,
- fileid_type,
- nfsd_acceptable, exp);
+ dentry = exportfs_decode_fh(exp->ex_mnt, datap,
+ data_left, fileid_type,
+ nfsd_acceptable, exp);
}
if (dentry == NULL)
goto out;
@@ -257,8 +249,19 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
if (error)
goto out;
+ if (!(access & MAY_LOCK)) {
+ /*
+ * pseudoflavor restrictions are not enforced on NLM,
+ * which clients virtually always use auth_sys for,
+ * even while using RPCSEC_GSS for NFS.
+ */
+ error = check_nfsd_access(exp, rqstp);
+ if (error)
+ goto out;
+ }
+
/* Finally, check access permissions. */
- error = nfsd_permission(exp, dentry, access);
+ error = nfsd_permission(rqstp, exp, dentry, access);
if (error) {
dprintk("fh_verify: %s/%s permission failure, "
@@ -286,15 +289,13 @@ out:
static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
__u32 *datap, int *maxsize)
{
- struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-
if (dentry == exp->ex_dentry) {
*maxsize = 0;
return 0;
}
- return CALL(nop,encode_fh)(dentry, datap, maxsize,
- !(exp->ex_flags&NFSEXP_NOSUBTREECHECK));
+ return exportfs_encode_fh(dentry, datap, maxsize,
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
}
/*
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index b2c7147aa921..977a71f64e19 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -278,7 +278,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
* echo thing > device-special-file-or-pipe
* by doing a CREATE with type==0
*/
- nfserr = nfsd_permission(newfhp->fh_export,
+ nfserr = nfsd_permission(rqstp,
+ newfhp->fh_export,
newfhp->fh_dentry,
MAY_WRITE|MAY_LOCAL_ACCESS);
if (nfserr && nfserr != nfserr_rofs)
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ff55950efb43..a8c89ae4c743 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/freezer.h>
#include <linux/fs_struct.h>
#include <linux/sunrpc/types.h>
@@ -432,6 +433,7 @@ nfsd(struct svc_rqst *rqstp)
* dirty pages.
*/
current->flags |= PF_LESS_THROTTLE;
+ set_freezable();
/*
* The main request loop
@@ -492,6 +494,15 @@ out:
module_put_and_exit(0);
}
+static __be32 map_new_errors(u32 vers, __be32 nfserr)
+{
+ if (nfserr == nfserr_jukebox && vers == 2)
+ return nfserr_dropit;
+ if (nfserr == nfserr_wrongsec && vers < 4)
+ return nfserr_acces;
+ return nfserr;
+}
+
int
nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
{
@@ -534,6 +545,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
/* Now call the procedure handler, and encode NFS status. */
nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+ nfserr = map_new_errors(rqstp->rq_vers, nfserr);
if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
nfserr = nfserr_dropit;
if (nfserr == nfserr_dropit) {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 945b1cedde2b..e90f4a8a1d01 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -113,7 +113,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
- exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle);
+ exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
if (IS_ERR(exp2)) {
err = PTR_ERR(exp2);
dput(mounts);
@@ -135,21 +135,10 @@ out:
return err;
}
-/*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
- *
- * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_NOHIDE, then the lookup is
- * accepted as it stands and the mounted directory is
- * returned. Otherwise the covered directory is returned.
- * NOTE: this mountpoint crossing is not supported properly by all
- * clients and is explicitly disallowed for NFSv3
- * NeilBrown <neilb@cse.unsw.edu.au>
- */
__be32
-nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
- int len, struct svc_fh *resfh)
+nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ const char *name, int len,
+ struct svc_export **exp_ret, struct dentry **dentry_ret)
{
struct svc_export *exp;
struct dentry *dparent;
@@ -168,8 +157,6 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
exp = fhp->fh_export;
exp_get(exp);
- err = nfserr_acces;
-
/* Lookup the name, but don't follow links */
if (isdotent(name, len)) {
if (len==1)
@@ -190,17 +177,15 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
dput(dentry);
dentry = dp;
- exp2 = exp_parent(exp->ex_client, mnt, dentry,
- &rqstp->rq_chandle);
- if (IS_ERR(exp2)) {
+ exp2 = rqst_exp_parent(rqstp, mnt, dentry);
+ if (PTR_ERR(exp2) == -ENOENT) {
+ dput(dentry);
+ dentry = dget(dparent);
+ } else if (IS_ERR(exp2)) {
host_err = PTR_ERR(exp2);
dput(dentry);
mntput(mnt);
goto out_nfserr;
- }
- if (!exp2) {
- dput(dentry);
- dentry = dget(dparent);
} else {
exp_put(exp);
exp = exp2;
@@ -223,6 +208,41 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
}
}
}
+ *dentry_ret = dentry;
+ *exp_ret = exp;
+ return 0;
+
+out_nfserr:
+ exp_put(exp);
+ return nfserrno(host_err);
+}
+
+/*
+ * Look up one component of a pathname.
+ * N.B. After this call _both_ fhp and resfh need an fh_put
+ *
+ * If the lookup would cross a mountpoint, and the mounted filesystem
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
+ * accepted as it stands and the mounted directory is
+ * returned. Otherwise the covered directory is returned.
+ * NOTE: this mountpoint crossing is not supported properly by all
+ * clients and is explicitly disallowed for NFSv3
+ * NeilBrown <neilb@cse.unsw.edu.au>
+ */
+__be32
+nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ int len, struct svc_fh *resfh)
+{
+ struct svc_export *exp;
+ struct dentry *dentry;
+ __be32 err;
+
+ err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
+ if (err)
+ return err;
+ err = check_nfsd_access(exp, rqstp);
+ if (err)
+ goto out;
/*
* Note: we compose the file handle now, but as the
* dentry may be negative, it may need to be updated.
@@ -230,16 +250,13 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
err = fh_compose(resfh, exp, dentry, fhp);
if (!err && !dentry->d_inode)
err = nfserr_noent;
- dput(dentry);
out:
+ dput(dentry);
exp_put(exp);
return err;
-
-out_nfserr:
- err = nfserrno(host_err);
- goto out;
}
+
/*
* Set various file attributes.
* N.B. After this call fhp needs an fh_put
@@ -311,7 +328,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
/* The size case is special. It changes the file as well as the attributes. */
if (iap->ia_valid & ATTR_SIZE) {
if (iap->ia_size < inode->i_size) {
- err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
+ err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
if (err)
goto out;
}
@@ -435,7 +452,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
/* Get inode */
error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
if (error)
- goto out;
+ return error;
dentry = fhp->fh_dentry;
inode = dentry->d_inode;
@@ -444,33 +461,25 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
if (host_error == -EINVAL) {
- error = nfserr_attrnotsupp;
- goto out;
+ return nfserr_attrnotsupp;
} else if (host_error < 0)
goto out_nfserr;
host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
if (host_error < 0)
- goto out_nfserr;
+ goto out_release;
- if (S_ISDIR(inode->i_mode)) {
+ if (S_ISDIR(inode->i_mode))
host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
- if (host_error < 0)
- goto out_nfserr;
- }
-
- error = nfs_ok;
-out:
+out_release:
posix_acl_release(pacl);
posix_acl_release(dpacl);
- return (error);
out_nfserr:
if (host_error == -EOPNOTSUPP)
- error = nfserr_attrnotsupp;
+ return nfserr_attrnotsupp;
else
- error = nfserrno(host_error);
- goto out;
+ return nfserrno(host_error);
}
static struct posix_acl *
@@ -607,7 +616,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
sresult |= map->access;
- err2 = nfsd_permission(export, dentry, map->how);
+ err2 = nfsd_permission(rqstp, export, dentry, map->how);
switch (err2) {
case nfs_ok:
result |= map->access;
@@ -1034,7 +1043,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
__be32 err;
if (file) {
- err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+ err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
MAY_READ|MAY_OWNER_OVERRIDE);
if (err)
goto out;
@@ -1063,7 +1072,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
__be32 err = 0;
if (file) {
- err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+ err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
MAY_WRITE|MAY_OWNER_OVERRIDE);
if (err)
goto out;
@@ -1792,7 +1801,8 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
* Check for a user's access permissions to this inode.
*/
__be32
-nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
+nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+ struct dentry *dentry, int acc)
{
struct inode *inode = dentry->d_inode;
int err;
@@ -1823,7 +1833,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
*/
if (!(acc & MAY_LOCAL_ACCESS))
if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
- if (EX_RDONLY(exp) || IS_RDONLY(inode))
+ if (EX_RDONLY(exp, rqstp) || IS_RDONLY(inode))
return nfserr_rofs;
if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
return nfserr_perm;
diff --git a/fs/nls/Makefile b/fs/nls/Makefile
index a7ade138d684..f499dd7c3905 100644
--- a/fs/nls/Makefile
+++ b/fs/nls/Makefile
@@ -36,11 +36,9 @@ obj-$(CONFIG_NLS_ISO8859_6) += nls_iso8859-6.o
obj-$(CONFIG_NLS_ISO8859_7) += nls_iso8859-7.o
obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o
obj-$(CONFIG_NLS_ISO8859_9) += nls_iso8859-9.o
-obj-$(CONFIG_NLS_ISO8859_10) += nls_iso8859-10.o
obj-$(CONFIG_NLS_ISO8859_13) += nls_iso8859-13.o
obj-$(CONFIG_NLS_ISO8859_14) += nls_iso8859-14.o
obj-$(CONFIG_NLS_ISO8859_15) += nls_iso8859-15.o
obj-$(CONFIG_NLS_KOI8_R) += nls_koi8-r.o
obj-$(CONFIG_NLS_KOI8_U) += nls_koi8-u.o nls_koi8-ru.o
-obj-$(CONFIG_NLS_ABC) += nls_abc.o
obj-$(CONFIG_NLS_UTF8) += nls_utf8.o
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index bff01a54675a..e93c6142b23c 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -21,6 +21,7 @@
*/
#include <linux/dcache.h>
+#include <linux/exportfs.h>
#include <linux/security.h>
#include "attrib.h"
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 19712a7d145f..f5e11f4fa952 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -50,6 +50,8 @@
#include "buffer_head_io.h"
static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+ struct ocfs2_extent_block *eb);
/*
* Structures which describe a path through a btree, and functions to
@@ -117,6 +119,31 @@ static void ocfs2_free_path(struct ocfs2_path *path)
}
/*
+ * All the elements of src into dest. After this call, src could be freed
+ * without affecting dest.
+ *
+ * Both paths should have the same root. Any non-root elements of dest
+ * will be freed.
+ */
+static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
+{
+ int i;
+
+ BUG_ON(path_root_bh(dest) != path_root_bh(src));
+ BUG_ON(path_root_el(dest) != path_root_el(src));
+
+ ocfs2_reinit_path(dest, 1);
+
+ for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
+ dest->p_node[i].bh = src->p_node[i].bh;
+ dest->p_node[i].el = src->p_node[i].el;
+
+ if (dest->p_node[i].bh)
+ get_bh(dest->p_node[i].bh);
+ }
+}
+
+/*
* Make the *dest path the same as src and re-initialize src path to
* have a root only.
*/
@@ -212,10 +239,41 @@ out:
return ret;
}
+/*
+ * Return the index of the extent record which contains cluster #v_cluster.
+ * -1 is returned if it was not found.
+ *
+ * Should work fine on interior and exterior nodes.
+ */
+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
+{
+ int ret = -1;
+ int i;
+ struct ocfs2_extent_rec *rec;
+ u32 rec_end, rec_start, clusters;
+
+ for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
+ rec = &el->l_recs[i];
+
+ rec_start = le32_to_cpu(rec->e_cpos);
+ clusters = ocfs2_rec_clusters(el, rec);
+
+ rec_end = rec_start + clusters;
+
+ if (v_cluster >= rec_start && v_cluster < rec_end) {
+ ret = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
enum ocfs2_contig_type {
CONTIG_NONE = 0,
CONTIG_LEFT,
- CONTIG_RIGHT
+ CONTIG_RIGHT,
+ CONTIG_LEFTRIGHT,
};
@@ -253,6 +311,14 @@ static enum ocfs2_contig_type
{
u64 blkno = le64_to_cpu(insert_rec->e_blkno);
+ /*
+ * Refuse to coalesce extent records with different flag
+ * fields - we don't want to mix unwritten extents with user
+ * data.
+ */
+ if (ext->e_flags != insert_rec->e_flags)
+ return CONTIG_NONE;
+
if (ocfs2_extents_adjacent(ext, insert_rec) &&
ocfs2_block_extent_contig(inode->i_sb, ext, blkno))
return CONTIG_RIGHT;
@@ -277,7 +343,14 @@ enum ocfs2_append_type {
APPEND_TAIL,
};
+enum ocfs2_split_type {
+ SPLIT_NONE = 0,
+ SPLIT_LEFT,
+ SPLIT_RIGHT,
+};
+
struct ocfs2_insert_type {
+ enum ocfs2_split_type ins_split;
enum ocfs2_append_type ins_appending;
enum ocfs2_contig_type ins_contig;
int ins_contig_index;
@@ -285,6 +358,13 @@ struct ocfs2_insert_type {
int ins_tree_depth;
};
+struct ocfs2_merge_ctxt {
+ enum ocfs2_contig_type c_contig_type;
+ int c_has_empty_extent;
+ int c_split_covers_rec;
+ int c_used_tail_recs;
+};
+
/*
* How many free extents have we got before we need more meta data?
*/
@@ -384,13 +464,7 @@ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
eb->h_blkno = cpu_to_le64(first_blkno);
eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
- /* we always use slot zero's suballocator */
- eb->h_suballoc_slot = 0;
-#else
eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
-#endif
eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
eb->h_list.l_count =
cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
@@ -461,7 +535,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
struct inode *inode,
struct buffer_head *fe_bh,
struct buffer_head *eb_bh,
- struct buffer_head *last_eb_bh,
+ struct buffer_head **last_eb_bh,
struct ocfs2_alloc_context *meta_ac)
{
int status, new_blocks, i;
@@ -476,7 +550,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
mlog_entry_void();
- BUG_ON(!last_eb_bh);
+ BUG_ON(!last_eb_bh || !*last_eb_bh);
fe = (struct ocfs2_dinode *) fe_bh->b_data;
@@ -507,7 +581,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
goto bail;
}
- eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+ eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
/* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
@@ -568,7 +642,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
* journal_dirty erroring as it won't unless we've aborted the
* handle (in which case we would never be here) so reserving
* the write with journal_access is all we need to do. */
- status = ocfs2_journal_access(handle, inode, last_eb_bh,
+ status = ocfs2_journal_access(handle, inode, *last_eb_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) {
mlog_errno(status);
@@ -601,10 +675,10 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
* next_leaf on the previously last-extent-block. */
fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
- eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
- status = ocfs2_journal_dirty(handle, last_eb_bh);
+ status = ocfs2_journal_dirty(handle, *last_eb_bh);
if (status < 0)
mlog_errno(status);
status = ocfs2_journal_dirty(handle, fe_bh);
@@ -616,6 +690,14 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
mlog_errno(status);
}
+ /*
+ * Some callers want to track the rightmost leaf so pass it
+ * back here.
+ */
+ brelse(*last_eb_bh);
+ get_bh(new_eb_bhs[0]);
+ *last_eb_bh = new_eb_bhs[0];
+
status = 0;
bail:
if (new_eb_bhs) {
@@ -829,6 +911,87 @@ bail:
}
/*
+ * Grow a b-tree so that it has more records.
+ *
+ * We might shift the tree depth in which case existing paths should
+ * be considered invalid.
+ *
+ * Tree depth after the grow is returned via *final_depth.
+ *
+ * *last_eb_bh will be updated by ocfs2_add_branch().
+ */
+static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
+ struct buffer_head *di_bh, int *final_depth,
+ struct buffer_head **last_eb_bh,
+ struct ocfs2_alloc_context *meta_ac)
+{
+ int ret, shift;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+ int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct buffer_head *bh = NULL;
+
+ BUG_ON(meta_ac == NULL);
+
+ shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
+ if (shift < 0) {
+ ret = shift;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /* We traveled all the way to the bottom of the allocation tree
+ * and didn't find room for any more extents - we need to add
+ * another tree level */
+ if (shift) {
+ BUG_ON(bh);
+ mlog(0, "need to shift tree depth (current = %d)\n", depth);
+
+ /* ocfs2_shift_tree_depth will return us a buffer with
+ * the new extent block (so we can pass that to
+ * ocfs2_add_branch). */
+ ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
+ meta_ac, &bh);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ depth++;
+ if (depth == 1) {
+ /*
+ * Special case: we have room now if we shifted from
+ * tree_depth 0, so no more work needs to be done.
+ *
+ * We won't be calling add_branch, so pass
+ * back *last_eb_bh as the new leaf. At depth
+ * zero, it should always be null so there's
+ * no reason to brelse.
+ */
+ BUG_ON(*last_eb_bh);
+ get_bh(bh);
+ *last_eb_bh = bh;
+ goto out;
+ }
+ }
+
+ /* call ocfs2_add_branch to add the final part of the tree with
+ * the new data. */
+ mlog(0, "add branch. bh = %p\n", bh);
+ ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
+ meta_ac);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+out:
+ if (final_depth)
+ *final_depth = depth;
+ brelse(bh);
+ return ret;
+}
+
+/*
* This is only valid for leaf nodes, which are the only ones that can
* have empty extents anyway.
*/
@@ -934,6 +1097,22 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,
}
+static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el)
+{
+ int size, num_recs = le16_to_cpu(el->l_next_free_rec);
+
+ BUG_ON(num_recs == 0);
+
+ if (ocfs2_is_empty_extent(&el->l_recs[0])) {
+ num_recs--;
+ size = num_recs * sizeof(struct ocfs2_extent_rec);
+ memmove(&el->l_recs[0], &el->l_recs[1], size);
+ memset(&el->l_recs[num_recs], 0,
+ sizeof(struct ocfs2_extent_rec));
+ el->l_next_free_rec = cpu_to_le16(num_recs);
+ }
+}
+
/*
* Create an empty extent record .
*
@@ -1211,6 +1390,10 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
* immediately to their right.
*/
left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
+ if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
+ BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
+ left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
+ }
left_clusters -= le32_to_cpu(left_rec->e_cpos);
left_rec->e_int_clusters = cpu_to_le32(left_clusters);
@@ -1531,10 +1714,16 @@ out:
return ret;
}
+/*
+ * Extend the transaction by enough credits to complete the rotation,
+ * and still leave at least the original number of credits allocated
+ * to this transaction.
+ */
static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
+ int op_credits,
struct ocfs2_path *path)
{
- int credits = (path->p_tree_depth - subtree_depth) * 2 + 1;
+ int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;
if (handle->h_buffer_credits < credits)
return ocfs2_extend_trans(handle, credits);
@@ -1568,6 +1757,29 @@ static int ocfs2_rotate_requires_path_adjustment(struct ocfs2_path *left_path,
return 0;
}
+static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
+{
+ int next_free = le16_to_cpu(el->l_next_free_rec);
+ unsigned int range;
+ struct ocfs2_extent_rec *rec;
+
+ if (next_free == 0)
+ return 0;
+
+ rec = &el->l_recs[0];
+ if (ocfs2_is_empty_extent(rec)) {
+ /* Empty list. */
+ if (next_free == 1)
+ return 0;
+ rec = &el->l_recs[1];
+ }
+
+ range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+ if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
+ return 1;
+ return 0;
+}
+
/*
* Rotate all the records in a btree right one record, starting at insert_cpos.
*
@@ -1586,11 +1798,12 @@ static int ocfs2_rotate_requires_path_adjustment(struct ocfs2_path *left_path,
*/
static int ocfs2_rotate_tree_right(struct inode *inode,
handle_t *handle,
+ enum ocfs2_split_type split,
u32 insert_cpos,
struct ocfs2_path *right_path,
struct ocfs2_path **ret_left_path)
{
- int ret, start;
+ int ret, start, orig_credits = handle->h_buffer_credits;
u32 cpos;
struct ocfs2_path *left_path = NULL;
@@ -1657,9 +1870,9 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
(unsigned long long)
path_leaf_bh(left_path)->b_blocknr);
- if (ocfs2_rotate_requires_path_adjustment(left_path,
+ if (split == SPLIT_NONE &&
+ ocfs2_rotate_requires_path_adjustment(left_path,
insert_cpos)) {
- mlog(0, "Path adjustment required\n");
/*
* We've rotated the tree as much as we
@@ -1687,7 +1900,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
right_path->p_tree_depth);
ret = ocfs2_extend_rotate_transaction(handle, start,
- right_path);
+ orig_credits, right_path);
if (ret) {
mlog_errno(ret);
goto out;
@@ -1700,6 +1913,24 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
goto out;
}
+ if (split != SPLIT_NONE &&
+ ocfs2_leftmost_rec_contains(path_leaf_el(right_path),
+ insert_cpos)) {
+ /*
+ * A rotate moves the rightmost left leaf
+ * record over to the leftmost right leaf
+ * slot. If we're doing an extent split
+ * instead of a real insert, then we have to
+ * check that the extent to be split wasn't
+ * just moved over. If it was, then we can
+ * exit here, passing left_path back -
+ * ocfs2_split_extent() is smart enough to
+ * search both leaves.
+ */
+ *ret_left_path = left_path;
+ goto out_ret_path;
+ }
+
/*
* There is no need to re-read the next right path
* as we know that it'll be our current left
@@ -1722,6 +1953,1031 @@ out_ret_path:
return ret;
}
+static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *path)
+{
+ int i, idx;
+ struct ocfs2_extent_rec *rec;
+ struct ocfs2_extent_list *el;
+ struct ocfs2_extent_block *eb;
+ u32 range;
+
+ /* Path should always be rightmost. */
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+ BUG_ON(eb->h_next_leaf_blk != 0ULL);
+
+ el = &eb->h_list;
+ BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
+ idx = le16_to_cpu(el->l_next_free_rec) - 1;
+ rec = &el->l_recs[idx];
+ range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+
+ for (i = 0; i < path->p_tree_depth; i++) {
+ el = path->p_node[i].el;
+ idx = le16_to_cpu(el->l_next_free_rec) - 1;
+ rec = &el->l_recs[idx];
+
+ rec->e_int_clusters = cpu_to_le32(range);
+ le32_add_cpu(&rec->e_int_clusters, -le32_to_cpu(rec->e_cpos));
+
+ ocfs2_journal_dirty(handle, path->p_node[i].bh);
+ }
+}
+
+static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
+ struct ocfs2_cached_dealloc_ctxt *dealloc,
+ struct ocfs2_path *path, int unlink_start)
+{
+ int ret, i;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+ struct buffer_head *bh;
+
+ for(i = unlink_start; i < path_num_items(path); i++) {
+ bh = path->p_node[i].bh;
+
+ eb = (struct ocfs2_extent_block *)bh->b_data;
+ /*
+ * Not all nodes might have had their final count
+ * decremented by the caller - handle this here.
+ */
+ el = &eb->h_list;
+ if (le16_to_cpu(el->l_next_free_rec) > 1) {
+ mlog(ML_ERROR,
+ "Inode %llu, attempted to remove extent block "
+ "%llu with %u records\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)le64_to_cpu(eb->h_blkno),
+ le16_to_cpu(el->l_next_free_rec));
+
+ ocfs2_journal_dirty(handle, bh);
+ ocfs2_remove_from_cache(inode, bh);
+ continue;
+ }
+
+ el->l_next_free_rec = 0;
+ memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+
+ ocfs2_journal_dirty(handle, bh);
+
+ ret = ocfs2_cache_extent_block_free(dealloc, eb);
+ if (ret)
+ mlog_errno(ret);
+
+ ocfs2_remove_from_cache(inode, bh);
+ }
+}
+
+static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *left_path,
+ struct ocfs2_path *right_path,
+ int subtree_index,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int i;
+ struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;
+ struct ocfs2_extent_list *root_el = left_path->p_node[subtree_index].el;
+ struct ocfs2_extent_list *el;
+ struct ocfs2_extent_block *eb;
+
+ el = path_leaf_el(left_path);
+
+ eb = (struct ocfs2_extent_block *)right_path->p_node[subtree_index + 1].bh->b_data;
+
+ for(i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
+ if (root_el->l_recs[i].e_blkno == eb->h_blkno)
+ break;
+
+ BUG_ON(i >= le16_to_cpu(root_el->l_next_free_rec));
+
+ memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
+ le16_add_cpu(&root_el->l_next_free_rec, -1);
+
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+ eb->h_next_leaf_blk = 0;
+
+ ocfs2_journal_dirty(handle, root_bh);
+ ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+
+ ocfs2_unlink_path(inode, handle, dealloc, right_path,
+ subtree_index + 1);
+}
+
+static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *left_path,
+ struct ocfs2_path *right_path,
+ int subtree_index,
+ struct ocfs2_cached_dealloc_ctxt *dealloc,
+ int *deleted)
+{
+ int ret, i, del_right_subtree = 0, right_has_empty = 0;
+ struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+ struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;
+ struct ocfs2_extent_block *eb;
+
+ *deleted = 0;
+
+ right_leaf_el = path_leaf_el(right_path);
+ left_leaf_el = path_leaf_el(left_path);
+ root_bh = left_path->p_node[subtree_index].bh;
+ BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
+
+ if (!ocfs2_is_empty_extent(&left_leaf_el->l_recs[0]))
+ return 0;
+
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(right_path)->b_data;
+ if (ocfs2_is_empty_extent(&right_leaf_el->l_recs[0])) {
+ /*
+ * It's legal for us to proceed if the right leaf is
+ * the rightmost one and it has an empty extent. There
+ * are two cases to handle - whether the leaf will be
+ * empty after removal or not. If the leaf isn't empty
+ * then just remove the empty extent up front. The
+ * next block will handle empty leaves by flagging
+ * them for unlink.
+ *
+ * Non rightmost leaves will throw -EAGAIN and the
+ * caller can manually move the subtree and retry.
+ */
+
+ if (eb->h_next_leaf_blk != 0ULL)
+ return -EAGAIN;
+
+ if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {
+ ret = ocfs2_journal_access(handle, inode,
+ path_leaf_bh(right_path),
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ocfs2_remove_empty_extent(right_leaf_el);
+ } else
+ right_has_empty = 1;
+ }
+
+ if (eb->h_next_leaf_blk == 0ULL &&
+ le16_to_cpu(right_leaf_el->l_next_free_rec) == 1) {
+ /*
+ * We have to update i_last_eb_blk during the meta
+ * data delete.
+ */
+ ret = ocfs2_journal_access(handle, inode, di_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ del_right_subtree = 1;
+ }
+
+ /*
+ * Getting here with an empty extent in the right path implies
+ * that it's the rightmost path and will be deleted.
+ */
+ BUG_ON(right_has_empty && !del_right_subtree);
+
+ ret = ocfs2_journal_access(handle, inode, root_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
+ ret = ocfs2_journal_access(handle, inode,
+ right_path->p_node[i].bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_journal_access(handle, inode,
+ left_path->p_node[i].bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+ if (!right_has_empty) {
+ /*
+ * Only do this if we're moving a real
+ * record. Otherwise, the action is delayed until
+ * after removal of the right path in which case we
+ * can do a simple shift to remove the empty extent.
+ */
+ ocfs2_rotate_leaf(left_leaf_el, &right_leaf_el->l_recs[0]);
+ memset(&right_leaf_el->l_recs[0], 0,
+ sizeof(struct ocfs2_extent_rec));
+ }
+ if (eb->h_next_leaf_blk == 0ULL) {
+ /*
+ * Move recs over to get rid of empty extent, decrease
+ * next_free. This is allowed to remove the last
+ * extent in our leaf (setting l_next_free_rec to
+ * zero) - the delete code below won't care.
+ */
+ ocfs2_remove_empty_extent(right_leaf_el);
+ }
+
+ ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
+ if (ret)
+ mlog_errno(ret);
+ ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
+ if (ret)
+ mlog_errno(ret);
+
+ if (del_right_subtree) {
+ ocfs2_unlink_subtree(inode, handle, left_path, right_path,
+ subtree_index, dealloc);
+ ocfs2_update_edge_lengths(inode, handle, left_path);
+
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+ di->i_last_eb_blk = eb->h_blkno;
+
+ /*
+ * Removal of the extent in the left leaf was skipped
+ * above so we could delete the right path
+ * 1st.
+ */
+ if (right_has_empty)
+ ocfs2_remove_empty_extent(left_leaf_el);
+
+ ret = ocfs2_journal_dirty(handle, di_bh);
+ if (ret)
+ mlog_errno(ret);
+
+ *deleted = 1;
+ } else
+ ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
+ subtree_index);
+
+out:
+ return ret;
+}
+
+/*
+ * Given a full path, determine what cpos value would return us a path
+ * containing the leaf immediately to the right of the current one.
+ *
+ * Will return zero if the path passed in is already the rightmost path.
+ *
+ * This looks similar, but is subtly different to
+ * ocfs2_find_cpos_for_left_leaf().
+ */
+static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+ struct ocfs2_path *path, u32 *cpos)
+{
+ int i, j, ret = 0;
+ u64 blkno;
+ struct ocfs2_extent_list *el;
+
+ *cpos = 0;
+
+ if (path->p_tree_depth == 0)
+ return 0;
+
+ blkno = path_leaf_bh(path)->b_blocknr;
+
+ /* Start at the tree node just above the leaf and work our way up. */
+ i = path->p_tree_depth - 1;
+ while (i >= 0) {
+ int next_free;
+
+ el = path->p_node[i].el;
+
+ /*
+ * Find the extent record just after the one in our
+ * path.
+ */
+ next_free = le16_to_cpu(el->l_next_free_rec);
+ for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {
+ if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {
+ if (j == (next_free - 1)) {
+ if (i == 0) {
+ /*
+ * We've determined that the
+ * path specified is already
+ * the rightmost one - return a
+ * cpos of zero.
+ */
+ goto out;
+ }
+ /*
+ * The rightmost record points to our
+ * leaf - we need to travel up the
+ * tree one level.
+ */
+ goto next_node;
+ }
+
+ *cpos = le32_to_cpu(el->l_recs[j + 1].e_cpos);
+ goto out;
+ }
+ }
+
+ /*
+ * If we got here, we never found a valid node where
+ * the tree indicated one should be.
+ */
+ ocfs2_error(sb,
+ "Invalid extent tree at extent block %llu\n",
+ (unsigned long long)blkno);
+ ret = -EROFS;
+ goto out;
+
+next_node:
+ blkno = path->p_node[i].bh->b_blocknr;
+ i--;
+ }
+
+out:
+ return ret;
+}
+
+static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
+ handle_t *handle,
+ struct buffer_head *bh,
+ struct ocfs2_extent_list *el)
+{
+ int ret;
+
+ if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+ return 0;
+
+ ret = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ocfs2_remove_empty_extent(el);
+
+ ret = ocfs2_journal_dirty(handle, bh);
+ if (ret)
+ mlog_errno(ret);
+
+out:
+ return ret;
+}
+
+static int __ocfs2_rotate_tree_left(struct inode *inode,
+ handle_t *handle, int orig_credits,
+ struct ocfs2_path *path,
+ struct ocfs2_cached_dealloc_ctxt *dealloc,
+ struct ocfs2_path **empty_extent_path)
+{
+ int ret, subtree_root, deleted;
+ u32 right_cpos;
+ struct ocfs2_path *left_path = NULL;
+ struct ocfs2_path *right_path = NULL;
+
+ BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));
+
+ *empty_extent_path = NULL;
+
+ ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,
+ &right_cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ left_path = ocfs2_new_path(path_root_bh(path),
+ path_root_el(path));
+ if (!left_path) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ocfs2_cp_path(left_path, path);
+
+ right_path = ocfs2_new_path(path_root_bh(path),
+ path_root_el(path));
+ if (!right_path) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ while (right_cpos) {
+ ret = ocfs2_find_path(inode, right_path, right_cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ subtree_root = ocfs2_find_subtree_root(inode, left_path,
+ right_path);
+
+ mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
+ subtree_root,
+ (unsigned long long)
+ right_path->p_node[subtree_root].bh->b_blocknr,
+ right_path->p_tree_depth);
+
+ ret = ocfs2_extend_rotate_transaction(handle, subtree_root,
+ orig_credits, left_path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
+ right_path, subtree_root,
+ dealloc, &deleted);
+ if (ret == -EAGAIN) {
+ /*
+ * The rotation has to temporarily stop due to
+ * the right subtree having an empty
+ * extent. Pass it back to the caller for a
+ * fixup.
+ */
+ *empty_extent_path = right_path;
+ right_path = NULL;
+ goto out;
+ }
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * The subtree rotate might have removed records on
+ * the rightmost edge. If so, then rotation is
+ * complete.
+ */
+ if (deleted)
+ break;
+
+ ocfs2_mv_path(left_path, right_path);
+
+ ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
+ &right_cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+out:
+ ocfs2_free_path(right_path);
+ ocfs2_free_path(left_path);
+
+ return ret;
+}
+
+static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *path,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int ret, subtree_index;
+ u32 cpos;
+ struct ocfs2_path *left_path = NULL;
+ struct ocfs2_dinode *di;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+
+ /*
+ * XXX: This code assumes that the root is an inode, which is
+ * true for now but may change as tree code gets generic.
+ */
+ di = (struct ocfs2_dinode *)path_root_bh(path)->b_data;
+ if (!OCFS2_IS_VALID_DINODE(di)) {
+ ret = -EIO;
+ ocfs2_error(inode->i_sb,
+ "Inode %llu has invalid path root",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ goto out;
+ }
+
+ /*
+ * There's two ways we handle this depending on
+ * whether path is the only existing one.
+ */
+ ret = ocfs2_extend_rotate_transaction(handle, 0,
+ handle->h_buffer_credits,
+ path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_journal_access_path(inode, handle, path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path, &cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (cpos) {
+ /*
+ * We have a path to the left of this one - it needs
+ * an update too.
+ */
+ left_path = ocfs2_new_path(path_root_bh(path),
+ path_root_el(path));
+ if (!left_path) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_find_path(inode, left_path, cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_journal_access_path(inode, handle, left_path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+
+ ocfs2_unlink_subtree(inode, handle, left_path, path,
+ subtree_index, dealloc);
+ ocfs2_update_edge_lengths(inode, handle, left_path);
+
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
+ di->i_last_eb_blk = eb->h_blkno;
+ } else {
+ /*
+ * 'path' is also the leftmost path which
+ * means it must be the only one. This gets
+ * handled differently because we want to
+ * revert the inode back to having extents
+ * in-line.
+ */
+ ocfs2_unlink_path(inode, handle, dealloc, path, 1);
+
+ el = &di->id2.i_list;
+ el->l_tree_depth = 0;
+ el->l_next_free_rec = 0;
+ memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+
+ di->i_last_eb_blk = 0;
+ }
+
+ ocfs2_journal_dirty(handle, path_root_bh(path));
+
+out:
+ ocfs2_free_path(left_path);
+ return ret;
+}
+
+/*
+ * Left rotation of btree records.
+ *
+ * In many ways, this is (unsurprisingly) the opposite of right
+ * rotation. We start at some non-rightmost path containing an empty
+ * extent in the leaf block. The code works its way to the rightmost
+ * path by rotating records to the left in every subtree.
+ *
+ * This is used by any code which reduces the number of extent records
+ * in a leaf. After removal, an empty record should be placed in the
+ * leftmost list position.
+ *
+ * This won't handle a length update of the rightmost path records if
+ * the rightmost tree leaf record is removed so the caller is
+ * responsible for detecting and correcting that.
+ */
+static int ocfs2_rotate_tree_left(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *path,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int ret, orig_credits = handle->h_buffer_credits;
+ struct ocfs2_path *tmp_path = NULL, *restart_path = NULL;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+
+ el = path_leaf_el(path);
+ if (!ocfs2_is_empty_extent(&el->l_recs[0]))
+ return 0;
+
+ if (path->p_tree_depth == 0) {
+rightmost_no_delete:
+ /*
+ * In-inode extents. This is trivially handled, so do
+ * it up front.
+ */
+ ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
+ path_leaf_bh(path),
+ path_leaf_el(path));
+ if (ret)
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * Handle rightmost branch now. There's several cases:
+ * 1) simple rotation leaving records in there. That's trivial.
+ * 2) rotation requiring a branch delete - there's no more
+ * records left. Two cases of this:
+ * a) There are branches to the left.
+ * b) This is also the leftmost (the only) branch.
+ *
+ * 1) is handled via ocfs2_rotate_rightmost_leaf_left()
+ * 2a) we need the left branch so that we can update it with the unlink
+ * 2b) we need to bring the inode back to inline extents.
+ */
+
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+ el = &eb->h_list;
+ if (eb->h_next_leaf_blk == 0) {
+ /*
+ * This gets a bit tricky if we're going to delete the
+ * rightmost path. Get the other cases out of the way
+ * 1st.
+ */
+ if (le16_to_cpu(el->l_next_free_rec) > 1)
+ goto rightmost_no_delete;
+
+ if (le16_to_cpu(el->l_next_free_rec) == 0) {
+ ret = -EIO;
+ ocfs2_error(inode->i_sb,
+ "Inode %llu has empty extent block at %llu",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)le64_to_cpu(eb->h_blkno));
+ goto out;
+ }
+
+ /*
+ * XXX: The caller can not trust "path" any more after
+ * this as it will have been deleted. What do we do?
+ *
+ * In theory the rotate-for-merge code will never get
+ * here because it'll always ask for a rotate in a
+ * nonempty list.
+ */
+
+ ret = ocfs2_remove_rightmost_path(inode, handle, path,
+ dealloc);
+ if (ret)
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * Now we can loop, remembering the path we get from -EAGAIN
+ * and restarting from there.
+ */
+try_rotate:
+ ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits, path,
+ dealloc, &restart_path);
+ if (ret && ret != -EAGAIN) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ while (ret == -EAGAIN) {
+ tmp_path = restart_path;
+ restart_path = NULL;
+
+ ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits,
+ tmp_path, dealloc,
+ &restart_path);
+ if (ret && ret != -EAGAIN) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ocfs2_free_path(tmp_path);
+ tmp_path = NULL;
+
+ if (ret == 0)
+ goto try_rotate;
+ }
+
+out:
+ ocfs2_free_path(tmp_path);
+ ocfs2_free_path(restart_path);
+ return ret;
+}
+
+static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
+ int index)
+{
+ struct ocfs2_extent_rec *rec = &el->l_recs[index];
+ unsigned int size;
+
+ if (rec->e_leaf_clusters == 0) {
+ /*
+ * We consumed all of the merged-from record. An empty
+ * extent cannot exist anywhere but the 1st array
+ * position, so move things over if the merged-from
+ * record doesn't occupy that position.
+ *
+ * This creates a new empty extent so the caller
+ * should be smart enough to have removed any existing
+ * ones.
+ */
+ if (index > 0) {
+ BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+ size = index * sizeof(struct ocfs2_extent_rec);
+ memmove(&el->l_recs[1], &el->l_recs[0], size);
+ }
+
+ /*
+ * Always memset - the caller doesn't check whether it
+ * created an empty extent, so there could be junk in
+ * the other fields.
+ */
+ memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
+ }
+}
+
+/*
+ * Remove split_rec clusters from the record at index and merge them
+ * onto the beginning of the record at index + 1.
+ */
+static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+ handle_t *handle,
+ struct ocfs2_extent_rec *split_rec,
+ struct ocfs2_extent_list *el, int index)
+{
+ int ret;
+ unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+ struct ocfs2_extent_rec *left_rec;
+ struct ocfs2_extent_rec *right_rec;
+
+ BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
+
+ left_rec = &el->l_recs[index];
+ right_rec = &el->l_recs[index + 1];
+
+ ret = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ le16_add_cpu(&left_rec->e_leaf_clusters, -split_clusters);
+
+ le32_add_cpu(&right_rec->e_cpos, -split_clusters);
+ le64_add_cpu(&right_rec->e_blkno,
+ -ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+ le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
+
+ ocfs2_cleanup_merge(el, index);
+
+ ret = ocfs2_journal_dirty(handle, bh);
+ if (ret)
+ mlog_errno(ret);
+
+out:
+ return ret;
+}
+
+/*
+ * Remove split_rec clusters from the record at index and merge them
+ * onto the tail of the record at index - 1.
+ */
+static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+ handle_t *handle,
+ struct ocfs2_extent_rec *split_rec,
+ struct ocfs2_extent_list *el, int index)
+{
+ int ret, has_empty_extent = 0;
+ unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+ struct ocfs2_extent_rec *left_rec;
+ struct ocfs2_extent_rec *right_rec;
+
+ BUG_ON(index <= 0);
+
+ left_rec = &el->l_recs[index - 1];
+ right_rec = &el->l_recs[index];
+ if (ocfs2_is_empty_extent(&el->l_recs[0]))
+ has_empty_extent = 1;
+
+ ret = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (has_empty_extent && index == 1) {
+ /*
+ * The easy case - we can just plop the record right in.
+ */
+ *left_rec = *split_rec;
+
+ has_empty_extent = 0;
+ } else {
+ le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+ }
+
+ le32_add_cpu(&right_rec->e_cpos, split_clusters);
+ le64_add_cpu(&right_rec->e_blkno,
+ ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+ le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
+
+ ocfs2_cleanup_merge(el, index);
+
+ ret = ocfs2_journal_dirty(handle, bh);
+ if (ret)
+ mlog_errno(ret);
+
+out:
+ return ret;
+}
+
+static int ocfs2_try_to_merge_extent(struct inode *inode,
+ handle_t *handle,
+ struct ocfs2_path *left_path,
+ int split_index,
+ struct ocfs2_extent_rec *split_rec,
+ struct ocfs2_cached_dealloc_ctxt *dealloc,
+ struct ocfs2_merge_ctxt *ctxt)
+
+{
+ int ret = 0, delete_tail_recs = 0;
+ struct ocfs2_extent_list *el = path_leaf_el(left_path);
+ struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+
+ BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
+
+ if (ctxt->c_split_covers_rec) {
+ delete_tail_recs++;
+
+ if (ctxt->c_contig_type == CONTIG_LEFTRIGHT ||
+ ctxt->c_has_empty_extent)
+ delete_tail_recs++;
+
+ if (ctxt->c_has_empty_extent) {
+ /*
+ * The merge code will need to create an empty
+ * extent to take the place of the newly
+ * emptied slot. Remove any pre-existing empty
+ * extents - having more than one in a leaf is
+ * illegal.
+ */
+ ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+ dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ split_index--;
+ rec = &el->l_recs[split_index];
+ }
+ }
+
+ if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) {
+ /*
+ * Left-right contig implies this.
+ */
+ BUG_ON(!ctxt->c_split_covers_rec);
+ BUG_ON(split_index == 0);
+
+ /*
+ * Since the leftright insert always covers the entire
+ * extent, this call will delete the insert record
+ * entirely, resulting in an empty extent record added to
+ * the extent block.
+ *
+ * Since the adding of an empty extent shifts
+ * everything back to the right, there's no need to
+ * update split_index here.
+ */
+ ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
+ handle, split_rec, el, split_index);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * We can only get this from logic error above.
+ */
+ BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+ /*
+ * The left merge left us with an empty extent, remove
+ * it.
+ */
+ ret = ocfs2_rotate_tree_left(inode, handle, left_path, dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ split_index--;
+ rec = &el->l_recs[split_index];
+
+ /*
+ * Note that we don't pass split_rec here on purpose -
+ * we've merged it into the left side.
+ */
+ ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
+ handle, rec, el, split_index);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+ ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+ dealloc);
+ /*
+ * Error from this last rotate is not critical, so
+ * print but don't bubble it up.
+ */
+ if (ret)
+ mlog_errno(ret);
+ ret = 0;
+ } else {
+ /*
+ * Merge a record to the left or right.
+ *
+ * 'contig_type' is relative to the existing record,
+ * so for example, if we're "right contig", it's to
+ * the record on the left (hence the left merge).
+ */
+ if (ctxt->c_contig_type == CONTIG_RIGHT) {
+ ret = ocfs2_merge_rec_left(inode,
+ path_leaf_bh(left_path),
+ handle, split_rec, el,
+ split_index);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ } else {
+ ret = ocfs2_merge_rec_right(inode,
+ path_leaf_bh(left_path),
+ handle, split_rec, el,
+ split_index);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+ if (ctxt->c_split_covers_rec) {
+ /*
+ * The merge may have left an empty extent in
+ * our leaf. Try to rotate it away.
+ */
+ ret = ocfs2_rotate_tree_left(inode, handle, left_path,
+ dealloc);
+ if (ret)
+ mlog_errno(ret);
+ ret = 0;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static void ocfs2_subtract_from_rec(struct super_block *sb,
+ enum ocfs2_split_type split,
+ struct ocfs2_extent_rec *rec,
+ struct ocfs2_extent_rec *split_rec)
+{
+ u64 len_blocks;
+
+ len_blocks = ocfs2_clusters_to_blocks(sb,
+ le16_to_cpu(split_rec->e_leaf_clusters));
+
+ if (split == SPLIT_LEFT) {
+ /*
+ * Region is on the left edge of the existing
+ * record.
+ */
+ le32_add_cpu(&rec->e_cpos,
+ le16_to_cpu(split_rec->e_leaf_clusters));
+ le64_add_cpu(&rec->e_blkno, len_blocks);
+ le16_add_cpu(&rec->e_leaf_clusters,
+ -le16_to_cpu(split_rec->e_leaf_clusters));
+ } else {
+ /*
+ * Region is on the right edge of the existing
+ * record.
+ */
+ le16_add_cpu(&rec->e_leaf_clusters,
+ -le16_to_cpu(split_rec->e_leaf_clusters));
+ }
+}
+
/*
* Do the final bits of extent record insertion at the target leaf
* list. If this leaf is part of an allocation tree, it is assumed
@@ -1738,6 +2994,15 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
+ if (insert->ins_split != SPLIT_NONE) {
+ i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
+ BUG_ON(i == -1);
+ rec = &el->l_recs[i];
+ ocfs2_subtract_from_rec(inode->i_sb, insert->ins_split, rec,
+ insert_rec);
+ goto rotate;
+ }
+
/*
* Contiguous insert - either left or right.
*/
@@ -1792,6 +3057,7 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
return;
}
+rotate:
/*
* Ok, we have to rotate.
*
@@ -1815,13 +3081,53 @@ static inline void ocfs2_update_dinode_clusters(struct inode *inode,
spin_unlock(&OCFS2_I(inode)->ip_lock);
}
+static void ocfs2_adjust_rightmost_records(struct inode *inode,
+ handle_t *handle,
+ struct ocfs2_path *path,
+ struct ocfs2_extent_rec *insert_rec)
+{
+ int ret, i, next_free;
+ struct buffer_head *bh;
+ struct ocfs2_extent_list *el;
+ struct ocfs2_extent_rec *rec;
+
+ /*
+ * Update everything except the leaf block.
+ */
+ for (i = 0; i < path->p_tree_depth; i++) {
+ bh = path->p_node[i].bh;
+ el = path->p_node[i].el;
+
+ next_free = le16_to_cpu(el->l_next_free_rec);
+ if (next_free == 0) {
+ ocfs2_error(inode->i_sb,
+ "Dinode %llu has a bad extent list",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ ret = -EIO;
+ return;
+ }
+
+ rec = &el->l_recs[next_free - 1];
+
+ rec->e_int_clusters = insert_rec->e_cpos;
+ le32_add_cpu(&rec->e_int_clusters,
+ le16_to_cpu(insert_rec->e_leaf_clusters));
+ le32_add_cpu(&rec->e_int_clusters,
+ -le32_to_cpu(rec->e_cpos));
+
+ ret = ocfs2_journal_dirty(handle, bh);
+ if (ret)
+ mlog_errno(ret);
+
+ }
+}
+
static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
struct ocfs2_extent_rec *insert_rec,
struct ocfs2_path *right_path,
struct ocfs2_path **ret_left_path)
{
- int ret, i, next_free;
- struct buffer_head *bh;
+ int ret, next_free;
struct ocfs2_extent_list *el;
struct ocfs2_path *left_path = NULL;
@@ -1887,40 +3193,7 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
goto out;
}
- el = path_root_el(right_path);
- bh = path_root_bh(right_path);
- i = 0;
- while (1) {
- struct ocfs2_extent_rec *rec;
-
- next_free = le16_to_cpu(el->l_next_free_rec);
- if (next_free == 0) {
- ocfs2_error(inode->i_sb,
- "Dinode %llu has a bad extent list",
- (unsigned long long)OCFS2_I(inode)->ip_blkno);
- ret = -EIO;
- goto out;
- }
-
- rec = &el->l_recs[next_free - 1];
-
- rec->e_int_clusters = insert_rec->e_cpos;
- le32_add_cpu(&rec->e_int_clusters,
- le16_to_cpu(insert_rec->e_leaf_clusters));
- le32_add_cpu(&rec->e_int_clusters,
- -le32_to_cpu(rec->e_cpos));
-
- ret = ocfs2_journal_dirty(handle, bh);
- if (ret)
- mlog_errno(ret);
-
- /* Don't touch the leaf node */
- if (++i >= right_path->p_tree_depth)
- break;
-
- bh = right_path->p_node[i].bh;
- el = right_path->p_node[i].el;
- }
+ ocfs2_adjust_rightmost_records(inode, handle, right_path, insert_rec);
*ret_left_path = left_path;
ret = 0;
@@ -1931,6 +3204,83 @@ out:
return ret;
}
+static void ocfs2_split_record(struct inode *inode,
+ struct ocfs2_path *left_path,
+ struct ocfs2_path *right_path,
+ struct ocfs2_extent_rec *split_rec,
+ enum ocfs2_split_type split)
+{
+ int index;
+ u32 cpos = le32_to_cpu(split_rec->e_cpos);
+ struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el;
+ struct ocfs2_extent_rec *rec, *tmprec;
+
+ right_el = path_leaf_el(right_path);;
+ if (left_path)
+ left_el = path_leaf_el(left_path);
+
+ el = right_el;
+ insert_el = right_el;
+ index = ocfs2_search_extent_list(el, cpos);
+ if (index != -1) {
+ if (index == 0 && left_path) {
+ BUG_ON(ocfs2_is_empty_extent(&el->l_recs[0]));
+
+ /*
+ * This typically means that the record
+ * started in the left path but moved to the
+ * right as a result of rotation. We either
+ * move the existing record to the left, or we
+ * do the later insert there.
+ *
+ * In this case, the left path should always
+ * exist as the rotate code will have passed
+ * it back for a post-insert update.
+ */
+
+ if (split == SPLIT_LEFT) {
+ /*
+ * It's a left split. Since we know
+ * that the rotate code gave us an
+ * empty extent in the left path, we
+ * can just do the insert there.
+ */
+ insert_el = left_el;
+ } else {
+ /*
+ * Right split - we have to move the
+ * existing record over to the left
+ * leaf. The insert will be into the
+ * newly created empty extent in the
+ * right leaf.
+ */
+ tmprec = &right_el->l_recs[index];
+ ocfs2_rotate_leaf(left_el, tmprec);
+ el = left_el;
+
+ memset(tmprec, 0, sizeof(*tmprec));
+ index = ocfs2_search_extent_list(left_el, cpos);
+ BUG_ON(index == -1);
+ }
+ }
+ } else {
+ BUG_ON(!left_path);
+ BUG_ON(!ocfs2_is_empty_extent(&left_el->l_recs[0]));
+ /*
+ * Left path is easy - we can just allow the insert to
+ * happen.
+ */
+ el = left_el;
+ insert_el = left_el;
+ index = ocfs2_search_extent_list(el, cpos);
+ BUG_ON(index == -1);
+ }
+
+ rec = &el->l_recs[index];
+ ocfs2_subtract_from_rec(inode->i_sb, split, rec, split_rec);
+ ocfs2_rotate_leaf(insert_el, split_rec);
+}
+
/*
* This function only does inserts on an allocation b-tree. For dinode
* lists, ocfs2_insert_at_leaf() is called directly.
@@ -1948,7 +3298,6 @@ static int ocfs2_insert_path(struct inode *inode,
{
int ret, subtree_index;
struct buffer_head *leaf_bh = path_leaf_bh(right_path);
- struct ocfs2_extent_list *el;
/*
* Pass both paths to the journal. The majority of inserts
@@ -1984,9 +3333,18 @@ static int ocfs2_insert_path(struct inode *inode,
}
}
- el = path_leaf_el(right_path);
+ if (insert->ins_split != SPLIT_NONE) {
+ /*
+ * We could call ocfs2_insert_at_leaf() for some types
+ * of splits, but it's easier to just let one seperate
+ * function sort it all out.
+ */
+ ocfs2_split_record(inode, left_path, right_path,
+ insert_rec, insert->ins_split);
+ } else
+ ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path),
+ insert, inode);
- ocfs2_insert_at_leaf(insert_rec, el, insert, inode);
ret = ocfs2_journal_dirty(handle, leaf_bh);
if (ret)
mlog_errno(ret);
@@ -2075,7 +3433,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
* can wind up skipping both of these two special cases...
*/
if (rotate) {
- ret = ocfs2_rotate_tree_right(inode, handle,
+ ret = ocfs2_rotate_tree_right(inode, handle, type->ins_split,
le32_to_cpu(insert_rec->e_cpos),
right_path, &left_path);
if (ret) {
@@ -2100,8 +3458,9 @@ static int ocfs2_do_insert_extent(struct inode *inode,
}
out_update_clusters:
- ocfs2_update_dinode_clusters(inode, di,
- le16_to_cpu(insert_rec->e_leaf_clusters));
+ if (type->ins_split == SPLIT_NONE)
+ ocfs2_update_dinode_clusters(inode, di,
+ le16_to_cpu(insert_rec->e_leaf_clusters));
ret = ocfs2_journal_dirty(handle, di_bh);
if (ret)
@@ -2114,6 +3473,44 @@ out:
return ret;
}
+static enum ocfs2_contig_type
+ocfs2_figure_merge_contig_type(struct inode *inode,
+ struct ocfs2_extent_list *el, int index,
+ struct ocfs2_extent_rec *split_rec)
+{
+ struct ocfs2_extent_rec *rec;
+ enum ocfs2_contig_type ret = CONTIG_NONE;
+
+ /*
+ * We're careful to check for an empty extent record here -
+ * the merge code will know what to do if it sees one.
+ */
+
+ if (index > 0) {
+ rec = &el->l_recs[index - 1];
+ if (index == 1 && ocfs2_is_empty_extent(rec)) {
+ if (split_rec->e_cpos == el->l_recs[index].e_cpos)
+ ret = CONTIG_RIGHT;
+ } else {
+ ret = ocfs2_extent_contig(inode, rec, split_rec);
+ }
+ }
+
+ if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
+ enum ocfs2_contig_type contig_type;
+
+ rec = &el->l_recs[index + 1];
+ contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+
+ if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
+ ret = CONTIG_LEFTRIGHT;
+ else if (ret == CONTIG_NONE)
+ ret = contig_type;
+ }
+
+ return ret;
+}
+
static void ocfs2_figure_contig_type(struct inode *inode,
struct ocfs2_insert_type *insert,
struct ocfs2_extent_list *el,
@@ -2205,6 +3602,8 @@ static int ocfs2_figure_insert_type(struct inode *inode,
struct ocfs2_path *path = NULL;
struct buffer_head *bh = NULL;
+ insert->ins_split = SPLIT_NONE;
+
el = &di->id2.i_list;
insert->ins_tree_depth = le16_to_cpu(el->l_tree_depth);
@@ -2327,9 +3726,10 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
u32 cpos,
u64 start_blk,
u32 new_clusters,
+ u8 flags,
struct ocfs2_alloc_context *meta_ac)
{
- int status, shift;
+ int status;
struct buffer_head *last_eb_bh = NULL;
struct buffer_head *bh = NULL;
struct ocfs2_insert_type insert = {0, };
@@ -2350,6 +3750,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
rec.e_cpos = cpu_to_le32(cpos);
rec.e_blkno = cpu_to_le64(start_blk);
rec.e_leaf_clusters = cpu_to_le16(new_clusters);
+ rec.e_flags = flags;
status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
&insert);
@@ -2364,55 +3765,16 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
insert.ins_free_records, insert.ins_tree_depth);
- /*
- * Avoid growing the tree unless we're out of records and the
- * insert type requres one.
- */
- if (insert.ins_contig != CONTIG_NONE || insert.ins_free_records)
- goto out_add;
-
- shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
- if (shift < 0) {
- status = shift;
- mlog_errno(status);
- goto bail;
- }
-
- /* We traveled all the way to the bottom of the allocation tree
- * and didn't find room for any more extents - we need to add
- * another tree level */
- if (shift) {
- BUG_ON(bh);
- mlog(0, "need to shift tree depth "
- "(current = %d)\n", insert.ins_tree_depth);
-
- /* ocfs2_shift_tree_depth will return us a buffer with
- * the new extent block (so we can pass that to
- * ocfs2_add_branch). */
- status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
- meta_ac, &bh);
- if (status < 0) {
+ if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
+ status = ocfs2_grow_tree(inode, handle, fe_bh,
+ &insert.ins_tree_depth, &last_eb_bh,
+ meta_ac);
+ if (status) {
mlog_errno(status);
goto bail;
}
- insert.ins_tree_depth++;
- /* Special case: we have room now if we shifted from
- * tree_depth 0 */
- if (insert.ins_tree_depth == 1)
- goto out_add;
- }
-
- /* call ocfs2_add_branch to add the final part of the tree with
- * the new data. */
- mlog(0, "add branch. bh = %p\n", bh);
- status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
- meta_ac);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
}
-out_add:
/* Finally, we can add clusters. This might rotate the tree for us. */
status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
if (status < 0)
@@ -2431,7 +3793,720 @@ bail:
return status;
}
-static inline int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
+static void ocfs2_make_right_split_rec(struct super_block *sb,
+ struct ocfs2_extent_rec *split_rec,
+ u32 cpos,
+ struct ocfs2_extent_rec *rec)
+{
+ u32 rec_cpos = le32_to_cpu(rec->e_cpos);
+ u32 rec_range = rec_cpos + le16_to_cpu(rec->e_leaf_clusters);
+
+ memset(split_rec, 0, sizeof(struct ocfs2_extent_rec));
+
+ split_rec->e_cpos = cpu_to_le32(cpos);
+ split_rec->e_leaf_clusters = cpu_to_le16(rec_range - cpos);
+
+ split_rec->e_blkno = rec->e_blkno;
+ le64_add_cpu(&split_rec->e_blkno,
+ ocfs2_clusters_to_blocks(sb, cpos - rec_cpos));
+
+ split_rec->e_flags = rec->e_flags;
+}
+
+static int ocfs2_split_and_insert(struct inode *inode,
+ handle_t *handle,
+ struct ocfs2_path *path,
+ struct buffer_head *di_bh,
+ struct buffer_head **last_eb_bh,
+ int split_index,
+ struct ocfs2_extent_rec *orig_split_rec,
+ struct ocfs2_alloc_context *meta_ac)
+{
+ int ret = 0, depth;
+ unsigned int insert_range, rec_range, do_leftright = 0;
+ struct ocfs2_extent_rec tmprec;
+ struct ocfs2_extent_list *rightmost_el;
+ struct ocfs2_extent_rec rec;
+ struct ocfs2_extent_rec split_rec = *orig_split_rec;
+ struct ocfs2_insert_type insert;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_dinode *di;
+
+leftright:
+ /*
+ * Store a copy of the record on the stack - it might move
+ * around as the tree is manipulated below.
+ */
+ rec = path_leaf_el(path)->l_recs[split_index];
+
+ di = (struct ocfs2_dinode *)di_bh->b_data;
+ rightmost_el = &di->id2.i_list;
+
+ depth = le16_to_cpu(rightmost_el->l_tree_depth);
+ if (depth) {
+ BUG_ON(!(*last_eb_bh));
+ eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
+ rightmost_el = &eb->h_list;
+ }
+
+ if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+ le16_to_cpu(rightmost_el->l_count)) {
+ int old_depth = depth;
+
+ ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh,
+ meta_ac);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (old_depth != depth) {
+ eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
+ rightmost_el = &eb->h_list;
+ }
+ }
+
+ memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+ insert.ins_appending = APPEND_NONE;
+ insert.ins_contig = CONTIG_NONE;
+ insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+ - le16_to_cpu(rightmost_el->l_next_free_rec);
+ insert.ins_tree_depth = depth;
+
+ insert_range = le32_to_cpu(split_rec.e_cpos) +
+ le16_to_cpu(split_rec.e_leaf_clusters);
+ rec_range = le32_to_cpu(rec.e_cpos) +
+ le16_to_cpu(rec.e_leaf_clusters);
+
+ if (split_rec.e_cpos == rec.e_cpos) {
+ insert.ins_split = SPLIT_LEFT;
+ } else if (insert_range == rec_range) {
+ insert.ins_split = SPLIT_RIGHT;
+ } else {
+ /*
+ * Left/right split. We fake this as a right split
+ * first and then make a second pass as a left split.
+ */
+ insert.ins_split = SPLIT_RIGHT;
+
+ ocfs2_make_right_split_rec(inode->i_sb, &tmprec, insert_range,
+ &rec);
+
+ split_rec = tmprec;
+
+ BUG_ON(do_leftright);
+ do_leftright = 1;
+ }
+
+ ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec,
+ &insert);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (do_leftright == 1) {
+ u32 cpos;
+ struct ocfs2_extent_list *el;
+
+ do_leftright++;
+ split_rec = *orig_split_rec;
+
+ ocfs2_reinit_path(path, 1);
+
+ cpos = le32_to_cpu(split_rec.e_cpos);
+ ret = ocfs2_find_path(inode, path, cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ el = path_leaf_el(path);
+ split_index = ocfs2_search_extent_list(el, cpos);
+ goto leftright;
+ }
+out:
+
+ return ret;
+}
+
+/*
+ * Mark part or all of the extent record at split_index in the leaf
+ * pointed to by path as written. This removes the unwritten
+ * extent flag.
+ *
+ * Care is taken to handle contiguousness so as to not grow the tree.
+ *
+ * meta_ac is not strictly necessary - we only truly need it if growth
+ * of the tree is required. All other cases will degrade into a less
+ * optimal tree layout.
+ *
+ * last_eb_bh should be the rightmost leaf block for any inode with a
+ * btree. Since a split may grow the tree or a merge might shrink it, the caller cannot trust the contents of that buffer after this call.
+ *
+ * This code is optimized for readability - several passes might be
+ * made over certain portions of the tree. All of those blocks will
+ * have been brought into cache (and pinned via the journal), so the
+ * extra overhead is not expressed in terms of disk reads.
+ */
+static int __ocfs2_mark_extent_written(struct inode *inode,
+ struct buffer_head *di_bh,
+ handle_t *handle,
+ struct ocfs2_path *path,
+ int split_index,
+ struct ocfs2_extent_rec *split_rec,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int ret = 0;
+ struct ocfs2_extent_list *el = path_leaf_el(path);
+ struct buffer_head *eb_bh, *last_eb_bh = NULL;
+ struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+ struct ocfs2_merge_ctxt ctxt;
+ struct ocfs2_extent_list *rightmost_el;
+
+ if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
+ ret = -EIO;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
+ ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
+ (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
+ ret = -EIO;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ eb_bh = path_leaf_bh(path);
+ ret = ocfs2_journal_access(handle, inode, eb_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
+ split_index,
+ split_rec);
+
+ /*
+ * The core merge / split code wants to know how much room is
+ * left in this inodes allocation tree, so we pass the
+ * rightmost extent list.
+ */
+ if (path->p_tree_depth) {
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+
+ ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ le64_to_cpu(di->i_last_eb_blk),
+ &last_eb_bh, OCFS2_BH_CACHED, inode);
+ if (ret) {
+ mlog_exit(ret);
+ goto out;
+ }
+
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ ret = -EROFS;
+ goto out;
+ }
+
+ rightmost_el = &eb->h_list;
+ } else
+ rightmost_el = path_root_el(path);
+
+ ctxt.c_used_tail_recs = le16_to_cpu(rightmost_el->l_next_free_rec);
+ if (ctxt.c_used_tail_recs > 0 &&
+ ocfs2_is_empty_extent(&rightmost_el->l_recs[0]))
+ ctxt.c_used_tail_recs--;
+
+ if (rec->e_cpos == split_rec->e_cpos &&
+ rec->e_leaf_clusters == split_rec->e_leaf_clusters)
+ ctxt.c_split_covers_rec = 1;
+ else
+ ctxt.c_split_covers_rec = 0;
+
+ ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]);
+
+ mlog(0, "index: %d, contig: %u, used_tail_recs: %u, "
+ "has_empty: %u, split_covers: %u\n", split_index,
+ ctxt.c_contig_type, ctxt.c_used_tail_recs,
+ ctxt.c_has_empty_extent, ctxt.c_split_covers_rec);
+
+ if (ctxt.c_contig_type == CONTIG_NONE) {
+ if (ctxt.c_split_covers_rec)
+ el->l_recs[split_index] = *split_rec;
+ else
+ ret = ocfs2_split_and_insert(inode, handle, path, di_bh,
+ &last_eb_bh, split_index,
+ split_rec, meta_ac);
+ if (ret)
+ mlog_errno(ret);
+ } else {
+ ret = ocfs2_try_to_merge_extent(inode, handle, path,
+ split_index, split_rec,
+ dealloc, &ctxt);
+ if (ret)
+ mlog_errno(ret);
+ }
+
+ ocfs2_journal_dirty(handle, eb_bh);
+
+out:
+ brelse(last_eb_bh);
+ return ret;
+}
+
+/*
+ * Mark the already-existing extent at cpos as written for len clusters.
+ *
+ * If the existing extent is larger than the request, initiate a
+ * split. An attempt will be made at merging with adjacent extents.
+ *
+ * The caller is responsible for passing down meta_ac if we'll need it.
+ */
+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+ handle_t *handle, u32 cpos, u32 len, u32 phys,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int ret, index;
+ u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
+ struct ocfs2_extent_rec split_rec;
+ struct ocfs2_path *left_path = NULL;
+ struct ocfs2_extent_list *el;
+
+ mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
+ inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
+
+ if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
+ ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
+ "that are being written to, but the feature bit "
+ "is not set in the super block.",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ ret = -EROFS;
+ goto out;
+ }
+
+ /*
+ * XXX: This should be fixed up so that we just re-insert the
+ * next extent records.
+ */
+ ocfs2_extent_map_trunc(inode, 0);
+
+ left_path = ocfs2_new_inode_path(di_bh);
+ if (!left_path) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_find_path(inode, left_path, cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ el = path_leaf_el(left_path);
+
+ index = ocfs2_search_extent_list(el, cpos);
+ if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+ ocfs2_error(inode->i_sb,
+ "Inode %llu has an extent at cpos %u which can no "
+ "longer be found.\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+ ret = -EROFS;
+ goto out;
+ }
+
+ memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
+ split_rec.e_cpos = cpu_to_le32(cpos);
+ split_rec.e_leaf_clusters = cpu_to_le16(len);
+ split_rec.e_blkno = cpu_to_le64(start_blkno);
+ split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
+ split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
+
+ ret = __ocfs2_mark_extent_written(inode, di_bh, handle, left_path,
+ index, &split_rec, meta_ac, dealloc);
+ if (ret)
+ mlog_errno(ret);
+
+out:
+ ocfs2_free_path(left_path);
+ return ret;
+}
+
+static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
+ handle_t *handle, struct ocfs2_path *path,
+ int index, u32 new_range,
+ struct ocfs2_alloc_context *meta_ac)
+{
+ int ret, depth, credits = handle->h_buffer_credits;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+ struct buffer_head *last_eb_bh = NULL;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *rightmost_el, *el;
+ struct ocfs2_extent_rec split_rec;
+ struct ocfs2_extent_rec *rec;
+ struct ocfs2_insert_type insert;
+
+ /*
+ * Setup the record to split before we grow the tree.
+ */
+ el = path_leaf_el(path);
+ rec = &el->l_recs[index];
+ ocfs2_make_right_split_rec(inode->i_sb, &split_rec, new_range, rec);
+
+ depth = path->p_tree_depth;
+ if (depth > 0) {
+ ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ le64_to_cpu(di->i_last_eb_blk),
+ &last_eb_bh, OCFS2_BH_CACHED, inode);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ rightmost_el = &eb->h_list;
+ } else
+ rightmost_el = path_leaf_el(path);
+
+ credits += path->p_tree_depth + ocfs2_extend_meta_needed(di);
+ ret = ocfs2_extend_trans(handle, credits);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
+ le16_to_cpu(rightmost_el->l_count)) {
+ int old_depth = depth;
+
+ ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, &last_eb_bh,
+ meta_ac);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (old_depth != depth) {
+ eb = (struct ocfs2_extent_block *)last_eb_bh->b_data;
+ rightmost_el = &eb->h_list;
+ }
+ }
+
+ memset(&insert, 0, sizeof(struct ocfs2_insert_type));
+ insert.ins_appending = APPEND_NONE;
+ insert.ins_contig = CONTIG_NONE;
+ insert.ins_split = SPLIT_RIGHT;
+ insert.ins_free_records = le16_to_cpu(rightmost_el->l_count)
+ - le16_to_cpu(rightmost_el->l_next_free_rec);
+ insert.ins_tree_depth = depth;
+
+ ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec, &insert);
+ if (ret)
+ mlog_errno(ret);
+
+out:
+ brelse(last_eb_bh);
+ return ret;
+}
+
+static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *path, int index,
+ struct ocfs2_cached_dealloc_ctxt *dealloc,
+ u32 cpos, u32 len)
+{
+ int ret;
+ u32 left_cpos, rec_range, trunc_range;
+ int wants_rotate = 0, is_rightmost_tree_rec = 0;
+ struct super_block *sb = inode->i_sb;
+ struct ocfs2_path *left_path = NULL;
+ struct ocfs2_extent_list *el = path_leaf_el(path);
+ struct ocfs2_extent_rec *rec;
+ struct ocfs2_extent_block *eb;
+
+ if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) {
+ ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ index--;
+ }
+
+ if (index == (le16_to_cpu(el->l_next_free_rec) - 1) &&
+ path->p_tree_depth) {
+ /*
+ * Check whether this is the rightmost tree record. If
+ * we remove all of this record or part of its right
+ * edge then an update of the record lengths above it
+ * will be required.
+ */
+ eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
+ if (eb->h_next_leaf_blk == 0)
+ is_rightmost_tree_rec = 1;
+ }
+
+ rec = &el->l_recs[index];
+ if (index == 0 && path->p_tree_depth &&
+ le32_to_cpu(rec->e_cpos) == cpos) {
+ /*
+ * Changing the leftmost offset (via partial or whole
+ * record truncate) of an interior (or rightmost) path
+ * means we have to update the subtree that is formed
+ * by this leaf and the one to it's left.
+ *
+ * There are two cases we can skip:
+ * 1) Path is the leftmost one in our inode tree.
+ * 2) The leaf is rightmost and will be empty after
+ * we remove the extent record - the rotate code
+ * knows how to update the newly formed edge.
+ */
+
+ ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path,
+ &left_cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (left_cpos && le16_to_cpu(el->l_next_free_rec) > 1) {
+ left_path = ocfs2_new_path(path_root_bh(path),
+ path_root_el(path));
+ if (!left_path) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_find_path(inode, left_path, left_cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+ }
+
+ ret = ocfs2_extend_rotate_transaction(handle, 0,
+ handle->h_buffer_credits,
+ path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_journal_access_path(inode, handle, path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_journal_access_path(inode, handle, left_path);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ rec_range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+ trunc_range = cpos + len;
+
+ if (le32_to_cpu(rec->e_cpos) == cpos && rec_range == trunc_range) {
+ int next_free;
+
+ memset(rec, 0, sizeof(*rec));
+ ocfs2_cleanup_merge(el, index);
+ wants_rotate = 1;
+
+ next_free = le16_to_cpu(el->l_next_free_rec);
+ if (is_rightmost_tree_rec && next_free > 1) {
+ /*
+ * We skip the edge update if this path will
+ * be deleted by the rotate code.
+ */
+ rec = &el->l_recs[next_free - 1];
+ ocfs2_adjust_rightmost_records(inode, handle, path,
+ rec);
+ }
+ } else if (le32_to_cpu(rec->e_cpos) == cpos) {
+ /* Remove leftmost portion of the record. */
+ le32_add_cpu(&rec->e_cpos, len);
+ le64_add_cpu(&rec->e_blkno, ocfs2_clusters_to_blocks(sb, len));
+ le16_add_cpu(&rec->e_leaf_clusters, -len);
+ } else if (rec_range == trunc_range) {
+ /* Remove rightmost portion of the record */
+ le16_add_cpu(&rec->e_leaf_clusters, -len);
+ if (is_rightmost_tree_rec)
+ ocfs2_adjust_rightmost_records(inode, handle, path, rec);
+ } else {
+ /* Caller should have trapped this. */
+ mlog(ML_ERROR, "Inode %llu: Invalid record truncate: (%u, %u) "
+ "(%u, %u)\n", (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ le32_to_cpu(rec->e_cpos),
+ le16_to_cpu(rec->e_leaf_clusters), cpos, len);
+ BUG();
+ }
+
+ if (left_path) {
+ int subtree_index;
+
+ subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+ ocfs2_complete_edge_insert(inode, handle, left_path, path,
+ subtree_index);
+ }
+
+ ocfs2_journal_dirty(handle, path_leaf_bh(path));
+
+ ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+out:
+ ocfs2_free_path(left_path);
+ return ret;
+}
+
+int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+ u32 cpos, u32 len, handle_t *handle,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int ret, index;
+ u32 rec_range, trunc_range;
+ struct ocfs2_extent_rec *rec;
+ struct ocfs2_extent_list *el;
+ struct ocfs2_path *path;
+
+ ocfs2_extent_map_trunc(inode, 0);
+
+ path = ocfs2_new_inode_path(di_bh);
+ if (!path) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_find_path(inode, path, cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ el = path_leaf_el(path);
+ index = ocfs2_search_extent_list(el, cpos);
+ if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+ ocfs2_error(inode->i_sb,
+ "Inode %llu has an extent at cpos %u which can no "
+ "longer be found.\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+ ret = -EROFS;
+ goto out;
+ }
+
+ /*
+ * We have 3 cases of extent removal:
+ * 1) Range covers the entire extent rec
+ * 2) Range begins or ends on one edge of the extent rec
+ * 3) Range is in the middle of the extent rec (no shared edges)
+ *
+ * For case 1 we remove the extent rec and left rotate to
+ * fill the hole.
+ *
+ * For case 2 we just shrink the existing extent rec, with a
+ * tree update if the shrinking edge is also the edge of an
+ * extent block.
+ *
+ * For case 3 we do a right split to turn the extent rec into
+ * something case 2 can handle.
+ */
+ rec = &el->l_recs[index];
+ rec_range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
+ trunc_range = cpos + len;
+
+ BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range);
+
+ mlog(0, "Inode %llu, remove (cpos %u, len %u). Existing index %d "
+ "(cpos %u, len %u)\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos, len, index,
+ le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec));
+
+ if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {
+ ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
+ cpos, len);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ } else {
+ ret = ocfs2_split_tree(inode, di_bh, handle, path, index,
+ trunc_range, meta_ac);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * The split could have manipulated the tree enough to
+ * move the record location, so we have to look for it again.
+ */
+ ocfs2_reinit_path(path, 1);
+
+ ret = ocfs2_find_path(inode, path, cpos);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ el = path_leaf_el(path);
+ index = ocfs2_search_extent_list(el, cpos);
+ if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
+ ocfs2_error(inode->i_sb,
+ "Inode %llu: split at cpos %u lost record.",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ cpos);
+ ret = -EROFS;
+ goto out;
+ }
+
+ /*
+ * Double check our values here. If anything is fishy,
+ * it's easier to catch it at the top level.
+ */
+ rec = &el->l_recs[index];
+ rec_range = le32_to_cpu(rec->e_cpos) +
+ ocfs2_rec_clusters(el, rec);
+ if (rec_range != trunc_range) {
+ ocfs2_error(inode->i_sb,
+ "Inode %llu: error after split at cpos %u"
+ "trunc len %u, existing record is (%u,%u)",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ cpos, len, le32_to_cpu(rec->e_cpos),
+ ocfs2_rec_clusters(el, rec));
+ ret = -EROFS;
+ goto out;
+ }
+
+ ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
+ cpos, len);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+out:
+ ocfs2_free_path(path);
+ return ret;
+}
+
+int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
{
struct buffer_head *tl_bh = osb->osb_tl_bh;
struct ocfs2_dinode *di;
@@ -2464,10 +4539,10 @@ static int ocfs2_truncate_log_can_coalesce(struct ocfs2_truncate_log *tl,
return current_tail == new_start;
}
-static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
- handle_t *handle,
- u64 start_blk,
- unsigned int num_clusters)
+int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+ handle_t *handle,
+ u64 start_blk,
+ unsigned int num_clusters)
{
int status, index;
unsigned int start_cluster, tl_count;
@@ -2623,7 +4698,7 @@ bail:
}
/* Expects you to already be holding tl_inode->i_mutex */
-static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
+int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
{
int status;
unsigned int num_to_flush;
@@ -2957,6 +5032,219 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
return status;
}
+/*
+ * Delayed de-allocation of suballocator blocks.
+ *
+ * Some sets of block de-allocations might involve multiple suballocator inodes.
+ *
+ * The locking for this can get extremely complicated, especially when
+ * the suballocator inodes to delete from aren't known until deep
+ * within an unrelated codepath.
+ *
+ * ocfs2_extent_block structures are a good example of this - an inode
+ * btree could have been grown by any number of nodes each allocating
+ * out of their own suballoc inode.
+ *
+ * These structures allow the delay of block de-allocation until a
+ * later time, when locking of multiple cluster inodes won't cause
+ * deadlock.
+ */
+
+/*
+ * Describes a single block free from a suballocator
+ */
+struct ocfs2_cached_block_free {
+ struct ocfs2_cached_block_free *free_next;
+ u64 free_blk;
+ unsigned int free_bit;
+};
+
+struct ocfs2_per_slot_free_list {
+ struct ocfs2_per_slot_free_list *f_next_suballocator;
+ int f_inode_type;
+ int f_slot;
+ struct ocfs2_cached_block_free *f_first;
+};
+
+static int ocfs2_free_cached_items(struct ocfs2_super *osb,
+ int sysfile_type,
+ int slot,
+ struct ocfs2_cached_block_free *head)
+{
+ int ret;
+ u64 bg_blkno;
+ handle_t *handle;
+ struct inode *inode;
+ struct buffer_head *di_bh = NULL;
+ struct ocfs2_cached_block_free *tmp;
+
+ inode = ocfs2_get_system_file_inode(osb, sysfile_type, slot);
+ if (!inode) {
+ ret = -EINVAL;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ mutex_lock(&inode->i_mutex);
+
+ ret = ocfs2_meta_lock(inode, &di_bh, 1);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_mutex;
+ }
+
+ handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ mlog_errno(ret);
+ goto out_unlock;
+ }
+
+ while (head) {
+ bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
+ head->free_bit);
+ mlog(0, "Free bit: (bit %u, blkno %llu)\n",
+ head->free_bit, (unsigned long long)head->free_blk);
+
+ ret = ocfs2_free_suballoc_bits(handle, inode, di_bh,
+ head->free_bit, bg_blkno, 1);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_journal;
+ }
+
+ ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_journal;
+ }
+
+ tmp = head;
+ head = head->free_next;
+ kfree(tmp);
+ }
+
+out_journal:
+ ocfs2_commit_trans(osb, handle);
+
+out_unlock:
+ ocfs2_meta_unlock(inode, 1);
+ brelse(di_bh);
+out_mutex:
+ mutex_unlock(&inode->i_mutex);
+ iput(inode);
+out:
+ while(head) {
+ /* Premature exit may have left some dangling items. */
+ tmp = head;
+ head = head->free_next;
+ kfree(tmp);
+ }
+
+ return ret;
+}
+
+int ocfs2_run_deallocs(struct ocfs2_super *osb,
+ struct ocfs2_cached_dealloc_ctxt *ctxt)
+{
+ int ret = 0, ret2;
+ struct ocfs2_per_slot_free_list *fl;
+
+ if (!ctxt)
+ return 0;
+
+ while (ctxt->c_first_suballocator) {
+ fl = ctxt->c_first_suballocator;
+
+ if (fl->f_first) {
+ mlog(0, "Free items: (type %u, slot %d)\n",
+ fl->f_inode_type, fl->f_slot);
+ ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
+ fl->f_slot, fl->f_first);
+ if (ret2)
+ mlog_errno(ret2);
+ if (!ret)
+ ret = ret2;
+ }
+
+ ctxt->c_first_suballocator = fl->f_next_suballocator;
+ kfree(fl);
+ }
+
+ return ret;
+}
+
+static struct ocfs2_per_slot_free_list *
+ocfs2_find_per_slot_free_list(int type,
+ int slot,
+ struct ocfs2_cached_dealloc_ctxt *ctxt)
+{
+ struct ocfs2_per_slot_free_list *fl = ctxt->c_first_suballocator;
+
+ while (fl) {
+ if (fl->f_inode_type == type && fl->f_slot == slot)
+ return fl;
+
+ fl = fl->f_next_suballocator;
+ }
+
+ fl = kmalloc(sizeof(*fl), GFP_NOFS);
+ if (fl) {
+ fl->f_inode_type = type;
+ fl->f_slot = slot;
+ fl->f_first = NULL;
+ fl->f_next_suballocator = ctxt->c_first_suballocator;
+
+ ctxt->c_first_suballocator = fl;
+ }
+ return fl;
+}
+
+static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+ int type, int slot, u64 blkno,
+ unsigned int bit)
+{
+ int ret;
+ struct ocfs2_per_slot_free_list *fl;
+ struct ocfs2_cached_block_free *item;
+
+ fl = ocfs2_find_per_slot_free_list(type, slot, ctxt);
+ if (fl == NULL) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ item = kmalloc(sizeof(*item), GFP_NOFS);
+ if (item == NULL) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
+ type, slot, bit, (unsigned long long)blkno);
+
+ item->free_blk = blkno;
+ item->free_bit = bit;
+ item->free_next = fl->f_first;
+
+ fl->f_first = item;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
+ struct ocfs2_extent_block *eb)
+{
+ return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
+ le16_to_cpu(eb->h_suballoc_slot),
+ le64_to_cpu(eb->h_blkno),
+ le16_to_cpu(eb->h_suballoc_bit));
+}
+
/* This function will figure out whether the currently last extent
* block will be deleted, and if it will, what the new last extent
* block will be so we can update his h_next_leaf_blk field, as well
@@ -3238,27 +5526,10 @@ delete:
BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
- if (le16_to_cpu(eb->h_suballoc_slot) == 0) {
- /*
- * This code only understands how to
- * lock the suballocator in slot 0,
- * which is fine because allocation is
- * only ever done out of that
- * suballocator too. A future version
- * might change that however, so avoid
- * a free if we don't know how to
- * handle it. This way an fs incompat
- * bit will not be necessary.
- */
- ret = ocfs2_free_extent_block(handle,
- tc->tc_ext_alloc_inode,
- tc->tc_ext_alloc_bh,
- eb);
-
- /* An error here is not fatal. */
- if (ret < 0)
- mlog_errno(ret);
- }
+ ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
+ /* An error here is not fatal. */
+ if (ret < 0)
+ mlog_errno(ret);
} else {
deleted_eb = 0;
}
@@ -3397,9 +5668,9 @@ static int ocfs2_ordered_zero_func(handle_t *handle, struct buffer_head *bh)
return ocfs2_journal_dirty_data(handle, bh);
}
-static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
- struct page **pages, int numpages,
- u64 phys, handle_t *handle)
+static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start,
+ loff_t end, struct page **pages,
+ int numpages, u64 phys, handle_t *handle)
{
int i, ret, partial = 0;
void *kaddr;
@@ -3412,26 +5683,14 @@ static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
if (numpages == 0)
goto out;
- from = isize & (PAGE_CACHE_SIZE - 1); /* 1st page offset */
- if (PAGE_CACHE_SHIFT > OCFS2_SB(sb)->s_clustersize_bits) {
- /*
- * Since 'from' has been capped to a value below page
- * size, this calculation won't be able to overflow
- * 'to'
- */
- to = ocfs2_align_bytes_to_clusters(sb, from);
-
- /*
- * The truncate tail in this case should never contain
- * more than one page at maximum. The loop below also
- * assumes this.
- */
- BUG_ON(numpages != 1);
- }
-
+ to = PAGE_CACHE_SIZE;
for(i = 0; i < numpages; i++) {
page = pages[i];
+ from = start & (PAGE_CACHE_SIZE - 1);
+ if ((end >> PAGE_CACHE_SHIFT) == page->index)
+ to = end & (PAGE_CACHE_SIZE - 1);
+
BUG_ON(from > PAGE_CACHE_SIZE);
BUG_ON(to > PAGE_CACHE_SIZE);
@@ -3468,10 +5727,7 @@ static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
flush_dcache_page(page);
- /*
- * Every page after the 1st one should be completely zero'd.
- */
- from = 0;
+ start = (page->index + 1) << PAGE_CACHE_SHIFT;
}
out:
if (pages) {
@@ -3484,24 +5740,26 @@ out:
}
}
-static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page **pages,
- int *num, u64 *phys)
+static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
+ struct page **pages, int *num, u64 *phys)
{
int i, numpages = 0, ret = 0;
- unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize;
unsigned int ext_flags;
struct super_block *sb = inode->i_sb;
struct address_space *mapping = inode->i_mapping;
unsigned long index;
- u64 next_cluster_bytes;
+ loff_t last_page_bytes;
BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb)));
+ BUG_ON(start > end);
- /* Cluster boundary, so we don't need to grab any pages. */
- if ((isize & (csize - 1)) == 0)
+ if (start == end)
goto out;
- ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits,
+ BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
+ (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
+
+ ret = ocfs2_extent_map_get_blocks(inode, start >> sb->s_blocksize_bits,
phys, NULL, &ext_flags);
if (ret) {
mlog_errno(ret);
@@ -3517,8 +5775,8 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
if (ext_flags & OCFS2_EXT_UNWRITTEN)
goto out;
- next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize);
- index = isize >> PAGE_CACHE_SHIFT;
+ last_page_bytes = PAGE_ALIGN(end);
+ index = start >> PAGE_CACHE_SHIFT;
do {
pages[numpages] = grab_cache_page(mapping, index);
if (!pages[numpages]) {
@@ -3529,7 +5787,7 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
numpages++;
index++;
- } while (index < (next_cluster_bytes >> PAGE_CACHE_SHIFT));
+ } while (index < (last_page_bytes >> PAGE_CACHE_SHIFT));
out:
if (ret != 0) {
@@ -3558,11 +5816,10 @@ out:
* otherwise block_write_full_page() will skip writeout of pages past
* i_size. The new_i_size parameter is passed for this reason.
*/
-int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
- u64 new_i_size)
+int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
+ u64 range_start, u64 range_end)
{
int ret, numpages;
- loff_t endbyte;
struct page **pages = NULL;
u64 phys;
@@ -3581,7 +5838,8 @@ int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
goto out;
}
- ret = ocfs2_grab_eof_pages(inode, new_i_size, pages, &numpages, &phys);
+ ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages,
+ &numpages, &phys);
if (ret) {
mlog_errno(ret);
goto out;
@@ -3590,17 +5848,16 @@ int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
if (numpages == 0)
goto out;
- ocfs2_zero_cluster_pages(inode, new_i_size, pages, numpages, phys,
- handle);
+ ocfs2_zero_cluster_pages(inode, range_start, range_end, pages,
+ numpages, phys, handle);
/*
* Initiate writeout of the pages we zero'd here. We don't
* wait on them - the truncate_inode_pages() call later will
* do that for us.
*/
- endbyte = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
- ret = do_sync_mapping_range(inode->i_mapping, new_i_size,
- endbyte - 1, SYNC_FILE_RANGE_WRITE);
+ ret = do_sync_mapping_range(inode->i_mapping, range_start,
+ range_end - 1, SYNC_FILE_RANGE_WRITE);
if (ret)
mlog_errno(ret);
@@ -3631,8 +5888,6 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
mlog_entry_void();
- down_write(&OCFS2_I(inode)->ip_alloc_sem);
-
new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
i_size_read(inode));
@@ -3754,7 +6009,6 @@ start:
goto start;
bail:
- up_write(&OCFS2_I(inode)->ip_alloc_sem);
ocfs2_schedule_truncate_log_flush(osb, 1);
@@ -3764,6 +6018,8 @@ bail:
if (handle)
ocfs2_commit_trans(osb, handle);
+ ocfs2_run_deallocs(osb, &tc->tc_dealloc);
+
ocfs2_free_path(path);
/* This will drop the ext_alloc cluster lock for us */
@@ -3774,23 +6030,18 @@ bail:
}
/*
- * Expects the inode to already be locked. This will figure out which
- * inodes need to be locked and will put them on the returned truncate
- * context.
+ * Expects the inode to already be locked.
*/
int ocfs2_prepare_truncate(struct ocfs2_super *osb,
struct inode *inode,
struct buffer_head *fe_bh,
struct ocfs2_truncate_context **tc)
{
- int status, metadata_delete, i;
+ int status;
unsigned int new_i_clusters;
struct ocfs2_dinode *fe;
struct ocfs2_extent_block *eb;
- struct ocfs2_extent_list *el;
struct buffer_head *last_eb_bh = NULL;
- struct inode *ext_alloc_inode = NULL;
- struct buffer_head *ext_alloc_bh = NULL;
mlog_entry_void();
@@ -3810,12 +6061,9 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
mlog_errno(status);
goto bail;
}
+ ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
- metadata_delete = 0;
if (fe->id2.i_list.l_tree_depth) {
- /* If we have a tree, then the truncate may result in
- * metadata deletes. Figure this out from the
- * rightmost leaf block.*/
status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
&last_eb_bh, OCFS2_BH_CACHED, inode);
if (status < 0) {
@@ -3830,43 +6078,10 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
status = -EIO;
goto bail;
}
- el = &(eb->h_list);
-
- i = 0;
- if (ocfs2_is_empty_extent(&el->l_recs[0]))
- i = 1;
- /*
- * XXX: Should we check that next_free_rec contains
- * the extent?
- */
- if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_i_clusters)
- metadata_delete = 1;
}
(*tc)->tc_last_eb_bh = last_eb_bh;
- if (metadata_delete) {
- mlog(0, "Will have to delete metadata for this trunc. "
- "locking allocator.\n");
- ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
- if (!ext_alloc_inode) {
- status = -ENOMEM;
- mlog_errno(status);
- goto bail;
- }
-
- mutex_lock(&ext_alloc_inode->i_mutex);
- (*tc)->tc_ext_alloc_inode = ext_alloc_inode;
-
- status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
- }
- (*tc)->tc_ext_alloc_bh = ext_alloc_bh;
- (*tc)->tc_ext_alloc_locked = 1;
- }
-
status = 0;
bail:
if (status < 0) {
@@ -3880,16 +6095,13 @@ bail:
static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
{
- if (tc->tc_ext_alloc_inode) {
- if (tc->tc_ext_alloc_locked)
- ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);
-
- mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
- iput(tc->tc_ext_alloc_inode);
- }
-
- if (tc->tc_ext_alloc_bh)
- brelse(tc->tc_ext_alloc_bh);
+ /*
+ * The caller is responsible for completing deallocation
+ * before freeing the context.
+ */
+ if (tc->tc_dealloc.c_first_suballocator != NULL)
+ mlog(ML_NOTICE,
+ "Truncate completion has non-empty dealloc context\n");
if (tc->tc_last_eb_bh)
brelse(tc->tc_last_eb_bh);
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index fbcb5934a081..990df48ae8d3 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -34,7 +34,17 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
u32 cpos,
u64 start_blk,
u32 new_clusters,
+ u8 flags,
struct ocfs2_alloc_context *meta_ac);
+struct ocfs2_cached_dealloc_ctxt;
+int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+ handle_t *handle, u32 cpos, u32 len, u32 phys,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_cached_dealloc_ctxt *dealloc);
+int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+ u32 cpos, u32 len, handle_t *handle,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_cached_dealloc_ctxt *dealloc);
int ocfs2_num_free_extents(struct ocfs2_super *osb,
struct inode *inode,
struct ocfs2_dinode *fe);
@@ -62,17 +72,41 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
struct ocfs2_dinode **tl_copy);
int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
struct ocfs2_dinode *tl_copy);
+int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb);
+int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+ handle_t *handle,
+ u64 start_blk,
+ unsigned int num_clusters);
+int __ocfs2_flush_truncate_log(struct ocfs2_super *osb);
+
+/*
+ * Process local structure which describes the block unlinks done
+ * during an operation. This is populated via
+ * ocfs2_cache_block_dealloc().
+ *
+ * ocfs2_run_deallocs() should be called after the potentially
+ * de-allocating routines. No journal handles should be open, and most
+ * locks should have been dropped.
+ */
+struct ocfs2_cached_dealloc_ctxt {
+ struct ocfs2_per_slot_free_list *c_first_suballocator;
+};
+static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
+{
+ c->c_first_suballocator = NULL;
+}
+int ocfs2_run_deallocs(struct ocfs2_super *osb,
+ struct ocfs2_cached_dealloc_ctxt *ctxt);
struct ocfs2_truncate_context {
- struct inode *tc_ext_alloc_inode;
- struct buffer_head *tc_ext_alloc_bh;
+ struct ocfs2_cached_dealloc_ctxt tc_dealloc;
int tc_ext_alloc_locked; /* is it cluster locked? */
/* these get destroyed once it's passed to ocfs2_commit_truncate. */
struct buffer_head *tc_last_eb_bh;
};
-int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
- u64 new_i_size);
+int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
+ u64 range_start, u64 range_end);
int ocfs2_prepare_truncate(struct ocfs2_super *osb,
struct inode *inode,
struct buffer_head *fe_bh,
@@ -84,6 +118,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
u32 cpos, struct buffer_head **leaf_bh);
+int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
/*
* Helper function to look at the # of clusters in an extent record.
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index a480b09c79b9..84bf6e79de23 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -684,6 +684,8 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
bh = bh->b_this_page, block_start += bsize) {
block_end = block_start + bsize;
+ clear_buffer_new(bh);
+
/*
* Ignore blocks outside of our i/o range -
* they may belong to unallocated clusters.
@@ -698,9 +700,8 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
* For an allocating write with cluster size >= page
* size, we always write the entire page.
*/
-
- if (buffer_new(bh))
- clear_buffer_new(bh);
+ if (new)
+ set_buffer_new(bh);
if (!buffer_mapped(bh)) {
map_bh(bh, inode->i_sb, *p_blkno);
@@ -711,7 +712,8 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
if (!buffer_uptodate(bh))
set_buffer_uptodate(bh);
} else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
- (block_start < from || block_end > to)) {
+ !buffer_new(bh) &&
+ (block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
*wait_bh++=bh;
}
@@ -738,18 +740,13 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
bh = head;
block_start = 0;
do {
- void *kaddr;
-
block_end = block_start + bsize;
if (block_end <= from)
goto next_bh;
if (block_start >= to)
break;
- kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr+block_start, 0, bh->b_size);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
+ zero_user_page(page, block_start, bh->b_size, KM_USER0);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
@@ -761,217 +758,240 @@ next_bh:
return ret;
}
+#if (PAGE_CACHE_SIZE >= OCFS2_MAX_CLUSTERSIZE)
+#define OCFS2_MAX_CTXT_PAGES 1
+#else
+#define OCFS2_MAX_CTXT_PAGES (OCFS2_MAX_CLUSTERSIZE / PAGE_CACHE_SIZE)
+#endif
+
+#define OCFS2_MAX_CLUSTERS_PER_PAGE (PAGE_CACHE_SIZE / OCFS2_MIN_CLUSTERSIZE)
+
/*
- * This will copy user data from the buffer page in the splice
- * context.
- *
- * For now, we ignore SPLICE_F_MOVE as that would require some extra
- * communication out all the way to ocfs2_write().
+ * Describe the state of a single cluster to be written to.
*/
-int ocfs2_map_and_write_splice_data(struct inode *inode,
- struct ocfs2_write_ctxt *wc, u64 *p_blkno,
- unsigned int *ret_from, unsigned int *ret_to)
+struct ocfs2_write_cluster_desc {
+ u32 c_cpos;
+ u32 c_phys;
+ /*
+ * Give this a unique field because c_phys eventually gets
+ * filled.
+ */
+ unsigned c_new;
+ unsigned c_unwritten;
+};
+
+static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
{
- int ret;
- unsigned int to, from, cluster_start, cluster_end;
- char *src, *dst;
- struct ocfs2_splice_write_priv *sp = wc->w_private;
- struct pipe_buffer *buf = sp->s_buf;
- unsigned long bytes, src_from;
- struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ return d->c_new || d->c_unwritten;
+}
- ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
- &cluster_end);
+struct ocfs2_write_ctxt {
+ /* Logical cluster position / len of write */
+ u32 w_cpos;
+ u32 w_clen;
- from = sp->s_offset;
- src_from = sp->s_buf_offset;
- bytes = wc->w_count;
+ struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
- if (wc->w_large_pages) {
- /*
- * For cluster size < page size, we have to
- * calculate pos within the cluster and obey
- * the rightmost boundary.
- */
- bytes = min(bytes, (unsigned long)(osb->s_clustersize
- - (wc->w_pos & (osb->s_clustersize - 1))));
- }
- to = from + bytes;
+ /*
+ * This is true if page_size > cluster_size.
+ *
+ * It triggers a set of special cases during write which might
+ * have to deal with allocating writes to partial pages.
+ */
+ unsigned int w_large_pages;
+
+ /*
+ * Pages involved in this write.
+ *
+ * w_target_page is the page being written to by the user.
+ *
+ * w_pages is an array of pages which always contains
+ * w_target_page, and in the case of an allocating write with
+ * page_size < cluster size, it will contain zero'd and mapped
+ * pages adjacent to w_target_page which need to be written
+ * out in so that future reads from that region will get
+ * zero's.
+ */
+ struct page *w_pages[OCFS2_MAX_CTXT_PAGES];
+ unsigned int w_num_pages;
+ struct page *w_target_page;
- BUG_ON(from > PAGE_CACHE_SIZE);
- BUG_ON(to > PAGE_CACHE_SIZE);
- BUG_ON(from < cluster_start);
- BUG_ON(to > cluster_end);
+ /*
+ * ocfs2_write_end() uses this to know what the real range to
+ * write in the target should be.
+ */
+ unsigned int w_target_from;
+ unsigned int w_target_to;
- if (wc->w_this_page_new)
- ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
- cluster_start, cluster_end, 1);
- else
- ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
- from, to, 0);
- if (ret) {
- mlog_errno(ret);
- goto out;
+ /*
+ * We could use journal_current_handle() but this is cleaner,
+ * IMHO -Mark
+ */
+ handle_t *w_handle;
+
+ struct buffer_head *w_di_bh;
+
+ struct ocfs2_cached_dealloc_ctxt w_dealloc;
+};
+
+static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
+{
+ int i;
+
+ for(i = 0; i < wc->w_num_pages; i++) {
+ if (wc->w_pages[i] == NULL)
+ continue;
+
+ unlock_page(wc->w_pages[i]);
+ mark_page_accessed(wc->w_pages[i]);
+ page_cache_release(wc->w_pages[i]);
}
- src = buf->ops->map(sp->s_pipe, buf, 1);
- dst = kmap_atomic(wc->w_this_page, KM_USER1);
- memcpy(dst + from, src + src_from, bytes);
- kunmap_atomic(wc->w_this_page, KM_USER1);
- buf->ops->unmap(sp->s_pipe, buf, src);
+ brelse(wc->w_di_bh);
+ kfree(wc);
+}
+
+static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
+ struct ocfs2_super *osb, loff_t pos,
+ unsigned len, struct buffer_head *di_bh)
+{
+ struct ocfs2_write_ctxt *wc;
+
+ wc = kzalloc(sizeof(struct ocfs2_write_ctxt), GFP_NOFS);
+ if (!wc)
+ return -ENOMEM;
- wc->w_finished_copy = 1;
+ wc->w_cpos = pos >> osb->s_clustersize_bits;
+ wc->w_clen = ocfs2_clusters_for_bytes(osb->sb, len);
+ get_bh(di_bh);
+ wc->w_di_bh = di_bh;
- *ret_from = from;
- *ret_to = to;
-out:
+ if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
+ wc->w_large_pages = 1;
+ else
+ wc->w_large_pages = 0;
+
+ ocfs2_init_dealloc_ctxt(&wc->w_dealloc);
+
+ *wcp = wc;
- return bytes ? (unsigned int)bytes : ret;
+ return 0;
}
/*
- * This will copy user data from the iovec in the buffered write
- * context.
+ * If a page has any new buffers, zero them out here, and mark them uptodate
+ * and dirty so they'll be written out (in order to prevent uninitialised
+ * block data from leaking). And clear the new bit.
*/
-int ocfs2_map_and_write_user_data(struct inode *inode,
- struct ocfs2_write_ctxt *wc, u64 *p_blkno,
- unsigned int *ret_from, unsigned int *ret_to)
+static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to)
{
- int ret;
- unsigned int to, from, cluster_start, cluster_end;
- unsigned long bytes, src_from;
- char *dst;
- struct ocfs2_buffered_write_priv *bp = wc->w_private;
- const struct iovec *cur_iov = bp->b_cur_iov;
- char __user *buf;
- struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ unsigned int block_start, block_end;
+ struct buffer_head *head, *bh;
- ocfs2_figure_cluster_boundaries(osb, wc->w_cpos, &cluster_start,
- &cluster_end);
+ BUG_ON(!PageLocked(page));
+ if (!page_has_buffers(page))
+ return;
- buf = cur_iov->iov_base + bp->b_cur_off;
- src_from = (unsigned long)buf & ~PAGE_CACHE_MASK;
+ bh = head = page_buffers(page);
+ block_start = 0;
+ do {
+ block_end = block_start + bh->b_size;
- from = wc->w_pos & (PAGE_CACHE_SIZE - 1);
+ if (buffer_new(bh)) {
+ if (block_end > from && block_start < to) {
+ if (!PageUptodate(page)) {
+ unsigned start, end;
- /*
- * This is a lot of comparisons, but it reads quite
- * easily, which is important here.
- */
- /* Stay within the src page */
- bytes = PAGE_SIZE - src_from;
- /* Stay within the vector */
- bytes = min(bytes,
- (unsigned long)(cur_iov->iov_len - bp->b_cur_off));
- /* Stay within count */
- bytes = min(bytes, (unsigned long)wc->w_count);
- /*
- * For clustersize > page size, just stay within
- * target page, otherwise we have to calculate pos
- * within the cluster and obey the rightmost
- * boundary.
- */
- if (wc->w_large_pages) {
- /*
- * For cluster size < page size, we have to
- * calculate pos within the cluster and obey
- * the rightmost boundary.
- */
- bytes = min(bytes, (unsigned long)(osb->s_clustersize
- - (wc->w_pos & (osb->s_clustersize - 1))));
- } else {
- /*
- * cluster size > page size is the most common
- * case - we just stay within the target page
- * boundary.
- */
- bytes = min(bytes, PAGE_CACHE_SIZE - from);
- }
+ start = max(from, block_start);
+ end = min(to, block_end);
- to = from + bytes;
+ zero_user_page(page, start, end - start, KM_USER0);
+ set_buffer_uptodate(bh);
+ }
- BUG_ON(from > PAGE_CACHE_SIZE);
- BUG_ON(to > PAGE_CACHE_SIZE);
- BUG_ON(from < cluster_start);
- BUG_ON(to > cluster_end);
+ clear_buffer_new(bh);
+ mark_buffer_dirty(bh);
+ }
+ }
- if (wc->w_this_page_new)
- ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
- cluster_start, cluster_end, 1);
- else
- ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
- from, to, 0);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
+ block_start = block_end;
+ bh = bh->b_this_page;
+ } while (bh != head);
+}
- dst = kmap(wc->w_this_page);
- memcpy(dst + from, bp->b_src_buf + src_from, bytes);
- kunmap(wc->w_this_page);
+/*
+ * Only called when we have a failure during allocating write to write
+ * zero's to the newly allocated region.
+ */
+static void ocfs2_write_failure(struct inode *inode,
+ struct ocfs2_write_ctxt *wc,
+ loff_t user_pos, unsigned user_len)
+{
+ int i;
+ unsigned from, to;
+ struct page *tmppage;
- /*
- * XXX: This is slow, but simple. The caller of
- * ocfs2_buffered_write_cluster() is responsible for
- * passing through the iovecs, so it's difficult to
- * predict what our next step is in here after our
- * initial write. A future version should be pushing
- * that iovec manipulation further down.
- *
- * By setting this, we indicate that a copy from user
- * data was done, and subsequent calls for this
- * cluster will skip copying more data.
- */
- wc->w_finished_copy = 1;
+ ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len);
- *ret_from = from;
- *ret_to = to;
-out:
+ if (wc->w_large_pages) {
+ from = wc->w_target_from;
+ to = wc->w_target_to;
+ } else {
+ from = 0;
+ to = PAGE_CACHE_SIZE;
+ }
+
+ for(i = 0; i < wc->w_num_pages; i++) {
+ tmppage = wc->w_pages[i];
- return bytes ? (unsigned int)bytes : ret;
+ if (ocfs2_should_order_data(inode))
+ walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+ from, to, NULL,
+ ocfs2_journal_dirty_data);
+
+ block_commit_write(tmppage, from, to);
+ }
}
-/*
- * Map, fill and write a page to disk.
- *
- * The work of copying data is done via callback. Newly allocated
- * pages which don't take user data will be zero'd (set 'new' to
- * indicate an allocating write)
- *
- * Returns a negative error code or the number of bytes copied into
- * the page.
- */
-static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
- u64 *p_blkno, struct page *page,
- struct ocfs2_write_ctxt *wc, int new)
+static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
+ struct ocfs2_write_ctxt *wc,
+ struct page *page, u32 cpos,
+ loff_t user_pos, unsigned user_len,
+ int new)
{
- int ret, copied = 0;
- unsigned int from = 0, to = 0;
+ int ret;
+ unsigned int map_from = 0, map_to = 0;
unsigned int cluster_start, cluster_end;
- unsigned int zero_from = 0, zero_to = 0;
+ unsigned int user_data_from = 0, user_data_to = 0;
- ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), wc->w_cpos,
+ ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
&cluster_start, &cluster_end);
- if ((wc->w_pos >> PAGE_CACHE_SHIFT) == page->index
- && !wc->w_finished_copy) {
-
- wc->w_this_page = page;
- wc->w_this_page_new = new;
- ret = wc->w_write_data_page(inode, wc, p_blkno, &from, &to);
- if (ret < 0) {
+ if (page == wc->w_target_page) {
+ map_from = user_pos & (PAGE_CACHE_SIZE - 1);
+ map_to = map_from + user_len;
+
+ if (new)
+ ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+ cluster_start, cluster_end,
+ new);
+ else
+ ret = ocfs2_map_page_blocks(page, p_blkno, inode,
+ map_from, map_to, new);
+ if (ret) {
mlog_errno(ret);
goto out;
}
- copied = ret;
-
- zero_from = from;
- zero_to = to;
+ user_data_from = map_from;
+ user_data_to = map_to;
if (new) {
- from = cluster_start;
- to = cluster_end;
+ map_from = cluster_start;
+ map_to = cluster_end;
}
+
+ wc->w_target_from = map_from;
+ wc->w_target_to = map_to;
} else {
/*
* If we haven't allocated the new page yet, we
@@ -980,11 +1000,11 @@ static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
*/
BUG_ON(!new);
- from = cluster_start;
- to = cluster_end;
+ map_from = cluster_start;
+ map_to = cluster_end;
ret = ocfs2_map_page_blocks(page, p_blkno, inode,
- cluster_start, cluster_end, 1);
+ cluster_start, cluster_end, new);
if (ret) {
mlog_errno(ret);
goto out;
@@ -1003,108 +1023,113 @@ static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
*/
if (new && !PageUptodate(page))
ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
- wc->w_cpos, zero_from, zero_to);
+ cpos, user_data_from, user_data_to);
flush_dcache_page(page);
- if (ocfs2_should_order_data(inode)) {
- ret = walk_page_buffers(handle,
- page_buffers(page),
- from, to, NULL,
- ocfs2_journal_dirty_data);
- if (ret < 0)
- mlog_errno(ret);
- }
-
- /*
- * We don't use generic_commit_write() because we need to
- * handle our own i_size update.
- */
- ret = block_commit_write(page, from, to);
- if (ret)
- mlog_errno(ret);
out:
-
- return copied ? copied : ret;
+ return ret;
}
/*
- * Do the actual write of some data into an inode. Optionally allocate
- * in order to fulfill the write.
- *
- * cpos is the logical cluster offset within the file to write at
- *
- * 'phys' is the physical mapping of that offset. a 'phys' value of
- * zero indicates that allocation is required. In this case, data_ac
- * and meta_ac should be valid (meta_ac can be null if metadata
- * allocation isn't required).
+ * This function will only grab one clusters worth of pages.
*/
-static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
- struct buffer_head *di_bh,
- struct ocfs2_alloc_context *data_ac,
- struct ocfs2_alloc_context *meta_ac,
- struct ocfs2_write_ctxt *wc)
+static int ocfs2_grab_pages_for_write(struct address_space *mapping,
+ struct ocfs2_write_ctxt *wc,
+ u32 cpos, loff_t user_pos, int new,
+ struct page *mmap_page)
{
- int ret, i, numpages = 1, new;
- unsigned int copied = 0;
- u32 tmp_pos;
- u64 v_blkno, p_blkno;
- struct address_space *mapping = file->f_mapping;
+ int ret = 0, i;
+ unsigned long start, target_index, index;
struct inode *inode = mapping->host;
- unsigned long index, start;
- struct page **cpages;
- new = phys == 0 ? 1 : 0;
+ target_index = user_pos >> PAGE_CACHE_SHIFT;
/*
* Figure out how many pages we'll be manipulating here. For
* non allocating write, we just change the one
* page. Otherwise, we'll need a whole clusters worth.
*/
- if (new)
- numpages = ocfs2_pages_per_cluster(inode->i_sb);
-
- cpages = kzalloc(sizeof(*cpages) * numpages, GFP_NOFS);
- if (!cpages) {
- ret = -ENOMEM;
- mlog_errno(ret);
- return ret;
- }
-
- /*
- * Fill our page array first. That way we've grabbed enough so
- * that we can zero and flush if we error after adding the
- * extent.
- */
if (new) {
- start = ocfs2_align_clusters_to_page_index(inode->i_sb,
- wc->w_cpos);
- v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, wc->w_cpos);
+ wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);
+ start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);
} else {
- start = wc->w_pos >> PAGE_CACHE_SHIFT;
- v_blkno = wc->w_pos >> inode->i_sb->s_blocksize_bits;
+ wc->w_num_pages = 1;
+ start = target_index;
}
- for(i = 0; i < numpages; i++) {
+ for(i = 0; i < wc->w_num_pages; i++) {
index = start + i;
- cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
- if (!cpages[i]) {
- ret = -ENOMEM;
- mlog_errno(ret);
- goto out;
+ if (index == target_index && mmap_page) {
+ /*
+ * ocfs2_pagemkwrite() is a little different
+ * and wants us to directly use the page
+ * passed in.
+ */
+ lock_page(mmap_page);
+
+ if (mmap_page->mapping != mapping) {
+ unlock_page(mmap_page);
+ /*
+ * Sanity check - the locking in
+ * ocfs2_pagemkwrite() should ensure
+ * that this code doesn't trigger.
+ */
+ ret = -EINVAL;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ page_cache_get(mmap_page);
+ wc->w_pages[i] = mmap_page;
+ } else {
+ wc->w_pages[i] = find_or_create_page(mapping, index,
+ GFP_NOFS);
+ if (!wc->w_pages[i]) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
}
+
+ if (index == target_index)
+ wc->w_target_page = wc->w_pages[i];
}
+out:
+ return ret;
+}
+
+/*
+ * Prepare a single cluster for write one cluster into the file.
+ */
+static int ocfs2_write_cluster(struct address_space *mapping,
+ u32 phys, unsigned int unwritten,
+ struct ocfs2_alloc_context *data_ac,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_write_ctxt *wc, u32 cpos,
+ loff_t user_pos, unsigned user_len)
+{
+ int ret, i, new, should_zero = 0;
+ u64 v_blkno, p_blkno;
+ struct inode *inode = mapping->host;
+
+ new = phys == 0 ? 1 : 0;
+ if (new || unwritten)
+ should_zero = 1;
if (new) {
+ u32 tmp_pos;
+
/*
* This is safe to call with the page locks - it won't take
* any additional semaphores or cluster locks.
*/
- tmp_pos = wc->w_cpos;
+ tmp_pos = cpos;
ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
- &tmp_pos, 1, di_bh, handle,
- data_ac, meta_ac, NULL);
+ &tmp_pos, 1, 0, wc->w_di_bh,
+ wc->w_handle, data_ac,
+ meta_ac, NULL);
/*
* This shouldn't happen because we must have already
* calculated the correct meta data allocation required. The
@@ -1121,159 +1146,433 @@ static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
mlog_errno(ret);
goto out;
}
+ } else if (unwritten) {
+ ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
+ wc->w_handle, cpos, 1, phys,
+ meta_ac, &wc->w_dealloc);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
}
+ if (should_zero)
+ v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, cpos);
+ else
+ v_blkno = user_pos >> inode->i_sb->s_blocksize_bits;
+
+ /*
+ * The only reason this should fail is due to an inability to
+ * find the extent added.
+ */
ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,
NULL);
if (ret < 0) {
-
- /*
- * XXX: Should we go readonly here?
- */
-
- mlog_errno(ret);
+ ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, "
+ "at logical block %llu",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)v_blkno);
goto out;
}
BUG_ON(p_blkno == 0);
- for(i = 0; i < numpages; i++) {
- ret = ocfs2_write_data_page(inode, handle, &p_blkno, cpages[i],
- wc, new);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
+ for(i = 0; i < wc->w_num_pages; i++) {
+ int tmpret;
+
+ tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,
+ wc->w_pages[i], cpos,
+ user_pos, user_len,
+ should_zero);
+ if (tmpret) {
+ mlog_errno(tmpret);
+ if (ret == 0)
+ tmpret = ret;
}
-
- copied += ret;
}
+ /*
+ * We only have cleanup to do in case of allocating write.
+ */
+ if (ret && new)
+ ocfs2_write_failure(inode, wc, user_pos, user_len);
+
out:
- for(i = 0; i < numpages; i++) {
- unlock_page(cpages[i]);
- mark_page_accessed(cpages[i]);
- page_cache_release(cpages[i]);
+
+ return ret;
+}
+
+static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
+ struct ocfs2_alloc_context *data_ac,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_write_ctxt *wc,
+ loff_t pos, unsigned len)
+{
+ int ret, i;
+ struct ocfs2_write_cluster_desc *desc;
+
+ for (i = 0; i < wc->w_clen; i++) {
+ desc = &wc->w_desc[i];
+
+ ret = ocfs2_write_cluster(mapping, desc->c_phys,
+ desc->c_unwritten, data_ac, meta_ac,
+ wc, desc->c_cpos, pos, len);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
}
- kfree(cpages);
- return copied ? copied : ret;
+ ret = 0;
+out:
+ return ret;
}
-static void ocfs2_write_ctxt_init(struct ocfs2_write_ctxt *wc,
- struct ocfs2_super *osb, loff_t pos,
- size_t count, ocfs2_page_writer *cb,
- void *cb_priv)
+/*
+ * ocfs2_write_end() wants to know which parts of the target page it
+ * should complete the write on. It's easiest to compute them ahead of
+ * time when a more complete view of the write is available.
+ */
+static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
+ struct ocfs2_write_ctxt *wc,
+ loff_t pos, unsigned len, int alloc)
{
- wc->w_count = count;
- wc->w_pos = pos;
- wc->w_cpos = wc->w_pos >> osb->s_clustersize_bits;
- wc->w_finished_copy = 0;
+ struct ocfs2_write_cluster_desc *desc;
- if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))
- wc->w_large_pages = 1;
- else
- wc->w_large_pages = 0;
+ wc->w_target_from = pos & (PAGE_CACHE_SIZE - 1);
+ wc->w_target_to = wc->w_target_from + len;
- wc->w_write_data_page = cb;
- wc->w_private = cb_priv;
+ if (alloc == 0)
+ return;
+
+ /*
+ * Allocating write - we may have different boundaries based
+ * on page size and cluster size.
+ *
+ * NOTE: We can no longer compute one value from the other as
+ * the actual write length and user provided length may be
+ * different.
+ */
+
+ if (wc->w_large_pages) {
+ /*
+ * We only care about the 1st and last cluster within
+ * our range and whether they should be zero'd or not. Either
+ * value may be extended out to the start/end of a
+ * newly allocated cluster.
+ */
+ desc = &wc->w_desc[0];
+ if (ocfs2_should_zero_cluster(desc))
+ ocfs2_figure_cluster_boundaries(osb,
+ desc->c_cpos,
+ &wc->w_target_from,
+ NULL);
+
+ desc = &wc->w_desc[wc->w_clen - 1];
+ if (ocfs2_should_zero_cluster(desc))
+ ocfs2_figure_cluster_boundaries(osb,
+ desc->c_cpos,
+ NULL,
+ &wc->w_target_to);
+ } else {
+ wc->w_target_from = 0;
+ wc->w_target_to = PAGE_CACHE_SIZE;
+ }
}
/*
- * Write a cluster to an inode. The cluster may not be allocated yet,
- * in which case it will be. This only exists for buffered writes -
- * O_DIRECT takes a more "traditional" path through the kernel.
- *
- * The caller is responsible for incrementing pos, written counts, etc
+ * Populate each single-cluster write descriptor in the write context
+ * with information about the i/o to be done.
*
- * For file systems that don't support sparse files, pre-allocation
- * and page zeroing up until cpos should be done prior to this
- * function call.
- *
- * Callers should be holding i_sem, and the rw cluster lock.
- *
- * Returns the number of user bytes written, or less than zero for
- * error.
+ * Returns the number of clusters that will have to be allocated, as
+ * well as a worst case estimate of the number of extent records that
+ * would have to be created during a write to an unwritten region.
*/
-ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
- size_t count, ocfs2_page_writer *actor,
- void *priv)
+static int ocfs2_populate_write_desc(struct inode *inode,
+ struct ocfs2_write_ctxt *wc,
+ unsigned int *clusters_to_alloc,
+ unsigned int *extents_to_split)
+{
+ int ret;
+ struct ocfs2_write_cluster_desc *desc;
+ unsigned int num_clusters = 0;
+ unsigned int ext_flags = 0;
+ u32 phys = 0;
+ int i;
+
+ *clusters_to_alloc = 0;
+ *extents_to_split = 0;
+
+ for (i = 0; i < wc->w_clen; i++) {
+ desc = &wc->w_desc[i];
+ desc->c_cpos = wc->w_cpos + i;
+
+ if (num_clusters == 0) {
+ /*
+ * Need to look up the next extent record.
+ */
+ ret = ocfs2_get_clusters(inode, desc->c_cpos, &phys,
+ &num_clusters, &ext_flags);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * Assume worst case - that we're writing in
+ * the middle of the extent.
+ *
+ * We can assume that the write proceeds from
+ * left to right, in which case the extent
+ * insert code is smart enough to coalesce the
+ * next splits into the previous records created.
+ */
+ if (ext_flags & OCFS2_EXT_UNWRITTEN)
+ *extents_to_split = *extents_to_split + 2;
+ } else if (phys) {
+ /*
+ * Only increment phys if it doesn't describe
+ * a hole.
+ */
+ phys++;
+ }
+
+ desc->c_phys = phys;
+ if (phys == 0) {
+ desc->c_new = 1;
+ *clusters_to_alloc = *clusters_to_alloc + 1;
+ }
+ if (ext_flags & OCFS2_EXT_UNWRITTEN)
+ desc->c_unwritten = 1;
+
+ num_clusters--;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int ocfs2_write_begin_nolock(struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata,
+ struct buffer_head *di_bh, struct page *mmap_page)
{
int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
- ssize_t written = 0;
- u32 phys;
- struct inode *inode = file->f_mapping->host;
+ unsigned int clusters_to_alloc, extents_to_split;
+ struct ocfs2_write_ctxt *wc;
+ struct inode *inode = mapping->host;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
- struct buffer_head *di_bh = NULL;
struct ocfs2_dinode *di;
struct ocfs2_alloc_context *data_ac = NULL;
struct ocfs2_alloc_context *meta_ac = NULL;
handle_t *handle;
- struct ocfs2_write_ctxt wc;
-
- ocfs2_write_ctxt_init(&wc, osb, pos, count, actor, priv);
- ret = ocfs2_meta_lock(inode, &di_bh, 1);
+ ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
if (ret) {
mlog_errno(ret);
- goto out;
+ return ret;
}
- di = (struct ocfs2_dinode *)di_bh->b_data;
-
- /*
- * Take alloc sem here to prevent concurrent lookups. That way
- * the mapping, zeroing and tree manipulation within
- * ocfs2_write() will be safe against ->readpage(). This
- * should also serve to lock out allocation from a shared
- * writeable region.
- */
- down_write(&OCFS2_I(inode)->ip_alloc_sem);
- ret = ocfs2_get_clusters(inode, wc.w_cpos, &phys, NULL, NULL);
+ ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
+ &extents_to_split);
if (ret) {
mlog_errno(ret);
- goto out_meta;
+ goto out;
}
- /* phys == 0 means that allocation is required. */
- if (phys == 0) {
- ret = ocfs2_lock_allocators(inode, di, 1, &data_ac, &meta_ac);
+ di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+
+ /*
+ * We set w_target_from, w_target_to here so that
+ * ocfs2_write_end() knows which range in the target page to
+ * write out. An allocation requires that we write the entire
+ * cluster range.
+ */
+ if (clusters_to_alloc || extents_to_split) {
+ /*
+ * XXX: We are stretching the limits of
+ * ocfs2_lock_allocators(). It greatly over-estimates
+ * the work to be done.
+ */
+ ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
+ extents_to_split, &data_ac, &meta_ac);
if (ret) {
mlog_errno(ret);
- goto out_meta;
+ goto out;
}
- credits = ocfs2_calc_extend_credits(inode->i_sb, di, 1);
- }
+ credits = ocfs2_calc_extend_credits(inode->i_sb, di,
+ clusters_to_alloc);
- ret = ocfs2_data_lock(inode, 1);
- if (ret) {
- mlog_errno(ret);
- goto out_meta;
}
+ ocfs2_set_target_boundaries(osb, wc, pos, len,
+ clusters_to_alloc + extents_to_split);
+
handle = ocfs2_start_trans(osb, credits);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
mlog_errno(ret);
- goto out_data;
+ goto out;
}
- written = ocfs2_write(file, phys, handle, di_bh, data_ac,
- meta_ac, &wc);
- if (written < 0) {
- ret = written;
+ wc->w_handle = handle;
+
+ /*
+ * We don't want this to fail in ocfs2_write_end(), so do it
+ * here.
+ */
+ ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
mlog_errno(ret);
goto out_commit;
}
- ret = ocfs2_journal_access(handle, inode, di_bh,
- OCFS2_JOURNAL_ACCESS_WRITE);
+ /*
+ * Fill our page array first. That way we've grabbed enough so
+ * that we can zero and flush if we error after adding the
+ * extent.
+ */
+ ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
+ clusters_to_alloc + extents_to_split,
+ mmap_page);
if (ret) {
mlog_errno(ret);
goto out_commit;
}
- pos += written;
+ ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
+ len);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+
+ if (data_ac)
+ ocfs2_free_alloc_context(data_ac);
+ if (meta_ac)
+ ocfs2_free_alloc_context(meta_ac);
+
+ *pagep = wc->w_target_page;
+ *fsdata = wc;
+ return 0;
+out_commit:
+ ocfs2_commit_trans(osb, handle);
+
+out:
+ ocfs2_free_write_ctxt(wc);
+
+ if (data_ac)
+ ocfs2_free_alloc_context(data_ac);
+ if (meta_ac)
+ ocfs2_free_alloc_context(meta_ac);
+ return ret;
+}
+
+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ int ret;
+ struct buffer_head *di_bh = NULL;
+ struct inode *inode = mapping->host;
+
+ ret = ocfs2_meta_lock(inode, &di_bh, 1);
+ if (ret) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ /*
+ * Take alloc sem here to prevent concurrent lookups. That way
+ * the mapping, zeroing and tree manipulation within
+ * ocfs2_write() will be safe against ->readpage(). This
+ * should also serve to lock out allocation from a shared
+ * writeable region.
+ */
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ret = ocfs2_data_lock(inode, 1);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_fail;
+ }
+
+ ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
+ fsdata, di_bh, NULL);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_fail_data;
+ }
+
+ brelse(di_bh);
+
+ return 0;
+
+out_fail_data:
+ ocfs2_data_unlock(inode, 1);
+out_fail:
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ brelse(di_bh);
+ ocfs2_meta_unlock(inode, 1);
+
+ return ret;
+}
+
+int ocfs2_write_end_nolock(struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ int i;
+ unsigned from, to, start = pos & (PAGE_CACHE_SIZE - 1);
+ struct inode *inode = mapping->host;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_write_ctxt *wc = fsdata;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data;
+ handle_t *handle = wc->w_handle;
+ struct page *tmppage;
+
+ if (unlikely(copied < len)) {
+ if (!PageUptodate(wc->w_target_page))
+ copied = 0;
+
+ ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
+ start+len);
+ }
+ flush_dcache_page(wc->w_target_page);
+
+ for(i = 0; i < wc->w_num_pages; i++) {
+ tmppage = wc->w_pages[i];
+
+ if (tmppage == wc->w_target_page) {
+ from = wc->w_target_from;
+ to = wc->w_target_to;
+
+ BUG_ON(from > PAGE_CACHE_SIZE ||
+ to > PAGE_CACHE_SIZE ||
+ to < from);
+ } else {
+ /*
+ * Pages adjacent to the target (if any) imply
+ * a hole-filling write in which case we want
+ * to flush their entire range.
+ */
+ from = 0;
+ to = PAGE_CACHE_SIZE;
+ }
+
+ if (ocfs2_should_order_data(inode))
+ walk_page_buffers(wc->w_handle, page_buffers(tmppage),
+ from, to, NULL,
+ ocfs2_journal_dirty_data);
+
+ block_commit_write(tmppage, from, to);
+ }
+
+ pos += copied;
if (pos > inode->i_size) {
i_size_write(inode, pos);
mark_inode_dirty(inode);
@@ -1283,29 +1582,31 @@ ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+ ocfs2_journal_dirty(handle, wc->w_di_bh);
- ret = ocfs2_journal_dirty(handle, di_bh);
- if (ret)
- mlog_errno(ret);
-
-out_commit:
ocfs2_commit_trans(osb, handle);
-out_data:
- ocfs2_data_unlock(inode, 1);
+ ocfs2_run_deallocs(osb, &wc->w_dealloc);
+
+ ocfs2_free_write_ctxt(wc);
+
+ return copied;
+}
+
+int ocfs2_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ int ret;
+ struct inode *inode = mapping->host;
-out_meta:
+ ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
+
+ ocfs2_data_unlock(inode, 1);
up_write(&OCFS2_I(inode)->ip_alloc_sem);
ocfs2_meta_unlock(inode, 1);
-out:
- brelse(di_bh);
- if (data_ac)
- ocfs2_free_alloc_context(data_ac);
- if (meta_ac)
- ocfs2_free_alloc_context(meta_ac);
-
- return written ? written : ret;
+ return ret;
}
const struct address_space_operations ocfs2_aops = {
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 45821d479b5a..389579bd64e3 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -42,57 +42,22 @@ int walk_page_buffers( handle_t *handle,
int (*fn)( handle_t *handle,
struct buffer_head *bh));
-struct ocfs2_write_ctxt;
-typedef int (ocfs2_page_writer)(struct inode *, struct ocfs2_write_ctxt *,
- u64 *, unsigned int *, unsigned int *);
+int ocfs2_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
-ssize_t ocfs2_buffered_write_cluster(struct file *file, loff_t pos,
- size_t count, ocfs2_page_writer *actor,
- void *priv);
+int ocfs2_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
-struct ocfs2_write_ctxt {
- size_t w_count;
- loff_t w_pos;
- u32 w_cpos;
- unsigned int w_finished_copy;
+int ocfs2_write_end_nolock(struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
- /* This is true if page_size > cluster_size */
- unsigned int w_large_pages;
-
- /* Filler callback and private data */
- ocfs2_page_writer *w_write_data_page;
- void *w_private;
-
- /* Only valid for the filler callback */
- struct page *w_this_page;
- unsigned int w_this_page_new;
-};
-
-struct ocfs2_buffered_write_priv {
- char *b_src_buf;
- const struct iovec *b_cur_iov; /* Current iovec */
- size_t b_cur_off; /* Offset in the
- * current iovec */
-};
-int ocfs2_map_and_write_user_data(struct inode *inode,
- struct ocfs2_write_ctxt *wc,
- u64 *p_blkno,
- unsigned int *ret_from,
- unsigned int *ret_to);
-
-struct ocfs2_splice_write_priv {
- struct splice_desc *s_sd;
- struct pipe_buffer *s_buf;
- struct pipe_inode_info *s_pipe;
- /* Neither offset value is ever larger than one page */
- unsigned int s_offset;
- unsigned int s_buf_offset;
-};
-int ocfs2_map_and_write_splice_data(struct inode *inode,
- struct ocfs2_write_ctxt *wc,
- u64 *p_blkno,
- unsigned int *ret_from,
- unsigned int *ret_to);
+int ocfs2_write_begin_nolock(struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata,
+ struct buffer_head *di_bh, struct page *mmap_page);
/* all ocfs2_dio_end_io()'s fault */
#define ocfs2_iocb_is_rw_locked(iocb) \
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 979113479c66..2bd7f788cf34 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -1335,6 +1335,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
ret = wait_event_interruptible(o2hb_steady_queue,
atomic_read(&reg->hr_steady_iterations) == 0);
if (ret) {
+ /* We got interrupted (hello ptrace!). Clean up */
spin_lock(&o2hb_live_lock);
hb_task = reg->hr_task;
reg->hr_task = NULL;
@@ -1345,7 +1346,16 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
goto out;
}
- ret = count;
+ /* Ok, we were woken. Make sure it wasn't by drop_item() */
+ spin_lock(&o2hb_live_lock);
+ hb_task = reg->hr_task;
+ spin_unlock(&o2hb_live_lock);
+
+ if (hb_task)
+ ret = count;
+ else
+ ret = -EIO;
+
out:
if (filp)
fput(filp);
@@ -1523,6 +1533,15 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
if (hb_task)
kthread_stop(hb_task);
+ /*
+ * If we're racing a dev_write(), we need to wake them. They will
+ * check reg->hr_task
+ */
+ if (atomic_read(&reg->hr_steady_iterations) != 0) {
+ atomic_set(&reg->hr_steady_iterations, 0);
+ wake_up(&o2hb_steady_queue);
+ }
+
config_item_put(item);
}
@@ -1665,7 +1684,67 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc,
}
EXPORT_SYMBOL_GPL(o2hb_setup_callback);
-int o2hb_register_callback(struct o2hb_callback_func *hc)
+static struct o2hb_region *o2hb_find_region(const char *region_uuid)
+{
+ struct o2hb_region *p, *reg = NULL;
+
+ assert_spin_locked(&o2hb_live_lock);
+
+ list_for_each_entry(p, &o2hb_all_regions, hr_all_item) {
+ if (!strcmp(region_uuid, config_item_name(&p->hr_item))) {
+ reg = p;
+ break;
+ }
+ }
+
+ return reg;
+}
+
+static int o2hb_region_get(const char *region_uuid)
+{
+ int ret = 0;
+ struct o2hb_region *reg;
+
+ spin_lock(&o2hb_live_lock);
+
+ reg = o2hb_find_region(region_uuid);
+ if (!reg)
+ ret = -ENOENT;
+ spin_unlock(&o2hb_live_lock);
+
+ if (ret)
+ goto out;
+
+ ret = o2nm_depend_this_node();
+ if (ret)
+ goto out;
+
+ ret = o2nm_depend_item(&reg->hr_item);
+ if (ret)
+ o2nm_undepend_this_node();
+
+out:
+ return ret;
+}
+
+static void o2hb_region_put(const char *region_uuid)
+{
+ struct o2hb_region *reg;
+
+ spin_lock(&o2hb_live_lock);
+
+ reg = o2hb_find_region(region_uuid);
+
+ spin_unlock(&o2hb_live_lock);
+
+ if (reg) {
+ o2nm_undepend_item(&reg->hr_item);
+ o2nm_undepend_this_node();
+ }
+}
+
+int o2hb_register_callback(const char *region_uuid,
+ struct o2hb_callback_func *hc)
{
struct o2hb_callback_func *tmp;
struct list_head *iter;
@@ -1681,6 +1760,12 @@ int o2hb_register_callback(struct o2hb_callback_func *hc)
goto out;
}
+ if (region_uuid) {
+ ret = o2hb_region_get(region_uuid);
+ if (ret)
+ goto out;
+ }
+
down_write(&o2hb_callback_sem);
list_for_each(iter, &hbcall->list) {
@@ -1702,16 +1787,21 @@ out:
}
EXPORT_SYMBOL_GPL(o2hb_register_callback);
-void o2hb_unregister_callback(struct o2hb_callback_func *hc)
+void o2hb_unregister_callback(const char *region_uuid,
+ struct o2hb_callback_func *hc)
{
BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n",
__builtin_return_address(0), hc);
+ /* XXX Can this happen _with_ a region reference? */
if (list_empty(&hc->hc_item))
return;
+ if (region_uuid)
+ o2hb_region_put(region_uuid);
+
down_write(&o2hb_callback_sem);
list_del_init(&hc->hc_item);
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h
index cc6d40b39771..35397dd5ecdb 100644
--- a/fs/ocfs2/cluster/heartbeat.h
+++ b/fs/ocfs2/cluster/heartbeat.h
@@ -69,8 +69,10 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc,
o2hb_cb_func *func,
void *data,
int priority);
-int o2hb_register_callback(struct o2hb_callback_func *hc);
-void o2hb_unregister_callback(struct o2hb_callback_func *hc);
+int o2hb_register_callback(const char *region_uuid,
+ struct o2hb_callback_func *hc);
+void o2hb_unregister_callback(const char *region_uuid,
+ struct o2hb_callback_func *hc);
void o2hb_fill_node_map(unsigned long *map,
unsigned bytes);
void o2hb_init(void);
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index 9f5ad0f01ce0..af2070da308b 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -900,6 +900,46 @@ static struct o2nm_cluster_group o2nm_cluster_group = {
},
};
+int o2nm_depend_item(struct config_item *item)
+{
+ return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
+}
+
+void o2nm_undepend_item(struct config_item *item)
+{
+ configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item);
+}
+
+int o2nm_depend_this_node(void)
+{
+ int ret = 0;
+ struct o2nm_node *local_node;
+
+ local_node = o2nm_get_node_by_num(o2nm_this_node());
+ if (!local_node) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = o2nm_depend_item(&local_node->nd_item);
+ o2nm_node_put(local_node);
+
+out:
+ return ret;
+}
+
+void o2nm_undepend_this_node(void)
+{
+ struct o2nm_node *local_node;
+
+ local_node = o2nm_get_node_by_num(o2nm_this_node());
+ BUG_ON(!local_node);
+
+ o2nm_undepend_item(&local_node->nd_item);
+ o2nm_node_put(local_node);
+}
+
+
static void __exit exit_o2nm(void)
{
if (ocfs2_table_header)
@@ -934,7 +974,7 @@ static int __init init_o2nm(void)
goto out_sysctl;
config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
- init_MUTEX(&o2nm_cluster_group.cs_subsys.su_sem);
+ mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex);
ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
if (ret) {
printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
index 070522138ae2..7c860361b8dd 100644
--- a/fs/ocfs2/cluster/nodemanager.h
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -77,4 +77,9 @@ struct o2nm_node *o2nm_get_node_by_ip(__be32 addr);
void o2nm_node_get(struct o2nm_node *node);
void o2nm_node_put(struct o2nm_node *node);
+int o2nm_depend_item(struct config_item *item);
+void o2nm_undepend_item(struct config_item *item);
+int o2nm_depend_this_node(void);
+void o2nm_undepend_this_node(void);
+
#endif /* O2CLUSTER_NODEMANAGER_H */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 0b229a9c7952..f0bdfd944c44 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -261,14 +261,12 @@ out:
static void o2net_complete_nodes_nsw(struct o2net_node *nn)
{
- struct list_head *iter, *tmp;
+ struct o2net_status_wait *nsw, *tmp;
unsigned int num_kills = 0;
- struct o2net_status_wait *nsw;
assert_spin_locked(&nn->nn_lock);
- list_for_each_safe(iter, tmp, &nn->nn_status_list) {
- nsw = list_entry(iter, struct o2net_status_wait, ns_node_item);
+ list_for_each_entry_safe(nsw, tmp, &nn->nn_status_list, ns_node_item) {
o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0);
num_kills++;
}
@@ -764,13 +762,10 @@ EXPORT_SYMBOL_GPL(o2net_register_handler);
void o2net_unregister_handler_list(struct list_head *list)
{
- struct list_head *pos, *n;
- struct o2net_msg_handler *nmh;
+ struct o2net_msg_handler *nmh, *n;
write_lock(&o2net_handler_lock);
- list_for_each_safe(pos, n, list) {
- nmh = list_entry(pos, struct o2net_msg_handler,
- nh_unregister_item);
+ list_for_each_entry_safe(nmh, n, list, nh_unregister_item) {
mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n",
nmh->nh_func, nmh->nh_msg_type, nmh->nh_key);
rb_erase(&nmh->nh_node, &o2net_handler_tree);
@@ -1638,8 +1633,8 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
void o2net_unregister_hb_callbacks(void)
{
- o2hb_unregister_callback(&o2net_hb_up);
- o2hb_unregister_callback(&o2net_hb_down);
+ o2hb_unregister_callback(NULL, &o2net_hb_up);
+ o2hb_unregister_callback(NULL, &o2net_hb_down);
}
int o2net_register_hb_callbacks(void)
@@ -1651,9 +1646,9 @@ int o2net_register_hb_callbacks(void)
o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB,
o2net_hb_node_up_cb, NULL, O2NET_HB_PRI);
- ret = o2hb_register_callback(&o2net_hb_up);
+ ret = o2hb_register_callback(NULL, &o2net_hb_up);
if (ret == 0)
- ret = o2hb_register_callback(&o2net_hb_down);
+ ret = o2hb_register_callback(NULL, &o2net_hb_down);
if (ret)
o2net_unregister_hb_callbacks();
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index c441ef1f2bad..0d5fdde959c8 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -368,7 +368,7 @@ int ocfs2_do_extend_dir(struct super_block *sb,
u32 offset = OCFS2_I(dir)->ip_clusters;
status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
- 1, parent_fe_bh, handle,
+ 1, 0, parent_fe_bh, handle,
data_ac, meta_ac, NULL);
BUG_ON(status == -EAGAIN);
if (status < 0) {
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index d836b98dd99a..6954565b8ccb 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -1128,8 +1128,8 @@ bail:
static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
{
- o2hb_unregister_callback(&dlm->dlm_hb_up);
- o2hb_unregister_callback(&dlm->dlm_hb_down);
+ o2hb_unregister_callback(NULL, &dlm->dlm_hb_up);
+ o2hb_unregister_callback(NULL, &dlm->dlm_hb_down);
o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
}
@@ -1141,13 +1141,13 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm)
o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
- status = o2hb_register_callback(&dlm->dlm_hb_down);
+ status = o2hb_register_callback(NULL, &dlm->dlm_hb_down);
if (status)
goto bail;
o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
- status = o2hb_register_callback(&dlm->dlm_hb_up);
+ status = o2hb_register_callback(NULL, &dlm->dlm_hb_up);
if (status)
goto bail;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 6edffca99d98..65b2b9b92688 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -192,25 +192,20 @@ static void dlm_print_one_mle(struct dlm_master_list_entry *mle)
static void dlm_dump_mles(struct dlm_ctxt *dlm)
{
struct dlm_master_list_entry *mle;
- struct list_head *iter;
mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
spin_lock(&dlm->master_lock);
- list_for_each(iter, &dlm->master_list) {
- mle = list_entry(iter, struct dlm_master_list_entry, list);
+ list_for_each_entry(mle, &dlm->master_list, list)
dlm_print_one_mle(mle);
- }
spin_unlock(&dlm->master_lock);
}
int dlm_dump_all_mles(const char __user *data, unsigned int len)
{
- struct list_head *iter;
struct dlm_ctxt *dlm;
spin_lock(&dlm_domain_lock);
- list_for_each(iter, &dlm_domains) {
- dlm = list_entry (iter, struct dlm_ctxt, list);
+ list_for_each_entry(dlm, &dlm_domains, list) {
mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
dlm_dump_mles(dlm);
}
@@ -454,12 +449,10 @@ static int dlm_find_mle(struct dlm_ctxt *dlm,
char *name, unsigned int namelen)
{
struct dlm_master_list_entry *tmpmle;
- struct list_head *iter;
assert_spin_locked(&dlm->master_lock);
- list_for_each(iter, &dlm->master_list) {
- tmpmle = list_entry(iter, struct dlm_master_list_entry, list);
+ list_for_each_entry(tmpmle, &dlm->master_list, list) {
if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
continue;
dlm_get_mle(tmpmle);
@@ -472,13 +465,10 @@ static int dlm_find_mle(struct dlm_ctxt *dlm,
void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
{
struct dlm_master_list_entry *mle;
- struct list_head *iter;
assert_spin_locked(&dlm->spinlock);
- list_for_each(iter, &dlm->mle_hb_events) {
- mle = list_entry(iter, struct dlm_master_list_entry,
- hb_events);
+ list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) {
if (node_up)
dlm_mle_node_up(dlm, mle, NULL, idx);
else
@@ -2434,7 +2424,7 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
int ret;
int i;
int count = 0;
- struct list_head *queue, *iter;
+ struct list_head *queue;
struct dlm_lock *lock;
assert_spin_locked(&res->spinlock);
@@ -2453,8 +2443,7 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
ret = 0;
queue = &res->granted;
for (i = 0; i < 3; i++) {
- list_for_each(iter, queue) {
- lock = list_entry(iter, struct dlm_lock, list);
+ list_for_each_entry(lock, queue, list) {
++count;
if (lock->ml.node == dlm->node_num) {
mlog(0, "found a lock owned by this node still "
@@ -2923,18 +2912,16 @@ again:
static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res)
{
- struct list_head *iter, *iter2;
struct list_head *queue = &res->granted;
int i, bit;
- struct dlm_lock *lock;
+ struct dlm_lock *lock, *next;
assert_spin_locked(&res->spinlock);
BUG_ON(res->owner == dlm->node_num);
for (i=0; i<3; i++) {
- list_for_each_safe(iter, iter2, queue) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry_safe(lock, next, queue, list) {
if (lock->ml.node != dlm->node_num) {
mlog(0, "putting lock for node %u\n",
lock->ml.node);
@@ -2976,7 +2963,6 @@ static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,
{
int i;
struct list_head *queue = &res->granted;
- struct list_head *iter;
struct dlm_lock *lock;
int nodenum;
@@ -2984,10 +2970,9 @@ static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,
spin_lock(&res->spinlock);
for (i=0; i<3; i++) {
- list_for_each(iter, queue) {
+ list_for_each_entry(lock, queue, list) {
/* up to the caller to make sure this node
* is alive */
- lock = list_entry (iter, struct dlm_lock, list);
if (lock->ml.node != dlm->node_num) {
spin_unlock(&res->spinlock);
return lock->ml.node;
@@ -3234,8 +3219,7 @@ static int dlm_add_migration_mle(struct dlm_ctxt *dlm,
void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
{
- struct list_head *iter, *iter2;
- struct dlm_master_list_entry *mle;
+ struct dlm_master_list_entry *mle, *next;
struct dlm_lock_resource *res;
unsigned int hash;
@@ -3245,9 +3229,7 @@ top:
/* clean the master list */
spin_lock(&dlm->master_lock);
- list_for_each_safe(iter, iter2, &dlm->master_list) {
- mle = list_entry(iter, struct dlm_master_list_entry, list);
-
+ list_for_each_entry_safe(mle, next, &dlm->master_list, list) {
BUG_ON(mle->type != DLM_MLE_BLOCK &&
mle->type != DLM_MLE_MASTER &&
mle->type != DLM_MLE_MIGRATION);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 671c4ed58ee2..a2c33160bfd6 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -158,8 +158,7 @@ void dlm_dispatch_work(struct work_struct *work)
struct dlm_ctxt *dlm =
container_of(work, struct dlm_ctxt, dispatched_work);
LIST_HEAD(tmp_list);
- struct list_head *iter, *iter2;
- struct dlm_work_item *item;
+ struct dlm_work_item *item, *next;
dlm_workfunc_t *workfunc;
int tot=0;
@@ -167,13 +166,12 @@ void dlm_dispatch_work(struct work_struct *work)
list_splice_init(&dlm->work_list, &tmp_list);
spin_unlock(&dlm->work_lock);
- list_for_each_safe(iter, iter2, &tmp_list) {
+ list_for_each_entry(item, &tmp_list, list) {
tot++;
}
mlog(0, "%s: work thread has %d work items\n", dlm->name, tot);
- list_for_each_safe(iter, iter2, &tmp_list) {
- item = list_entry(iter, struct dlm_work_item, list);
+ list_for_each_entry_safe(item, next, &tmp_list, list) {
workfunc = item->func;
list_del_init(&item->list);
@@ -549,7 +547,6 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
{
int status = 0;
struct dlm_reco_node_data *ndata;
- struct list_head *iter;
int all_nodes_done;
int destroy = 0;
int pass = 0;
@@ -567,8 +564,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
/* safe to access the node data list without a lock, since this
* process is the only one to change the list */
- list_for_each(iter, &dlm->reco.node_data) {
- ndata = list_entry (iter, struct dlm_reco_node_data, list);
+ list_for_each_entry(ndata, &dlm->reco.node_data, list) {
BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
@@ -655,9 +651,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
* done, or if anyone died */
all_nodes_done = 1;
spin_lock(&dlm_reco_state_lock);
- list_for_each(iter, &dlm->reco.node_data) {
- ndata = list_entry (iter, struct dlm_reco_node_data, list);
-
+ list_for_each_entry(ndata, &dlm->reco.node_data, list) {
mlog(0, "checking recovery state of node %u\n",
ndata->node_num);
switch (ndata->state) {
@@ -774,16 +768,14 @@ static int dlm_init_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
{
- struct list_head *iter, *iter2;
- struct dlm_reco_node_data *ndata;
+ struct dlm_reco_node_data *ndata, *next;
LIST_HEAD(tmplist);
spin_lock(&dlm_reco_state_lock);
list_splice_init(&dlm->reco.node_data, &tmplist);
spin_unlock(&dlm_reco_state_lock);
- list_for_each_safe(iter, iter2, &tmplist) {
- ndata = list_entry (iter, struct dlm_reco_node_data, list);
+ list_for_each_entry_safe(ndata, next, &tmplist, list) {
list_del_init(&ndata->list);
kfree(ndata);
}
@@ -876,7 +868,6 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data)
struct dlm_lock_resource *res;
struct dlm_ctxt *dlm;
LIST_HEAD(resources);
- struct list_head *iter;
int ret;
u8 dead_node, reco_master;
int skip_all_done = 0;
@@ -920,8 +911,7 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data)
/* any errors returned will be due to the new_master dying,
* the dlm_reco_thread should detect this */
- list_for_each(iter, &resources) {
- res = list_entry (iter, struct dlm_lock_resource, recovering);
+ list_for_each_entry(res, &resources, recovering) {
ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
DLM_MRES_RECOVERY);
if (ret < 0) {
@@ -983,7 +973,6 @@ int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data,
{
struct dlm_ctxt *dlm = data;
struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
- struct list_head *iter;
struct dlm_reco_node_data *ndata = NULL;
int ret = -EINVAL;
@@ -1000,8 +989,7 @@ int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data,
dlm->reco.dead_node, done->node_idx, dlm->node_num);
spin_lock(&dlm_reco_state_lock);
- list_for_each(iter, &dlm->reco.node_data) {
- ndata = list_entry (iter, struct dlm_reco_node_data, list);
+ list_for_each_entry(ndata, &dlm->reco.node_data, list) {
if (ndata->node_num != done->node_idx)
continue;
@@ -1049,13 +1037,11 @@ static void dlm_move_reco_locks_to_list(struct dlm_ctxt *dlm,
struct list_head *list,
u8 dead_node)
{
- struct dlm_lock_resource *res;
- struct list_head *iter, *iter2;
+ struct dlm_lock_resource *res, *next;
struct dlm_lock *lock;
spin_lock(&dlm->spinlock);
- list_for_each_safe(iter, iter2, &dlm->reco.resources) {
- res = list_entry (iter, struct dlm_lock_resource, recovering);
+ list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
/* always prune any $RECOVERY entries for dead nodes,
* otherwise hangs can occur during later recovery */
if (dlm_is_recovery_lock(res->lockname.name,
@@ -1169,7 +1155,7 @@ static void dlm_init_migratable_lockres(struct dlm_migratable_lockres *mres,
u8 flags, u8 master)
{
/* mres here is one full page */
- memset(mres, 0, PAGE_SIZE);
+ clear_page(mres);
mres->lockname_len = namelen;
memcpy(mres->lockname, lockname, namelen);
mres->num_locks = 0;
@@ -1252,7 +1238,7 @@ int dlm_send_one_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
struct dlm_migratable_lockres *mres,
u8 send_to, u8 flags)
{
- struct list_head *queue, *iter;
+ struct list_head *queue;
int total_locks, i;
u64 mig_cookie = 0;
struct dlm_lock *lock;
@@ -1278,9 +1264,7 @@ int dlm_send_one_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
total_locks = 0;
for (i=DLM_GRANTED_LIST; i<=DLM_BLOCKED_LIST; i++) {
queue = dlm_list_idx_to_ptr(res, i);
- list_for_each(iter, queue) {
- lock = list_entry (iter, struct dlm_lock, list);
-
+ list_for_each_entry(lock, queue, list) {
/* add another lock. */
total_locks++;
if (!dlm_add_lock_to_array(lock, mres, i))
@@ -1717,7 +1701,6 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
struct dlm_lockstatus *lksb = NULL;
int ret = 0;
int i, j, bad;
- struct list_head *iter;
struct dlm_lock *lock = NULL;
u8 from = O2NM_MAX_NODES;
unsigned int added = 0;
@@ -1755,8 +1738,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
spin_lock(&res->spinlock);
for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
tmpq = dlm_list_idx_to_ptr(res, j);
- list_for_each(iter, tmpq) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry(lock, tmpq, list) {
if (lock->ml.cookie != ml->cookie)
lock = NULL;
else
@@ -1930,8 +1912,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res)
{
int i;
- struct list_head *queue, *iter, *iter2;
- struct dlm_lock *lock;
+ struct list_head *queue;
+ struct dlm_lock *lock, *next;
res->state |= DLM_LOCK_RES_RECOVERING;
if (!list_empty(&res->recovering)) {
@@ -1947,8 +1929,7 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
/* find any pending locks and put them back on proper list */
for (i=DLM_BLOCKED_LIST; i>=DLM_GRANTED_LIST; i--) {
queue = dlm_list_idx_to_ptr(res, i);
- list_for_each_safe(iter, iter2, queue) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry_safe(lock, next, queue, list) {
dlm_lock_get(lock);
if (lock->convert_pending) {
/* move converting lock back to granted */
@@ -2013,18 +1994,15 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
u8 dead_node, u8 new_master)
{
int i;
- struct list_head *iter, *iter2;
struct hlist_node *hash_iter;
struct hlist_head *bucket;
-
- struct dlm_lock_resource *res;
+ struct dlm_lock_resource *res, *next;
mlog_entry_void();
assert_spin_locked(&dlm->spinlock);
- list_for_each_safe(iter, iter2, &dlm->reco.resources) {
- res = list_entry (iter, struct dlm_lock_resource, recovering);
+ list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
if (res->owner == dead_node) {
list_del_init(&res->recovering);
spin_lock(&res->spinlock);
@@ -2099,7 +2077,7 @@ static inline int dlm_lvb_needs_invalidation(struct dlm_lock *lock, int local)
static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res, u8 dead_node)
{
- struct list_head *iter, *queue;
+ struct list_head *queue;
struct dlm_lock *lock;
int blank_lvb = 0, local = 0;
int i;
@@ -2121,8 +2099,7 @@ static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
for (i=DLM_GRANTED_LIST; i<=DLM_CONVERTING_LIST; i++) {
queue = dlm_list_idx_to_ptr(res, i);
- list_for_each(iter, queue) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry(lock, queue, list) {
if (lock->ml.node == search_node) {
if (dlm_lvb_needs_invalidation(lock, local)) {
/* zero the lksb lvb and lockres lvb */
@@ -2143,8 +2120,7 @@ static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res, u8 dead_node)
{
- struct list_head *iter, *tmpiter;
- struct dlm_lock *lock;
+ struct dlm_lock *lock, *next;
unsigned int freed = 0;
/* this node is the lockres master:
@@ -2155,24 +2131,21 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
assert_spin_locked(&res->spinlock);
/* TODO: check pending_asts, pending_basts here */
- list_for_each_safe(iter, tmpiter, &res->granted) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry_safe(lock, next, &res->granted, list) {
if (lock->ml.node == dead_node) {
list_del_init(&lock->list);
dlm_lock_put(lock);
freed++;
}
}
- list_for_each_safe(iter, tmpiter, &res->converting) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry_safe(lock, next, &res->converting, list) {
if (lock->ml.node == dead_node) {
list_del_init(&lock->list);
dlm_lock_put(lock);
freed++;
}
}
- list_for_each_safe(iter, tmpiter, &res->blocked) {
- lock = list_entry (iter, struct dlm_lock, list);
+ list_for_each_entry_safe(lock, next, &res->blocked, list) {
if (lock->ml.node == dead_node) {
list_del_init(&lock->list);
dlm_lock_put(lock);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index d1bd305ef0d7..f71250ed166f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -600,15 +600,13 @@ static inline int ocfs2_highest_compat_lock_level(int level)
static void lockres_set_flags(struct ocfs2_lock_res *lockres,
unsigned long newflags)
{
- struct list_head *pos, *tmp;
- struct ocfs2_mask_waiter *mw;
+ struct ocfs2_mask_waiter *mw, *tmp;
assert_spin_locked(&lockres->l_lock);
lockres->l_flags = newflags;
- list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) {
- mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item);
+ list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {
if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
continue;
diff --git a/fs/ocfs2/endian.h b/fs/ocfs2/endian.h
index f226b2207628..ff257628af16 100644
--- a/fs/ocfs2/endian.h
+++ b/fs/ocfs2/endian.h
@@ -32,6 +32,11 @@ static inline void le32_add_cpu(__le32 *var, u32 val)
*var = cpu_to_le32(le32_to_cpu(*var) + val);
}
+static inline void le64_add_cpu(__le64 *var, u64 val)
+{
+ *var = cpu_to_le64(le64_to_cpu(*var) + val);
+}
+
static inline void le32_and_cpu(__le32 *var, u32 val)
{
*var = cpu_to_le32(le32_to_cpu(*var) & val);
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h
index 5b77ee7866ef..e08bed9e45a0 100644
--- a/fs/ocfs2/export.h
+++ b/fs/ocfs2/export.h
@@ -26,6 +26,8 @@
#ifndef OCFS2_EXPORT_H
#define OCFS2_EXPORT_H
+#include <linux/exportfs.h>
+
extern struct export_operations ocfs2_export_ops;
#endif /* OCFS2_EXPORT_H */
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index ba2b2ab1c6e4..03c1d365c78b 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -109,17 +109,14 @@ static int ocfs2_extent_map_lookup(struct inode *inode, unsigned int cpos,
*/
void ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
{
- struct list_head *p, *n;
- struct ocfs2_extent_map_item *emi;
+ struct ocfs2_extent_map_item *emi, *n;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_extent_map *em = &oi->ip_extent_map;
LIST_HEAD(tmp_list);
unsigned int range;
spin_lock(&oi->ip_lock);
- list_for_each_safe(p, n, &em->em_list) {
- emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
-
+ list_for_each_entry_safe(emi, n, &em->em_list, ei_list) {
if (emi->ei_cpos >= cpos) {
/* Full truncate of this record. */
list_move(&emi->ei_list, &tmp_list);
@@ -136,8 +133,7 @@ void ocfs2_extent_map_trunc(struct inode *inode, unsigned int cpos)
}
spin_unlock(&oi->ip_lock);
- list_for_each_safe(p, n, &tmp_list) {
- emi = list_entry(p, struct ocfs2_extent_map_item, ei_list);
+ list_for_each_entry_safe(emi, n, &tmp_list, ei_list) {
list_del(&emi->ei_list);
kfree(emi);
}
@@ -377,37 +373,6 @@ out:
return ret;
}
-/*
- * Return the index of the extent record which contains cluster #v_cluster.
- * -1 is returned if it was not found.
- *
- * Should work fine on interior and exterior nodes.
- */
-static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
- u32 v_cluster)
-{
- int ret = -1;
- int i;
- struct ocfs2_extent_rec *rec;
- u32 rec_end, rec_start, clusters;
-
- for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
- rec = &el->l_recs[i];
-
- rec_start = le32_to_cpu(rec->e_cpos);
- clusters = ocfs2_rec_clusters(el, rec);
-
- rec_end = rec_start + clusters;
-
- if (v_cluster >= rec_start && v_cluster < rec_end) {
- ret = i;
- break;
- }
- }
-
- return ret;
-}
-
int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
u32 *p_cluster, u32 *num_clusters,
unsigned int *extent_flags)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 4979b6675717..004c2abbc732 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -263,6 +263,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
int status;
handle_t *handle;
struct ocfs2_dinode *di;
+ u64 cluster_bytes;
mlog_entry_void();
@@ -286,7 +287,9 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
/*
* Do this before setting i_size.
*/
- status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size);
+ cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
+ status = ocfs2_zero_range_for_truncate(inode, handle, new_i_size,
+ cluster_bytes);
if (status) {
mlog_errno(status);
goto out_commit;
@@ -326,9 +329,6 @@ static int ocfs2_truncate_file(struct inode *inode,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
(unsigned long long)new_i_size);
- unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
- truncate_inode_pages(inode->i_mapping, new_i_size);
-
fe = (struct ocfs2_dinode *) di_bh->b_data;
if (!OCFS2_IS_VALID_DINODE(fe)) {
OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
@@ -363,16 +363,23 @@ static int ocfs2_truncate_file(struct inode *inode,
if (new_i_size == le64_to_cpu(fe->i_size))
goto bail;
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
/* This forces other nodes to sync and drop their pages. Do
* this even if we have a truncate without allocation change -
* ocfs2 cluster sizes can be much greater than page size, so
* we have to truncate them anyway. */
status = ocfs2_data_lock(inode, 1);
if (status < 0) {
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
mlog_errno(status);
goto bail;
}
+ unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
+ truncate_inode_pages(inode->i_mapping, new_i_size);
+
/* alright, we're going to need to do a full blown alloc size
* change. Orphan the inode so that recovery can complete the
* truncate if necessary. This does the task of marking
@@ -399,6 +406,8 @@ static int ocfs2_truncate_file(struct inode *inode,
bail_unlock_data:
ocfs2_data_unlock(inode, 1);
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
bail:
mlog_exit(status);
@@ -419,6 +428,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
struct inode *inode,
u32 *logical_offset,
u32 clusters_to_add,
+ int mark_unwritten,
struct buffer_head *fe_bh,
handle_t *handle,
struct ocfs2_alloc_context *data_ac,
@@ -431,9 +441,13 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
enum ocfs2_alloc_restarted reason = RESTART_NONE;
u32 bit_off, num_bits;
u64 block;
+ u8 flags = 0;
BUG_ON(!clusters_to_add);
+ if (mark_unwritten)
+ flags = OCFS2_EXT_UNWRITTEN;
+
free_extents = ocfs2_num_free_extents(osb, inode, fe);
if (free_extents < 0) {
status = free_extents;
@@ -483,7 +497,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
*logical_offset, block, num_bits,
- meta_ac);
+ flags, meta_ac);
if (status < 0) {
mlog_errno(status);
goto leave;
@@ -516,25 +530,31 @@ leave:
* For a given allocation, determine which allocators will need to be
* accessed, and lock them, reserving the appropriate number of bits.
*
- * Called from ocfs2_extend_allocation() for file systems which don't
- * support holes, and from ocfs2_write() for file systems which
- * understand sparse inodes.
+ * Sparse file systems call this from ocfs2_write_begin_nolock()
+ * and ocfs2_allocate_unwritten_extents().
+ *
+ * File systems which don't support holes call this from
+ * ocfs2_extend_allocation().
*/
int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
- u32 clusters_to_add,
+ u32 clusters_to_add, u32 extents_to_split,
struct ocfs2_alloc_context **data_ac,
struct ocfs2_alloc_context **meta_ac)
{
- int ret, num_free_extents;
+ int ret = 0, num_free_extents;
+ unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
*meta_ac = NULL;
- *data_ac = NULL;
+ if (data_ac)
+ *data_ac = NULL;
+
+ BUG_ON(clusters_to_add != 0 && data_ac == NULL);
mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
- "clusters_to_add = %u\n",
+ "clusters_to_add = %u, extents_to_split = %u\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
- le32_to_cpu(di->i_clusters), clusters_to_add);
+ le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
num_free_extents = ocfs2_num_free_extents(osb, inode, di);
if (num_free_extents < 0) {
@@ -552,9 +572,12 @@ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
*
* Most of the time we'll only be seeing this 1 cluster at a time
* anyway.
+ *
+ * Always lock for any unwritten extents - we might want to
+ * add blocks during a split.
*/
if (!num_free_extents ||
- (ocfs2_sparse_alloc(osb) && num_free_extents < clusters_to_add)) {
+ (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
if (ret < 0) {
if (ret != -ENOSPC)
@@ -563,6 +586,9 @@ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
}
}
+ if (clusters_to_add == 0)
+ goto out;
+
ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
if (ret < 0) {
if (ret != -ENOSPC)
@@ -585,14 +611,13 @@ out:
return ret;
}
-static int ocfs2_extend_allocation(struct inode *inode,
- u32 clusters_to_add)
+static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+ u32 clusters_to_add, int mark_unwritten)
{
int status = 0;
int restart_func = 0;
- int drop_alloc_sem = 0;
int credits;
- u32 prev_clusters, logical_start;
+ u32 prev_clusters;
struct buffer_head *bh = NULL;
struct ocfs2_dinode *fe = NULL;
handle_t *handle = NULL;
@@ -607,7 +632,7 @@ static int ocfs2_extend_allocation(struct inode *inode,
* This function only exists for file systems which don't
* support holes.
*/
- BUG_ON(ocfs2_sparse_alloc(osb));
+ BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
OCFS2_BH_CACHED, inode);
@@ -623,19 +648,10 @@ static int ocfs2_extend_allocation(struct inode *inode,
goto leave;
}
- logical_start = OCFS2_I(inode)->ip_clusters;
-
restart_all:
BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
- /* blocks peope in read/write from reading our allocation
- * until we're done changing it. We depend on i_mutex to block
- * other extend/truncate calls while we're here. Ordering wrt
- * start_trans is important here -- always do it before! */
- down_write(&OCFS2_I(inode)->ip_alloc_sem);
- drop_alloc_sem = 1;
-
- status = ocfs2_lock_allocators(inode, fe, clusters_to_add, &data_ac,
+ status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
&meta_ac);
if (status) {
mlog_errno(status);
@@ -668,6 +684,7 @@ restarted_transaction:
inode,
&logical_start,
clusters_to_add,
+ mark_unwritten,
bh,
handle,
data_ac,
@@ -720,10 +737,6 @@ restarted_transaction:
OCFS2_I(inode)->ip_clusters, i_size_read(inode));
leave:
- if (drop_alloc_sem) {
- up_write(&OCFS2_I(inode)->ip_alloc_sem);
- drop_alloc_sem = 0;
- }
if (handle) {
ocfs2_commit_trans(osb, handle);
handle = NULL;
@@ -749,6 +762,25 @@ leave:
return status;
}
+static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
+ u32 clusters_to_add, int mark_unwritten)
+{
+ int ret;
+
+ /*
+ * The alloc sem blocks peope in read/write from reading our
+ * allocation until we're done changing it. We depend on
+ * i_mutex to block other extend/truncate calls while we're
+ * here.
+ */
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+ ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add,
+ mark_unwritten);
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ return ret;
+}
+
/* Some parts of this taken from generic_cont_expand, which turned out
* to be too fragile to do exactly what we need without us having to
* worry about recursive locking in ->prepare_write() and
@@ -890,7 +922,9 @@ static int ocfs2_extend_file(struct inode *inode,
}
if (clusters_to_add) {
- ret = ocfs2_extend_allocation(inode, clusters_to_add);
+ ret = ocfs2_extend_allocation(inode,
+ OCFS2_I(inode)->ip_clusters,
+ clusters_to_add, 0);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
@@ -995,6 +1029,13 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
goto bail_unlock;
}
+ /*
+ * This will intentionally not wind up calling vmtruncate(),
+ * since all the work for a size change has been done above.
+ * Otherwise, we could get into problems with truncate as
+ * ip_alloc_sem is used there to protect against i_size
+ * changes.
+ */
status = inode_setattr(inode, attr);
if (status < 0) {
mlog_errno(status);
@@ -1070,17 +1111,16 @@ out:
return ret;
}
-static int ocfs2_write_remove_suid(struct inode *inode)
+static int __ocfs2_write_remove_suid(struct inode *inode,
+ struct buffer_head *bh)
{
int ret;
- struct buffer_head *bh = NULL;
- struct ocfs2_inode_info *oi = OCFS2_I(inode);
handle_t *handle;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_dinode *di;
mlog_entry("(Inode %llu, mode 0%o)\n",
- (unsigned long long)oi->ip_blkno, inode->i_mode);
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode);
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
if (handle == NULL) {
@@ -1089,17 +1129,11 @@ static int ocfs2_write_remove_suid(struct inode *inode)
goto out;
}
- ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
- if (ret < 0) {
- mlog_errno(ret);
- goto out_trans;
- }
-
ret = ocfs2_journal_access(handle, inode, bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret < 0) {
mlog_errno(ret);
- goto out_bh;
+ goto out_trans;
}
inode->i_mode &= ~S_ISUID;
@@ -1112,8 +1146,7 @@ static int ocfs2_write_remove_suid(struct inode *inode)
ret = ocfs2_journal_dirty(handle, bh);
if (ret < 0)
mlog_errno(ret);
-out_bh:
- brelse(bh);
+
out_trans:
ocfs2_commit_trans(osb, handle);
out:
@@ -1159,6 +1192,460 @@ out:
return ret;
}
+static int ocfs2_write_remove_suid(struct inode *inode)
+{
+ int ret;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = __ocfs2_write_remove_suid(inode, bh);
+out:
+ brelse(bh);
+ return ret;
+}
+
+/*
+ * Allocate enough extents to cover the region starting at byte offset
+ * start for len bytes. Existing extents are skipped, any extents
+ * added are marked as "unwritten".
+ */
+static int ocfs2_allocate_unwritten_extents(struct inode *inode,
+ u64 start, u64 len)
+{
+ int ret;
+ u32 cpos, phys_cpos, clusters, alloc_size;
+
+ /*
+ * We consider both start and len to be inclusive.
+ */
+ cpos = start >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+ clusters = ocfs2_clusters_for_bytes(inode->i_sb, start + len);
+ clusters -= cpos;
+
+ while (clusters) {
+ ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+ &alloc_size, NULL);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * Hole or existing extent len can be arbitrary, so
+ * cap it to our own allocation request.
+ */
+ if (alloc_size > clusters)
+ alloc_size = clusters;
+
+ if (phys_cpos) {
+ /*
+ * We already have an allocation at this
+ * region so we can safely skip it.
+ */
+ goto next;
+ }
+
+ ret = __ocfs2_extend_allocation(inode, cpos, alloc_size, 1);
+ if (ret) {
+ if (ret != -ENOSPC)
+ mlog_errno(ret);
+ goto out;
+ }
+
+next:
+ cpos += alloc_size;
+ clusters -= alloc_size;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+static int __ocfs2_remove_inode_range(struct inode *inode,
+ struct buffer_head *di_bh,
+ u32 cpos, u32 phys_cpos, u32 len,
+ struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+ int ret;
+ u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct inode *tl_inode = osb->osb_tl_inode;
+ handle_t *handle;
+ struct ocfs2_alloc_context *meta_ac = NULL;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+
+ ret = ocfs2_lock_allocators(inode, di, 0, 1, NULL, &meta_ac);
+ if (ret) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ mutex_lock(&tl_inode->i_mutex);
+
+ if (ocfs2_truncate_log_needs_flush(osb)) {
+ ret = __ocfs2_flush_truncate_log(osb);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+ if (handle == NULL) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_journal_access(handle, inode, di_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
+ dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+
+ OCFS2_I(inode)->ip_clusters -= len;
+ di->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
+
+ ret = ocfs2_journal_dirty(handle, di_bh);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+
+ ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
+ if (ret)
+ mlog_errno(ret);
+
+out_commit:
+ ocfs2_commit_trans(osb, handle);
+out:
+ mutex_unlock(&tl_inode->i_mutex);
+
+ if (meta_ac)
+ ocfs2_free_alloc_context(meta_ac);
+
+ return ret;
+}
+
+/*
+ * Truncate a byte range, avoiding pages within partial clusters. This
+ * preserves those pages for the zeroing code to write to.
+ */
+static void ocfs2_truncate_cluster_pages(struct inode *inode, u64 byte_start,
+ u64 byte_len)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ loff_t start, end;
+ struct address_space *mapping = inode->i_mapping;
+
+ start = (loff_t)ocfs2_align_bytes_to_clusters(inode->i_sb, byte_start);
+ end = byte_start + byte_len;
+ end = end & ~(osb->s_clustersize - 1);
+
+ if (start < end) {
+ unmap_mapping_range(mapping, start, end - start, 0);
+ truncate_inode_pages_range(mapping, start, end - 1);
+ }
+}
+
+static int ocfs2_zero_partial_clusters(struct inode *inode,
+ u64 start, u64 len)
+{
+ int ret = 0;
+ u64 tmpend, end = start + len;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ unsigned int csize = osb->s_clustersize;
+ handle_t *handle;
+
+ /*
+ * The "start" and "end" values are NOT necessarily part of
+ * the range whose allocation is being deleted. Rather, this
+ * is what the user passed in with the request. We must zero
+ * partial clusters here. There's no need to worry about
+ * physical allocation - the zeroing code knows to skip holes.
+ */
+ mlog(0, "byte start: %llu, end: %llu\n",
+ (unsigned long long)start, (unsigned long long)end);
+
+ /*
+ * If both edges are on a cluster boundary then there's no
+ * zeroing required as the region is part of the allocation to
+ * be truncated.
+ */
+ if ((start & (csize - 1)) == 0 && (end & (csize - 1)) == 0)
+ goto out;
+
+ handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+ if (handle == NULL) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * We want to get the byte offset of the end of the 1st cluster.
+ */
+ tmpend = (u64)osb->s_clustersize + (start & ~(osb->s_clustersize - 1));
+ if (tmpend > end)
+ tmpend = end;
+
+ mlog(0, "1st range: start: %llu, tmpend: %llu\n",
+ (unsigned long long)start, (unsigned long long)tmpend);
+
+ ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend);
+ if (ret)
+ mlog_errno(ret);
+
+ if (tmpend < end) {
+ /*
+ * This may make start and end equal, but the zeroing
+ * code will skip any work in that case so there's no
+ * need to catch it up here.
+ */
+ start = end & ~(osb->s_clustersize - 1);
+
+ mlog(0, "2nd range: start: %llu, end: %llu\n",
+ (unsigned long long)start, (unsigned long long)end);
+
+ ret = ocfs2_zero_range_for_truncate(inode, handle, start, end);
+ if (ret)
+ mlog_errno(ret);
+ }
+
+ ocfs2_commit_trans(osb, handle);
+out:
+ return ret;
+}
+
+static int ocfs2_remove_inode_range(struct inode *inode,
+ struct buffer_head *di_bh, u64 byte_start,
+ u64 byte_len)
+{
+ int ret = 0;
+ u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_cached_dealloc_ctxt dealloc;
+
+ ocfs2_init_dealloc_ctxt(&dealloc);
+
+ if (byte_len == 0)
+ return 0;
+
+ trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start);
+ trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits;
+ if (trunc_len >= trunc_start)
+ trunc_len -= trunc_start;
+ else
+ trunc_len = 0;
+
+ mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, clen: %u\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)byte_start,
+ (unsigned long long)byte_len, trunc_start, trunc_len);
+
+ ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ cpos = trunc_start;
+ while (trunc_len) {
+ ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
+ &alloc_size, NULL);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (alloc_size > trunc_len)
+ alloc_size = trunc_len;
+
+ /* Only do work for non-holes */
+ if (phys_cpos != 0) {
+ ret = __ocfs2_remove_inode_range(inode, di_bh, cpos,
+ phys_cpos, alloc_size,
+ &dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+ cpos += alloc_size;
+ trunc_len -= alloc_size;
+ }
+
+ ocfs2_truncate_cluster_pages(inode, byte_start, byte_len);
+
+out:
+ ocfs2_schedule_truncate_log_flush(osb, 1);
+ ocfs2_run_deallocs(osb, &dealloc);
+
+ return ret;
+}
+
+/*
+ * Parts of this function taken from xfs_change_file_space()
+ */
+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+ struct ocfs2_space_resv *sr)
+{
+ int ret;
+ s64 llen;
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct buffer_head *di_bh = NULL;
+ handle_t *handle;
+ unsigned long long max_off = ocfs2_max_file_offset(inode->i_sb->s_blocksize_bits);
+
+ if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) &&
+ !ocfs2_writes_unwritten_extents(osb))
+ return -ENOTTY;
+ else if ((cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) &&
+ !ocfs2_sparse_alloc(osb))
+ return -ENOTTY;
+
+ if (!S_ISREG(inode->i_mode))
+ return -EINVAL;
+
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EBADF;
+
+ if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+ return -EROFS;
+
+ mutex_lock(&inode->i_mutex);
+
+ /*
+ * This prevents concurrent writes on other nodes
+ */
+ ret = ocfs2_rw_lock(inode, 1);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_meta_lock(inode, &di_bh, 1);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_rw_unlock;
+ }
+
+ if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
+ ret = -EPERM;
+ goto out_meta_unlock;
+ }
+
+ switch (sr->l_whence) {
+ case 0: /*SEEK_SET*/
+ break;
+ case 1: /*SEEK_CUR*/
+ sr->l_start += file->f_pos;
+ break;
+ case 2: /*SEEK_END*/
+ sr->l_start += i_size_read(inode);
+ break;
+ default:
+ ret = -EINVAL;
+ goto out_meta_unlock;
+ }
+ sr->l_whence = 0;
+
+ llen = sr->l_len > 0 ? sr->l_len - 1 : sr->l_len;
+
+ if (sr->l_start < 0
+ || sr->l_start > max_off
+ || (sr->l_start + llen) < 0
+ || (sr->l_start + llen) > max_off) {
+ ret = -EINVAL;
+ goto out_meta_unlock;
+ }
+
+ if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
+ if (sr->l_len <= 0) {
+ ret = -EINVAL;
+ goto out_meta_unlock;
+ }
+ }
+
+ if (should_remove_suid(file->f_path.dentry)) {
+ ret = __ocfs2_write_remove_suid(inode, di_bh);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_meta_unlock;
+ }
+ }
+
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+ switch (cmd) {
+ case OCFS2_IOC_RESVSP:
+ case OCFS2_IOC_RESVSP64:
+ /*
+ * This takes unsigned offsets, but the signed ones we
+ * pass have been checked against overflow above.
+ */
+ ret = ocfs2_allocate_unwritten_extents(inode, sr->l_start,
+ sr->l_len);
+ break;
+ case OCFS2_IOC_UNRESVSP:
+ case OCFS2_IOC_UNRESVSP64:
+ ret = ocfs2_remove_inode_range(inode, di_bh, sr->l_start,
+ sr->l_len);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_meta_unlock;
+ }
+
+ /*
+ * We update c/mtime for these changes
+ */
+ handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ mlog_errno(ret);
+ goto out_meta_unlock;
+ }
+
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ ocfs2_commit_trans(osb, handle);
+
+out_meta_unlock:
+ brelse(di_bh);
+ ocfs2_meta_unlock(inode, 1);
+out_rw_unlock:
+ ocfs2_rw_unlock(inode, 1);
+
+ mutex_unlock(&inode->i_mutex);
+out:
+ return ret;
+}
+
static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
loff_t *ppos,
size_t count,
@@ -1329,15 +1816,16 @@ ocfs2_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
*basep = base;
}
-static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp,
+static struct page * ocfs2_get_write_source(char **ret_src_buf,
const struct iovec *cur_iov,
size_t iov_offset)
{
int ret;
- char *buf;
+ char *buf = cur_iov->iov_base + iov_offset;
struct page *src_page = NULL;
+ unsigned long off;
- buf = cur_iov->iov_base + iov_offset;
+ off = (unsigned long)(buf) & ~PAGE_CACHE_MASK;
if (!segment_eq(get_fs(), KERNEL_DS)) {
/*
@@ -1349,18 +1837,17 @@ static struct page * ocfs2_get_write_source(struct ocfs2_buffered_write_priv *bp
(unsigned long)buf & PAGE_CACHE_MASK, 1,
0, 0, &src_page, NULL);
if (ret == 1)
- bp->b_src_buf = kmap(src_page);
+ *ret_src_buf = kmap(src_page) + off;
else
src_page = ERR_PTR(-EFAULT);
} else {
- bp->b_src_buf = buf;
+ *ret_src_buf = buf;
}
return src_page;
}
-static void ocfs2_put_write_source(struct ocfs2_buffered_write_priv *bp,
- struct page *page)
+static void ocfs2_put_write_source(struct page *page)
{
if (page) {
kunmap(page);
@@ -1376,10 +1863,13 @@ static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
{
int ret = 0;
ssize_t copied, total = 0;
- size_t iov_offset = 0;
+ size_t iov_offset = 0, bytes;
+ loff_t pos;
const struct iovec *cur_iov = iov;
- struct ocfs2_buffered_write_priv bp;
- struct page *page;
+ struct page *user_page, *page;
+ char * uninitialized_var(buf);
+ char *dst;
+ void *fsdata;
/*
* handle partial DIO write. Adjust cur_iov if needed.
@@ -1387,21 +1877,38 @@ static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
ocfs2_set_next_iovec(&cur_iov, &iov_offset, o_direct_written);
do {
- bp.b_cur_off = iov_offset;
- bp.b_cur_iov = cur_iov;
+ pos = *ppos;
- page = ocfs2_get_write_source(&bp, cur_iov, iov_offset);
- if (IS_ERR(page)) {
- ret = PTR_ERR(page);
+ user_page = ocfs2_get_write_source(&buf, cur_iov, iov_offset);
+ if (IS_ERR(user_page)) {
+ ret = PTR_ERR(user_page);
goto out;
}
- copied = ocfs2_buffered_write_cluster(file, *ppos, count,
- ocfs2_map_and_write_user_data,
- &bp);
+ /* Stay within our page boundaries */
+ bytes = min((PAGE_CACHE_SIZE - ((unsigned long)pos & ~PAGE_CACHE_MASK)),
+ (PAGE_CACHE_SIZE - ((unsigned long)buf & ~PAGE_CACHE_MASK)));
+ /* Stay within the vector boundary */
+ bytes = min_t(size_t, bytes, cur_iov->iov_len - iov_offset);
+ /* Stay within count */
+ bytes = min(bytes, count);
+
+ page = NULL;
+ ret = ocfs2_write_begin(file, file->f_mapping, pos, bytes, 0,
+ &page, &fsdata);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
- ocfs2_put_write_source(&bp, page);
+ dst = kmap_atomic(page, KM_USER0);
+ memcpy(dst + (pos & (PAGE_CACHE_SIZE - 1)), buf, bytes);
+ kunmap_atomic(dst, KM_USER0);
+ flush_dcache_page(page);
+ ocfs2_put_write_source(user_page);
+ copied = ocfs2_write_end(file, file->f_mapping, pos, bytes,
+ bytes, page, fsdata);
if (copied < 0) {
mlog_errno(copied);
ret = copied;
@@ -1409,7 +1916,7 @@ static ssize_t ocfs2_file_buffered_write(struct file *file, loff_t *ppos,
}
total += copied;
- *ppos = *ppos + copied;
+ *ppos = pos + copied;
count -= copied;
ocfs2_set_next_iovec(&cur_iov, &iov_offset, copied);
@@ -1579,52 +2086,46 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
struct pipe_buffer *buf,
struct splice_desc *sd)
{
- int ret, count, total = 0;
+ int ret, count;
ssize_t copied = 0;
- struct ocfs2_splice_write_priv sp;
+ struct file *file = sd->u.file;
+ unsigned int offset;
+ struct page *page = NULL;
+ void *fsdata;
+ char *src, *dst;
ret = buf->ops->confirm(pipe, buf);
if (ret)
goto out;
- sp.s_sd = sd;
- sp.s_buf = buf;
- sp.s_pipe = pipe;
- sp.s_offset = sd->pos & ~PAGE_CACHE_MASK;
- sp.s_buf_offset = buf->offset;
-
+ offset = sd->pos & ~PAGE_CACHE_MASK;
count = sd->len;
- if (count + sp.s_offset > PAGE_CACHE_SIZE)
- count = PAGE_CACHE_SIZE - sp.s_offset;
+ if (count + offset > PAGE_CACHE_SIZE)
+ count = PAGE_CACHE_SIZE - offset;
- do {
- /*
- * splice wants us to copy up to one page at a
- * time. For pagesize > cluster size, this means we
- * might enter ocfs2_buffered_write_cluster() more
- * than once, so keep track of our progress here.
- */
- copied = ocfs2_buffered_write_cluster(sd->u.file,
- (loff_t)sd->pos + total,
- count,
- ocfs2_map_and_write_splice_data,
- &sp);
- if (copied < 0) {
- mlog_errno(copied);
- ret = copied;
- goto out;
- }
+ ret = ocfs2_write_begin(file, file->f_mapping, sd->pos, count, 0,
+ &page, &fsdata);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
- count -= copied;
- sp.s_offset += copied;
- sp.s_buf_offset += copied;
- total += copied;
- } while (count);
+ src = buf->ops->map(pipe, buf, 1);
+ dst = kmap_atomic(page, KM_USER1);
+ memcpy(dst + offset, src + buf->offset, count);
+ kunmap_atomic(page, KM_USER1);
+ buf->ops->unmap(pipe, buf, src);
- ret = 0;
+ copied = ocfs2_write_end(file, file->f_mapping, sd->pos, count, count,
+ page, fsdata);
+ if (copied < 0) {
+ mlog_errno(copied);
+ ret = copied;
+ goto out;
+ }
out:
- return total ? total : ret;
+ return copied ? copied : ret;
}
static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index a4dd1fa1822b..36fe27f268ee 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -39,15 +39,16 @@ enum ocfs2_alloc_restarted {
};
int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
struct inode *inode,
- u32 *cluster_start,
+ u32 *logical_offset,
u32 clusters_to_add,
+ int mark_unwritten,
struct buffer_head *fe_bh,
handle_t *handle,
struct ocfs2_alloc_context *data_ac,
struct ocfs2_alloc_context *meta_ac,
- enum ocfs2_alloc_restarted *reason);
+ enum ocfs2_alloc_restarted *reason_ret);
int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
- u32 clusters_to_add,
+ u32 clusters_to_add, u32 extents_to_split,
struct ocfs2_alloc_context **data_ac,
struct ocfs2_alloc_context **meta_ac);
int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
@@ -61,4 +62,7 @@ int ocfs2_should_update_atime(struct inode *inode,
int ocfs2_update_inode_atime(struct inode *inode,
struct buffer_head *bh);
+int ocfs2_change_file_space(struct file *file, unsigned int cmd,
+ struct ocfs2_space_resv *sr);
+
#endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
index b25ef63781ba..352eb4a13f98 100644
--- a/fs/ocfs2/heartbeat.c
+++ b/fs/ocfs2/heartbeat.c
@@ -157,16 +157,16 @@ int ocfs2_register_hb_callbacks(struct ocfs2_super *osb)
if (ocfs2_mount_local(osb))
return 0;
- status = o2hb_register_callback(&osb->osb_hb_down);
+ status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_down);
if (status < 0) {
mlog_errno(status);
goto bail;
}
- status = o2hb_register_callback(&osb->osb_hb_up);
+ status = o2hb_register_callback(osb->uuid_str, &osb->osb_hb_up);
if (status < 0) {
mlog_errno(status);
- o2hb_unregister_callback(&osb->osb_hb_down);
+ o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
}
bail:
@@ -178,8 +178,8 @@ void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb)
if (ocfs2_mount_local(osb))
return;
- o2hb_unregister_callback(&osb->osb_hb_down);
- o2hb_unregister_callback(&osb->osb_hb_up);
+ o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_down);
+ o2hb_unregister_callback(osb->uuid_str, &osb->osb_hb_up);
}
void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index f3ad21ad9aed..87dcece7e1b5 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -14,6 +14,7 @@
#include "ocfs2.h"
#include "alloc.h"
#include "dlmglue.h"
+#include "file.h"
#include "inode.h"
#include "journal.h"
@@ -62,7 +63,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
goto bail_unlock;
status = -EACCES;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
goto bail_unlock;
if (!S_ISDIR(inode->i_mode))
@@ -115,6 +116,7 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
{
unsigned int flags;
int status;
+ struct ocfs2_space_resv sr;
switch (cmd) {
case OCFS2_IOC_GETFLAGS:
@@ -130,6 +132,14 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
return ocfs2_set_inode_attr(inode, flags,
OCFS2_FL_MODIFIABLE);
+ case OCFS2_IOC_RESVSP:
+ case OCFS2_IOC_RESVSP64:
+ case OCFS2_IOC_UNRESVSP:
+ case OCFS2_IOC_UNRESVSP64:
+ if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
+ return -EFAULT;
+
+ return ocfs2_change_file_space(filp, cmd, &sr);
default:
return -ENOTTY;
}
@@ -148,6 +158,11 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case OCFS2_IOC32_SETFLAGS:
cmd = OCFS2_IOC_SETFLAGS;
break;
+ case OCFS2_IOC_RESVSP:
+ case OCFS2_IOC_RESVSP64:
+ case OCFS2_IOC_UNRESVSP:
+ case OCFS2_IOC_UNRESVSP64:
+ break;
default:
return -ENOIOCTLCMD;
}
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index dc1188081720..dbfb20bb27ea 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -722,8 +722,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
container_of(work, struct ocfs2_journal, j_recovery_work);
struct ocfs2_super *osb = journal->j_osb;
struct ocfs2_dinode *la_dinode, *tl_dinode;
- struct ocfs2_la_recovery_item *item;
- struct list_head *p, *n;
+ struct ocfs2_la_recovery_item *item, *n;
LIST_HEAD(tmp_la_list);
mlog_entry_void();
@@ -734,8 +733,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
spin_unlock(&journal->j_lock);
- list_for_each_safe(p, n, &tmp_la_list) {
- item = list_entry(p, struct ocfs2_la_recovery_item, lri_list);
+ list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) {
list_del_init(&item->lri_list);
mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 3db5de4506da..ce60aab013aa 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -289,6 +289,8 @@ int ocfs2_journal_dirty_data(handle_t *handle,
#define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE \
+ OCFS2_TRUNCATE_LOG_UPDATE)
+#define OCFS2_REMOVE_EXTENT_CREDITS (OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS)
+
/* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
* bitmap block for the new bit) */
#define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index af01158b39f5..d79aa12137d2 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -37,11 +37,29 @@
#include "ocfs2.h"
+#include "aops.h"
#include "dlmglue.h"
#include "file.h"
#include "inode.h"
#include "mmap.h"
+static inline int ocfs2_vm_op_block_sigs(sigset_t *blocked, sigset_t *oldset)
+{
+ /* The best way to deal with signals in the vm path is
+ * to block them upfront, rather than allowing the
+ * locking paths to return -ERESTARTSYS. */
+ sigfillset(blocked);
+
+ /* We should technically never get a bad return value
+ * from sigprocmask */
+ return sigprocmask(SIG_BLOCK, blocked, oldset);
+}
+
+static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
+{
+ return sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
static struct page *ocfs2_nopage(struct vm_area_struct * area,
unsigned long address,
int *type)
@@ -53,14 +71,7 @@ static struct page *ocfs2_nopage(struct vm_area_struct * area,
mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address,
type);
- /* The best way to deal with signals in this path is
- * to block them upfront, rather than allowing the
- * locking paths to return -ERESTARTSYS. */
- sigfillset(&blocked);
-
- /* We should technically never get a bad ret return
- * from sigprocmask */
- ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
+ ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
if (ret < 0) {
mlog_errno(ret);
goto out;
@@ -68,7 +79,7 @@ static struct page *ocfs2_nopage(struct vm_area_struct * area,
page = filemap_nopage(area, address, type);
- ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
+ ret = ocfs2_vm_op_unblock_sigs(&oldset);
if (ret < 0)
mlog_errno(ret);
out:
@@ -76,28 +87,136 @@ out:
return page;
}
-static struct vm_operations_struct ocfs2_file_vm_ops = {
- .nopage = ocfs2_nopage,
-};
+static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
+ struct page *page)
+{
+ int ret;
+ struct address_space *mapping = inode->i_mapping;
+ loff_t pos = page->index << PAGE_CACHE_SHIFT;
+ unsigned int len = PAGE_CACHE_SIZE;
+ pgoff_t last_index;
+ struct page *locked_page = NULL;
+ void *fsdata;
+ loff_t size = i_size_read(inode);
-int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
+ /*
+ * Another node might have truncated while we were waiting on
+ * cluster locks.
+ */
+ last_index = size >> PAGE_CACHE_SHIFT;
+ if (page->index > last_index) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * The i_size check above doesn't catch the case where nodes
+ * truncated and then re-extended the file. We'll re-check the
+ * page mapping after taking the page lock inside of
+ * ocfs2_write_begin_nolock().
+ */
+ if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * Call ocfs2_write_begin() and ocfs2_write_end() to take
+ * advantage of the allocation code there. We pass a write
+ * length of the whole page (chopped to i_size) to make sure
+ * the whole thing is allocated.
+ *
+ * Since we know the page is up to date, we don't have to
+ * worry about ocfs2_write_begin() skipping some buffer reads
+ * because the "write" would invalidate their data.
+ */
+ if (page->index == last_index)
+ len = size & ~PAGE_CACHE_MASK;
+
+ ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
+ &fsdata, di_bh, page);
+ if (ret) {
+ if (ret != -ENOSPC)
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
+ fsdata);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ BUG_ON(ret != len);
+ ret = 0;
+out:
+ return ret;
+}
+
+static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
{
- int ret = 0, lock_level = 0;
- struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+ struct buffer_head *di_bh = NULL;
+ sigset_t blocked, oldset;
+ int ret, ret2;
+
+ ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
+ if (ret < 0) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ /*
+ * The cluster locks taken will block a truncate from another
+ * node. Taking the data lock will also ensure that we don't
+ * attempt page truncation as part of a downconvert.
+ */
+ ret = ocfs2_meta_lock(inode, &di_bh, 1);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
/*
- * Only support shared writeable mmap for local mounts which
- * don't know about holes.
+ * The alloc sem should be enough to serialize with
+ * ocfs2_truncate_file() changing i_size as well as any thread
+ * modifying the inode btree.
*/
- if ((!ocfs2_mount_local(osb) || ocfs2_sparse_alloc(osb)) &&
- ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
- ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
- mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
- /* This is -EINVAL because generic_file_readonly_mmap
- * returns it in a similar situation. */
- return -EINVAL;
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ret = ocfs2_data_lock(inode, 1);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_meta_unlock;
}
+ ret = __ocfs2_page_mkwrite(inode, di_bh, page);
+
+ ocfs2_data_unlock(inode, 1);
+
+out_meta_unlock:
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ brelse(di_bh);
+ ocfs2_meta_unlock(inode, 1);
+
+out:
+ ret2 = ocfs2_vm_op_unblock_sigs(&oldset);
+ if (ret2 < 0)
+ mlog_errno(ret2);
+
+ return ret;
+}
+
+static struct vm_operations_struct ocfs2_file_vm_ops = {
+ .nopage = ocfs2_nopage,
+ .page_mkwrite = ocfs2_page_mkwrite,
+};
+
+int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ int ret = 0, lock_level = 0;
+
ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
file->f_vfsmnt, &lock_level);
if (ret < 0) {
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 36289e6295ce..d430fdab16e9 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1674,7 +1674,7 @@ static int ocfs2_symlink(struct inode *dir,
u32 offset = 0;
inode->i_op = &ocfs2_symlink_inode_operations;
- status = ocfs2_do_extend_allocation(osb, inode, &offset, 1,
+ status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
new_fe_bh,
handle, data_ac, NULL,
NULL);
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index a860633e833f..5cc90a40b3c5 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -219,6 +219,7 @@ struct ocfs2_super
u16 max_slots;
s16 node_num;
s16 slot_num;
+ s16 preferred_slot;
int s_sectsize_bits;
int s_clustersize;
int s_clustersize_bits;
@@ -305,6 +306,19 @@ static inline int ocfs2_sparse_alloc(struct ocfs2_super *osb)
return 0;
}
+static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb)
+{
+ /*
+ * Support for sparse files is a pre-requisite
+ */
+ if (!ocfs2_sparse_alloc(osb))
+ return 0;
+
+ if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
+ return 1;
+ return 0;
+}
+
/* set / clear functions because cluster events can make these happen
* in parallel so we want the transitions to be atomic. this also
* means that any future flags osb_flags must be protected by spinlock
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index f0d9eb08547a..82f8a75b207e 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -88,7 +88,7 @@
#define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB
#define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
| OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
-#define OCFS2_FEATURE_RO_COMPAT_SUPP 0
+#define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
/*
* Heartbeat-only devices are missing journals and other files. The
@@ -116,6 +116,11 @@
*/
#define OCFS2_FEATURE_COMPAT_BACKUP_SB 0x0001
+/*
+ * Unwritten extents support.
+ */
+#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001
+
/* The byte offset of the first backup block will be 1G.
* The following will be 4G, 16G, 64G, 256G and 1T.
*/
@@ -170,6 +175,32 @@
#define OCFS2_IOC32_SETFLAGS _IOW('f', 2, int)
/*
+ * Space reservation / allocation / free ioctls and argument structure
+ * are designed to be compatible with XFS.
+ *
+ * ALLOCSP* and FREESP* are not and will never be supported, but are
+ * included here for completeness.
+ */
+struct ocfs2_space_resv {
+ __s16 l_type;
+ __s16 l_whence;
+ __s64 l_start;
+ __s64 l_len; /* len == 0 means until end of file */
+ __s32 l_sysid;
+ __u32 l_pid;
+ __s32 l_pad[4]; /* reserve area */
+};
+
+#define OCFS2_IOC_ALLOCSP _IOW ('X', 10, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP _IOW ('X', 11, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP _IOW ('X', 40, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP _IOW ('X', 41, struct ocfs2_space_resv)
+#define OCFS2_IOC_ALLOCSP64 _IOW ('X', 36, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP64 _IOW ('X', 37, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP64 _IOW ('X', 42, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP64 _IOW ('X', 43, struct ocfs2_space_resv)
+
+/*
* Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
*/
#define OCFS2_JOURNAL_DIRTY_FL (0x00000001) /* Journal needs recovery */
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index d8b79067dc14..af4882b62cfa 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -121,17 +121,25 @@ static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
return ret;
}
-static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si)
+static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
{
int i;
s16 ret = OCFS2_INVALID_SLOT;
+ if (preferred >= 0 && preferred < si->si_num_slots) {
+ if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
+ ret = preferred;
+ goto out;
+ }
+ }
+
for(i = 0; i < si->si_num_slots; i++) {
if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
ret = (s16) i;
break;
}
}
+out:
return ret;
}
@@ -248,7 +256,7 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
if (slot == OCFS2_INVALID_SLOT) {
/* if no slot yet, then just take 1st available
* one. */
- slot = __ocfs2_find_empty_slot(si);
+ slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
if (slot == OCFS2_INVALID_SLOT) {
spin_unlock(&si->si_lock);
mlog(ML_ERROR, "no free slots available!\n");
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index e3437626d183..d9c5c9fcb30f 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -98,14 +98,6 @@ static int ocfs2_relink_block_group(handle_t *handle,
u16 chain);
static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
u32 wanted);
-static int ocfs2_free_suballoc_bits(handle_t *handle,
- struct inode *alloc_inode,
- struct buffer_head *alloc_bh,
- unsigned int start_bit,
- u64 bg_blkno,
- unsigned int count);
-static inline u64 ocfs2_which_suballoc_group(u64 block,
- unsigned int bit);
static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
u64 bg_blkno,
u16 bg_bit_off);
@@ -496,13 +488,7 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
(*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
(*ac)->ac_which = OCFS2_AC_USE_META;
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
- slot = 0;
-#else
slot = osb->slot_num;
-#endif
-
(*ac)->ac_group_search = ocfs2_block_group_search;
status = ocfs2_reserve_suballoc_bits(osb, (*ac),
@@ -1626,12 +1612,12 @@ bail:
/*
* expects the suballoc inode to already be locked.
*/
-static int ocfs2_free_suballoc_bits(handle_t *handle,
- struct inode *alloc_inode,
- struct buffer_head *alloc_bh,
- unsigned int start_bit,
- u64 bg_blkno,
- unsigned int count)
+int ocfs2_free_suballoc_bits(handle_t *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *alloc_bh,
+ unsigned int start_bit,
+ u64 bg_blkno,
+ unsigned int count)
{
int status = 0;
u32 tmp_used;
@@ -1703,13 +1689,6 @@ bail:
return status;
}
-static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
-{
- u64 group = block - (u64) bit;
-
- return group;
-}
-
int ocfs2_free_dinode(handle_t *handle,
struct inode *inode_alloc_inode,
struct buffer_head *inode_alloc_bh,
@@ -1723,19 +1702,6 @@ int ocfs2_free_dinode(handle_t *handle,
inode_alloc_bh, bit, bg_blkno, 1);
}
-int ocfs2_free_extent_block(handle_t *handle,
- struct inode *eb_alloc_inode,
- struct buffer_head *eb_alloc_bh,
- struct ocfs2_extent_block *eb)
-{
- u64 blk = le64_to_cpu(eb->h_blkno);
- u16 bit = le16_to_cpu(eb->h_suballoc_bit);
- u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
-
- return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
- bit, bg_blkno, 1);
-}
-
int ocfs2_free_clusters(handle_t *handle,
struct inode *bitmap_inode,
struct buffer_head *bitmap_bh,
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index 1a3c94cb9250..f212dc01a84b 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -86,20 +86,29 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
u32 *cluster_start,
u32 *num_clusters);
+int ocfs2_free_suballoc_bits(handle_t *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *alloc_bh,
+ unsigned int start_bit,
+ u64 bg_blkno,
+ unsigned int count);
int ocfs2_free_dinode(handle_t *handle,
struct inode *inode_alloc_inode,
struct buffer_head *inode_alloc_bh,
struct ocfs2_dinode *di);
-int ocfs2_free_extent_block(handle_t *handle,
- struct inode *eb_alloc_inode,
- struct buffer_head *eb_alloc_bh,
- struct ocfs2_extent_block *eb);
int ocfs2_free_clusters(handle_t *handle,
struct inode *bitmap_inode,
struct buffer_head *bitmap_bh,
u64 start_blk,
unsigned int num_clusters);
+static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
+{
+ u64 group = block - (u64) bit;
+
+ return group;
+}
+
static inline u32 ocfs2_cluster_from_desc(struct ocfs2_super *osb,
u64 bg_blkno)
{
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 86b559c7dce9..3a5a1ed09ac9 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -82,7 +82,8 @@ MODULE_AUTHOR("Oracle");
MODULE_LICENSE("GPL");
static int ocfs2_parse_options(struct super_block *sb, char *options,
- unsigned long *mount_opt, int is_remount);
+ unsigned long *mount_opt, s16 *slot,
+ int is_remount);
static void ocfs2_put_super(struct super_block *sb);
static int ocfs2_mount_volume(struct super_block *sb);
static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
@@ -114,8 +115,6 @@ static void ocfs2_write_super(struct super_block *sb);
static struct inode *ocfs2_alloc_inode(struct super_block *sb);
static void ocfs2_destroy_inode(struct inode *inode);
-static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
-
static const struct super_operations ocfs2_sops = {
.statfs = ocfs2_statfs,
.alloc_inode = ocfs2_alloc_inode,
@@ -140,6 +139,7 @@ enum {
Opt_data_ordered,
Opt_data_writeback,
Opt_atime_quantum,
+ Opt_slot,
Opt_err,
};
@@ -154,6 +154,7 @@ static match_table_t tokens = {
{Opt_data_ordered, "data=ordered"},
{Opt_data_writeback, "data=writeback"},
{Opt_atime_quantum, "atime_quantum=%u"},
+ {Opt_slot, "preferred_slot=%u"},
{Opt_err, NULL}
};
@@ -318,7 +319,7 @@ static void ocfs2_destroy_inode(struct inode *inode)
/* From xfs_super.c:xfs_max_file_offset
* Copyright (c) 2000-2004 Silicon Graphics, Inc.
*/
-static unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
+unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
{
unsigned int pagefactor = 1;
unsigned int bitshift = BITS_PER_LONG - 1;
@@ -355,9 +356,10 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
int incompat_features;
int ret = 0;
unsigned long parsed_options;
+ s16 slot;
struct ocfs2_super *osb = OCFS2_SB(sb);
- if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
+ if (!ocfs2_parse_options(sb, data, &parsed_options, &slot, 1)) {
ret = -EINVAL;
goto out;
}
@@ -534,6 +536,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
struct dentry *root;
int status, sector_size;
unsigned long parsed_opt;
+ s16 slot;
struct inode *inode = NULL;
struct ocfs2_super *osb = NULL;
struct buffer_head *bh = NULL;
@@ -541,7 +544,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
mlog_entry("%p, %p, %i", sb, data, silent);
- if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
+ if (!ocfs2_parse_options(sb, data, &parsed_opt, &slot, 0)) {
status = -EINVAL;
goto read_super_error;
}
@@ -571,6 +574,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
brelse(bh);
bh = NULL;
osb->s_mount_opt = parsed_opt;
+ osb->preferred_slot = slot;
sb->s_magic = OCFS2_SUPER_MAGIC;
@@ -713,6 +717,7 @@ static struct file_system_type ocfs2_fs_type = {
static int ocfs2_parse_options(struct super_block *sb,
char *options,
unsigned long *mount_opt,
+ s16 *slot,
int is_remount)
{
int status;
@@ -722,6 +727,7 @@ static int ocfs2_parse_options(struct super_block *sb,
options ? options : "(none)");
*mount_opt = 0;
+ *slot = OCFS2_INVALID_SLOT;
if (!options) {
status = 1;
@@ -782,6 +788,15 @@ static int ocfs2_parse_options(struct super_block *sb,
else
osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
break;
+ case Opt_slot:
+ option = 0;
+ if (match_int(&args[0], &option)) {
+ status = 0;
+ goto bail;
+ }
+ if (option)
+ *slot = (s16)option;
+ break;
default:
mlog(ML_ERROR,
"Unrecognized mount option \"%s\" "
diff --git a/fs/ocfs2/super.h b/fs/ocfs2/super.h
index 783f5270f2a1..3b9cb3d0b008 100644
--- a/fs/ocfs2/super.h
+++ b/fs/ocfs2/super.h
@@ -45,4 +45,6 @@ void __ocfs2_abort(struct super_block *sb,
#define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
+unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+
#endif /* OCFS2_SUPER_H */
diff --git a/fs/open.c b/fs/open.c
index 0d515d161974..be6a457f4226 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -855,7 +855,7 @@ EXPORT_SYMBOL(dentry_open);
/*
* Find an empty file descriptor entry, and mark it busy.
*/
-int get_unused_fd(void)
+int get_unused_fd_flags(int flags)
{
struct files_struct * files = current->files;
int fd, error;
@@ -891,7 +891,10 @@ repeat:
}
FD_SET(fd, fdt->open_fds);
- FD_CLR(fd, fdt->close_on_exec);
+ if (flags & O_CLOEXEC)
+ FD_SET(fd, fdt->close_on_exec);
+ else
+ FD_CLR(fd, fdt->close_on_exec);
files->next_fd = fd + 1;
#if 1
/* Sanity check */
@@ -907,6 +910,11 @@ out:
return error;
}
+int get_unused_fd(void)
+{
+ return get_unused_fd_flags(0);
+}
+
EXPORT_SYMBOL(get_unused_fd);
static void __put_unused_fd(struct files_struct *files, unsigned int fd)
@@ -959,7 +967,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
int fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
- fd = get_unused_fd();
+ fd = get_unused_fd_flags(flags);
if (fd >= 0) {
struct file *f = do_filp_open(dfd, tmp, flags, mode);
if (IS_ERR(f)) {
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c
index e3491328596b..3d3e16631472 100644
--- a/fs/partitions/acorn.c
+++ b/fs/partitions/acorn.c
@@ -25,6 +25,8 @@
#define PARTITION_RISCIX_SCSI 2
#define PARTITION_LINUX 9
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+ defined(CONFIG_ACORN_PARTITION_ADFS)
static struct adfs_discrecord *
adfs_partition(struct parsed_partitions *state, char *name, char *data,
unsigned long first_sector, int slot)
@@ -48,6 +50,7 @@ adfs_partition(struct parsed_partitions *state, char *name, char *data,
put_partition(state, slot, first_sector, nr_sects);
return dr;
}
+#endif
#ifdef CONFIG_ACORN_PARTITION_RISCIX
@@ -65,6 +68,8 @@ struct riscix_record {
struct riscix_part part[8];
};
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+ defined(CONFIG_ACORN_PARTITION_ADFS)
static int
riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
unsigned long first_sect, int slot, unsigned long nr_sects)
@@ -105,6 +110,7 @@ riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
return slot;
}
#endif
+#endif
#define LINUX_NATIVE_MAGIC 0xdeafa1de
#define LINUX_SWAP_MAGIC 0xdeafab1e
@@ -115,6 +121,8 @@ struct linux_part {
__le32 nr_sects;
};
+#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
+ defined(CONFIG_ACORN_PARTITION_ADFS)
static int
linux_partition(struct parsed_partitions *state, struct block_device *bdev,
unsigned long first_sect, int slot, unsigned long nr_sects)
@@ -146,6 +154,7 @@ linux_partition(struct parsed_partitions *state, struct block_device *bdev,
put_dev_sector(sect);
return slot;
}
+#endif
#ifdef CONFIG_ACORN_PARTITION_CUMANA
int
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index 99873a2b4cbc..e7dd1d4e3473 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -677,15 +677,24 @@ static bool ldm_create_data_partitions (struct parsed_partitions *pp,
* Return: -1 Error, the calculated offset exceeded the size of the buffer
* n OK, a range-checked offset into buffer
*/
-static int ldm_relative (const u8 *buffer, int buflen, int base, int offset)
+static int ldm_relative(const u8 *buffer, int buflen, int base, int offset)
{
base += offset;
- if ((!buffer) || (offset < 0) || (base > buflen))
+ if (!buffer || offset < 0 || base > buflen) {
+ if (!buffer)
+ ldm_error("!buffer");
+ if (offset < 0)
+ ldm_error("offset (%d) < 0", offset);
+ if (base > buflen)
+ ldm_error("base (%d) > buflen (%d)", base, buflen);
return -1;
- if ((base + buffer[base]) >= buflen)
+ }
+ if (base + buffer[base] >= buflen) {
+ ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base,
+ buffer[base], buflen);
return -1;
-
+ }
return buffer[base] + offset + 1;
}
@@ -1054,60 +1063,98 @@ static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb)
* Return: 'true' @vb contains a Volume VBLK
* 'false' @vb contents are not defined
*/
-static bool ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb)
{
- int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2;
- int r_drive, len;
+ int r_objid, r_name, r_vtype, r_disable_drive_letter, r_child, r_size;
+ int r_id1, r_id2, r_size2, r_drive, len;
struct vblk_volu *volu;
- BUG_ON (!buffer || !vb);
-
- r_objid = ldm_relative (buffer, buflen, 0x18, 0);
- r_name = ldm_relative (buffer, buflen, 0x18, r_objid);
- r_vtype = ldm_relative (buffer, buflen, 0x18, r_name);
- r_child = ldm_relative (buffer, buflen, 0x2E, r_vtype);
- r_size = ldm_relative (buffer, buflen, 0x3E, r_child);
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_ID1)
- r_id1 = ldm_relative (buffer, buflen, 0x53, r_size);
- else
+ BUG_ON(!buffer || !vb);
+ r_objid = ldm_relative(buffer, buflen, 0x18, 0);
+ if (r_objid < 0) {
+ ldm_error("r_objid %d < 0", r_objid);
+ return false;
+ }
+ r_name = ldm_relative(buffer, buflen, 0x18, r_objid);
+ if (r_name < 0) {
+ ldm_error("r_name %d < 0", r_name);
+ return false;
+ }
+ r_vtype = ldm_relative(buffer, buflen, 0x18, r_name);
+ if (r_vtype < 0) {
+ ldm_error("r_vtype %d < 0", r_vtype);
+ return false;
+ }
+ r_disable_drive_letter = ldm_relative(buffer, buflen, 0x18, r_vtype);
+ if (r_disable_drive_letter < 0) {
+ ldm_error("r_disable_drive_letter %d < 0",
+ r_disable_drive_letter);
+ return false;
+ }
+ r_child = ldm_relative(buffer, buflen, 0x2D, r_disable_drive_letter);
+ if (r_child < 0) {
+ ldm_error("r_child %d < 0", r_child);
+ return false;
+ }
+ r_size = ldm_relative(buffer, buflen, 0x3D, r_child);
+ if (r_size < 0) {
+ ldm_error("r_size %d < 0", r_size);
+ return false;
+ }
+ if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) {
+ r_id1 = ldm_relative(buffer, buflen, 0x52, r_size);
+ if (r_id1 < 0) {
+ ldm_error("r_id1 %d < 0", r_id1);
+ return false;
+ }
+ } else
r_id1 = r_size;
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_ID2)
- r_id2 = ldm_relative (buffer, buflen, 0x53, r_id1);
- else
+ if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) {
+ r_id2 = ldm_relative(buffer, buflen, 0x52, r_id1);
+ if (r_id2 < 0) {
+ ldm_error("r_id2 %d < 0", r_id2);
+ return false;
+ }
+ } else
r_id2 = r_id1;
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE)
- r_size2 = ldm_relative (buffer, buflen, 0x53, r_id2);
- else
+ if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) {
+ r_size2 = ldm_relative(buffer, buflen, 0x52, r_id2);
+ if (r_size2 < 0) {
+ ldm_error("r_size2 %d < 0", r_size2);
+ return false;
+ }
+ } else
r_size2 = r_id2;
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE)
- r_drive = ldm_relative (buffer, buflen, 0x53, r_size2);
- else
+ if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
+ r_drive = ldm_relative(buffer, buflen, 0x52, r_size2);
+ if (r_drive < 0) {
+ ldm_error("r_drive %d < 0", r_drive);
+ return false;
+ }
+ } else
r_drive = r_size2;
-
len = r_drive;
- if (len < 0)
+ if (len < 0) {
+ ldm_error("len %d < 0", len);
return false;
-
+ }
len += VBLK_SIZE_VOL5;
- if (len != BE32 (buffer + 0x14))
+ if (len > BE32(buffer + 0x14)) {
+ ldm_error("len %d > BE32(buffer + 0x14) %d", len,
+ BE32(buffer + 0x14));
return false;
-
+ }
volu = &vb->vblk.volu;
-
- ldm_get_vstr (buffer + 0x18 + r_name, volu->volume_type,
- sizeof (volu->volume_type));
- memcpy (volu->volume_state, buffer + 0x19 + r_vtype,
- sizeof (volu->volume_state));
- volu->size = ldm_get_vnum (buffer + 0x3E + r_child);
- volu->partition_type = buffer[0x42 + r_size];
- memcpy (volu->guid, buffer + 0x43 + r_size, sizeof (volu->guid));
+ ldm_get_vstr(buffer + 0x18 + r_name, volu->volume_type,
+ sizeof(volu->volume_type));
+ memcpy(volu->volume_state, buffer + 0x18 + r_disable_drive_letter,
+ sizeof(volu->volume_state));
+ volu->size = ldm_get_vnum(buffer + 0x3D + r_child);
+ volu->partition_type = buffer[0x41 + r_size];
+ memcpy(volu->guid, buffer + 0x42 + r_size, sizeof(volu->guid));
if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
- ldm_get_vstr (buffer + 0x53 + r_size, volu->drive_hint,
- sizeof (volu->drive_hint));
+ ldm_get_vstr(buffer + 0x52 + r_size, volu->drive_hint,
+ sizeof(volu->drive_hint));
}
return true;
}
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h
index d2e6a3046939..80f63b5fdd9f 100644
--- a/fs/partitions/ldm.h
+++ b/fs/partitions/ldm.h
@@ -68,7 +68,7 @@ struct parsed_partitions;
#define VBLK_SIZE_DSK3 12
#define VBLK_SIZE_DSK4 45
#define VBLK_SIZE_PRT3 28
-#define VBLK_SIZE_VOL5 59
+#define VBLK_SIZE_VOL5 58
/* component types */
#define COMP_STRIPE 0x01 /* Stripe-set */
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 98e78e2f18d6..965625a0977d 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -62,6 +62,8 @@
#include <linux/mman.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
@@ -76,9 +78,7 @@
#include <linux/rcupdate.h>
#include <linux/delayacct.h>
-#include <asm/uaccess.h>
#include <asm/pgtable.h>
-#include <asm/io.h>
#include <asm/processor.h>
#include "internal.h"
@@ -87,10 +87,10 @@
do { memcpy(buffer, string, strlen(string)); \
buffer += strlen(string); } while (0)
-static inline char * task_name(struct task_struct *p, char * buf)
+static inline char *task_name(struct task_struct *p, char *buf)
{
int i;
- char * name;
+ char *name;
char tcomm[sizeof(p->comm)];
get_task_comm(tcomm, p);
@@ -138,7 +138,7 @@ static const char *task_state_array[] = {
"X (dead)" /* 32 */
};
-static inline const char * get_task_state(struct task_struct *tsk)
+static inline const char *get_task_state(struct task_struct *tsk)
{
unsigned int state = (tsk->state & (TASK_RUNNING |
TASK_INTERRUPTIBLE |
@@ -156,7 +156,7 @@ static inline const char * get_task_state(struct task_struct *tsk)
return *p;
}
-static inline char * task_state(struct task_struct *p, char *buffer)
+static inline char *task_state(struct task_struct *p, char *buffer)
{
struct group_info *group_info;
int g;
@@ -172,8 +172,8 @@ static inline char * task_state(struct task_struct *p, char *buffer)
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
get_task_state(p),
- p->tgid, p->pid,
- pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
+ p->tgid, p->pid,
+ pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
p->uid, p->euid, p->suid, p->fsuid,
p->gid, p->egid, p->sgid, p->fsgid);
@@ -191,15 +191,15 @@ static inline char * task_state(struct task_struct *p, char *buffer)
get_group_info(group_info);
task_unlock(p);
- for (g = 0; g < min(group_info->ngroups,NGROUPS_SMALL); g++)
- buffer += sprintf(buffer, "%d ", GROUP_AT(group_info,g));
+ for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
+ buffer += sprintf(buffer, "%d ", GROUP_AT(group_info, g));
put_group_info(group_info);
buffer += sprintf(buffer, "\n");
return buffer;
}
-static char * render_sigset_t(const char *header, sigset_t *set, char *buffer)
+static char *render_sigset_t(const char *header, sigset_t *set, char *buffer)
{
int i, len;
@@ -239,7 +239,7 @@ static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
}
}
-static inline char * task_sig(struct task_struct *p, char *buffer)
+static inline char *task_sig(struct task_struct *p, char *buffer)
{
unsigned long flags;
sigset_t pending, shpending, blocked, ignored, caught;
@@ -289,14 +289,23 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
cap_t(p->cap_effective));
}
-int proc_pid_status(struct task_struct *task, char * buffer)
+static inline char *task_context_switch_counts(struct task_struct *p,
+ char *buffer)
{
- char * orig = buffer;
+ return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n"
+ "nonvoluntary_ctxt_switches:\t%lu\n",
+ p->nvcsw,
+ p->nivcsw);
+}
+
+int proc_pid_status(struct task_struct *task, char *buffer)
+{
+ char *orig = buffer;
struct mm_struct *mm = get_task_mm(task);
buffer = task_name(task, buffer);
buffer = task_state(task, buffer);
-
+
if (mm) {
buffer = task_mem(mm, buffer);
mmput(mm);
@@ -307,6 +316,7 @@ int proc_pid_status(struct task_struct *task, char * buffer)
#if defined(CONFIG_S390)
buffer = task_show_regs(task, buffer);
#endif
+ buffer = task_context_switch_counts(task, buffer);
return buffer - orig;
}
@@ -332,7 +342,7 @@ static clock_t task_utime(struct task_struct *p)
static clock_t task_stime(struct task_struct *p)
{
- clock_t stime = cputime_to_clock_t(p->stime);
+ clock_t stime;
/*
* Use CFS's precise accounting. (we subtract utime from
@@ -344,8 +354,7 @@ static clock_t task_stime(struct task_struct *p)
return stime;
}
-
-static int do_task_stat(struct task_struct *task, char * buffer, int whole)
+static int do_task_stat(struct task_struct *task, char *buffer, int whole)
{
unsigned long vsize, eip, esp, wchan = ~0UL;
long priority, nice;
@@ -353,7 +362,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
sigset_t sigign, sigcatch;
char state;
int res;
- pid_t ppid = 0, pgid = -1, sid = -1;
+ pid_t ppid = 0, pgid = -1, sid = -1;
int num_threads = 0;
struct mm_struct *mm;
unsigned long long start_time;
@@ -424,7 +433,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
}
rcu_read_unlock();
- if (!whole || num_threads<2)
+ if (!whole || num_threads < 2)
wchan = get_wchan(task);
if (!whole) {
min_flt = task->min_flt;
@@ -440,12 +449,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
/* Temporary variable needed for gcc-2.96 */
/* convert timespec -> nsec*/
- start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC
- + task->start_time.tv_nsec;
+ start_time =
+ (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
+ + task->real_start_time.tv_nsec;
/* convert nsec -> ticks */
start_time = nsec_to_clock_t(start_time);
- res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %lu \
+ res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n",
task->pid,
@@ -471,7 +481,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
start_time,
vsize,
mm ? get_mm_rss(mm) : 0,
- rsslim,
+ rsslim,
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
mm ? mm->start_stack : 0,
@@ -493,17 +503,17 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
task->rt_priority,
task->policy,
(unsigned long long)delayacct_blkio_ticks(task));
- if(mm)
+ if (mm)
mmput(mm);
return res;
}
-int proc_tid_stat(struct task_struct *task, char * buffer)
+int proc_tid_stat(struct task_struct *task, char *buffer)
{
return do_task_stat(task, buffer, 0);
}
-int proc_tgid_stat(struct task_struct *task, char * buffer)
+int proc_tgid_stat(struct task_struct *task, char *buffer)
{
return do_task_stat(task, buffer, 1);
}
@@ -512,12 +522,12 @@ int proc_pid_statm(struct task_struct *task, char *buffer)
{
int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
struct mm_struct *mm = get_task_mm(task);
-
+
if (mm) {
size = task_statm(mm, &shared, &text, &data, &resident);
mmput(mm);
}
- return sprintf(buffer,"%d %d %d %d %d %d %d\n",
+ return sprintf(buffer, "%d %d %d %d %d %d %d\n",
size, resident, shared, text, lib, data, 0);
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 46ea5d56e1bb..42cb4f5613b6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -67,7 +67,6 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ptrace.h>
-#include <linux/seccomp.h>
#include <linux/cpuset.h>
#include <linux/audit.h>
#include <linux/poll.h>
@@ -204,12 +203,17 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
int res = 0;
struct mm_struct *mm = get_task_mm(task);
if (mm) {
- unsigned int len = mm->env_end - mm->env_start;
+ unsigned int len;
+
+ res = -ESRCH;
+ if (!ptrace_may_attach(task))
+ goto out;
+
+ len = mm->env_end - mm->env_start;
if (len > PAGE_SIZE)
len = PAGE_SIZE;
res = access_process_vm(task, mm->env_start, buffer, len, 0);
- if (!ptrace_may_attach(task))
- res = -ESRCH;
+out:
mmput(mm);
}
return res;
@@ -279,7 +283,7 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer)
static int proc_pid_wchan(struct task_struct *task, char *buffer)
{
unsigned long wchan;
- char symname[KSYM_NAME_LEN+1];
+ char symname[KSYM_NAME_LEN];
wchan = get_wchan(task);
@@ -812,71 +816,6 @@ static const struct file_operations proc_loginuid_operations = {
};
#endif
-#ifdef CONFIG_SECCOMP
-static ssize_t seccomp_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
- char __buf[20];
- size_t len;
-
- if (!tsk)
- return -ESRCH;
- /* no need to print the trailing zero, so use only len */
- len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
- put_task_struct(tsk);
-
- return simple_read_from_buffer(buf, count, ppos, __buf, len);
-}
-
-static ssize_t seccomp_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
- char __buf[20], *end;
- unsigned int seccomp_mode;
- ssize_t result;
-
- result = -ESRCH;
- if (!tsk)
- goto out_no_task;
-
- /* can set it only once to be even more secure */
- result = -EPERM;
- if (unlikely(tsk->seccomp.mode))
- goto out;
-
- result = -EFAULT;
- memset(__buf, 0, sizeof(__buf));
- count = min(count, sizeof(__buf) - 1);
- if (copy_from_user(__buf, buf, count))
- goto out;
-
- seccomp_mode = simple_strtoul(__buf, &end, 0);
- if (*end == '\n')
- end++;
- result = -EINVAL;
- if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
- tsk->seccomp.mode = seccomp_mode;
- set_tsk_thread_flag(tsk, TIF_SECCOMP);
- } else
- goto out;
- result = -EIO;
- if (unlikely(!(end - __buf)))
- goto out;
- result = end - __buf;
-out:
- put_task_struct(tsk);
-out_no_task:
- return result;
-}
-
-static const struct file_operations proc_seccomp_operations = {
- .read = seccomp_read,
- .write = seccomp_write,
-};
-#endif /* CONFIG_SECCOMP */
-
#ifdef CONFIG_FAULT_INJECTION
static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
@@ -2037,9 +1976,6 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("numa_maps", S_IRUGO, numa_maps),
#endif
REG("mem", S_IRUSR|S_IWUSR, mem),
-#ifdef CONFIG_SECCOMP
- REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
-#endif
LNK("cwd", cwd),
LNK("root", root),
LNK("exe", exe),
@@ -2324,9 +2260,6 @@ static const struct pid_entry tid_base_stuff[] = {
REG("numa_maps", S_IRUGO, numa_maps),
#endif
REG("mem", S_IRUSR|S_IWUSR, mem),
-#ifdef CONFIG_SECCOMP
- REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
-#endif
LNK("cwd", cwd),
LNK("root", root),
LNK("exe", exe),
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a40e15f5ecb..b5e7155d30d8 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -20,6 +20,7 @@
#include <linux/namei.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
+#include <linux/completion.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -529,12 +530,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
return -EAGAIN;
dp->low_ino = i;
- spin_lock(&proc_subdir_lock);
- dp->next = dir->subdir;
- dp->parent = dir;
- dir->subdir = dp;
- spin_unlock(&proc_subdir_lock);
-
if (S_ISDIR(dp->mode)) {
if (dp->proc_iops == NULL) {
dp->proc_fops = &proc_dir_operations;
@@ -550,6 +545,13 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
if (dp->proc_iops == NULL)
dp->proc_iops = &proc_file_inode_operations;
}
+
+ spin_lock(&proc_subdir_lock);
+ dp->next = dir->subdir;
+ dp->parent = dir;
+ dir->subdir = dp;
+ spin_unlock(&proc_subdir_lock);
+
return 0;
}
@@ -613,6 +615,9 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
ent->namelen = len;
ent->mode = mode;
ent->nlink = nlink;
+ ent->pde_users = 0;
+ spin_lock_init(&ent->pde_unload_lock);
+ ent->pde_unload_completion = NULL;
out:
return ent;
}
@@ -649,9 +654,6 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
ent = proc_create(&parent, name, S_IFDIR | mode, 2);
if (ent) {
- ent->proc_fops = &proc_dir_operations;
- ent->proc_iops = &proc_dir_inode_operations;
-
if (proc_register(parent, ent) < 0) {
kfree(ent);
ent = NULL;
@@ -686,10 +688,6 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
ent = proc_create(&parent,name,mode,nlink);
if (ent) {
- if (S_ISDIR(mode)) {
- ent->proc_fops = &proc_dir_operations;
- ent->proc_iops = &proc_dir_inode_operations;
- }
if (proc_register(parent, ent) < 0) {
kfree(ent);
ent = NULL;
@@ -734,9 +732,35 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
de = *p;
*p = de->next;
de->next = NULL;
+
+ spin_lock(&de->pde_unload_lock);
+ /*
+ * Stop accepting new callers into module. If you're
+ * dynamically allocating ->proc_fops, save a pointer somewhere.
+ */
+ de->proc_fops = NULL;
+ /* Wait until all existing callers into module are done. */
+ if (de->pde_users > 0) {
+ DECLARE_COMPLETION_ONSTACK(c);
+
+ if (!de->pde_unload_completion)
+ de->pde_unload_completion = &c;
+
+ spin_unlock(&de->pde_unload_lock);
+ spin_unlock(&proc_subdir_lock);
+
+ wait_for_completion(de->pde_unload_completion);
+
+ spin_lock(&proc_subdir_lock);
+ goto continue_removing;
+ }
+ spin_unlock(&de->pde_unload_lock);
+
+continue_removing:
if (S_ISDIR(de->mode))
parent->nlink--;
- proc_kill_inodes(de);
+ if (!S_ISREG(de->mode))
+ proc_kill_inodes(de);
de->nlink = 0;
WARN_ON(de->subdir);
if (!atomic_read(&de->count))
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d5ce65c68d7b..dd28e86ab422 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
+#include <linux/completion.h>
#include <linux/file.h>
#include <linux/limits.h>
#include <linux/init.h>
@@ -140,6 +141,251 @@ static const struct super_operations proc_sops = {
.remount_fs = proc_remount,
};
+static void pde_users_dec(struct proc_dir_entry *pde)
+{
+ spin_lock(&pde->pde_unload_lock);
+ pde->pde_users--;
+ if (pde->pde_unload_completion && pde->pde_users == 0)
+ complete(pde->pde_unload_completion);
+ spin_unlock(&pde->pde_unload_lock);
+}
+
+static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ loff_t rv = -EINVAL;
+ loff_t (*llseek)(struct file *, loff_t, int);
+
+ spin_lock(&pde->pde_unload_lock);
+ /*
+ * remove_proc_entry() is going to delete PDE (as part of module
+ * cleanup sequence). No new callers into module allowed.
+ */
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ /*
+ * Bump refcount so that remove_proc_entry will wail for ->llseek to
+ * complete.
+ */
+ pde->pde_users++;
+ /*
+ * Save function pointer under lock, to protect against ->proc_fops
+ * NULL'ifying right after ->pde_unload_lock is dropped.
+ */
+ llseek = pde->proc_fops->llseek;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (!llseek)
+ llseek = default_llseek;
+ rv = llseek(file, offset, whence);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ ssize_t rv = -EIO;
+ ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ read = pde->proc_fops->read;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (read)
+ rv = read(file, buf, count, ppos);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ ssize_t rv = -EIO;
+ ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ write = pde->proc_fops->write;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (write)
+ rv = write(file, buf, count, ppos);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ unsigned int rv = 0;
+ unsigned int (*poll)(struct file *, struct poll_table_struct *);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ poll = pde->proc_fops->poll;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (poll)
+ rv = poll(file, pts);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ long rv = -ENOTTY;
+ long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
+ int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
+ ioctl = pde->proc_fops->ioctl;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (unlocked_ioctl) {
+ rv = unlocked_ioctl(file, cmd, arg);
+ if (rv == -ENOIOCTLCMD)
+ rv = -EINVAL;
+ } else if (ioctl) {
+ lock_kernel();
+ rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
+ unlock_kernel();
+ }
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+#ifdef CONFIG_COMPAT
+static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ long rv = -ENOTTY;
+ long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ compat_ioctl = pde->proc_fops->compat_ioctl;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (compat_ioctl)
+ rv = compat_ioctl(file, cmd, arg);
+
+ pde_users_dec(pde);
+ return rv;
+}
+#endif
+
+static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ int rv = -EIO;
+ int (*mmap)(struct file *, struct vm_area_struct *);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ mmap = pde->proc_fops->mmap;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (mmap)
+ rv = mmap(file, vma);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static int proc_reg_open(struct inode *inode, struct file *file)
+{
+ struct proc_dir_entry *pde = PDE(inode);
+ int rv = 0;
+ int (*open)(struct inode *, struct file *);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ open = pde->proc_fops->open;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (open)
+ rv = open(inode, file);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static int proc_reg_release(struct inode *inode, struct file *file)
+{
+ struct proc_dir_entry *pde = PDE(inode);
+ int rv = 0;
+ int (*release)(struct inode *, struct file *);
+
+ spin_lock(&pde->pde_unload_lock);
+ if (!pde->proc_fops) {
+ spin_unlock(&pde->pde_unload_lock);
+ return rv;
+ }
+ pde->pde_users++;
+ release = pde->proc_fops->release;
+ spin_unlock(&pde->pde_unload_lock);
+
+ if (release)
+ rv = release(inode, file);
+
+ pde_users_dec(pde);
+ return rv;
+}
+
+static const struct file_operations proc_reg_file_ops = {
+ .llseek = proc_reg_llseek,
+ .read = proc_reg_read,
+ .write = proc_reg_write,
+ .poll = proc_reg_poll,
+ .unlocked_ioctl = proc_reg_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = proc_reg_compat_ioctl,
+#endif
+ .mmap = proc_reg_mmap,
+ .open = proc_reg_open,
+ .release = proc_reg_release,
+};
+
struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
struct proc_dir_entry *de)
{
@@ -166,8 +412,12 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
inode->i_nlink = de->nlink;
if (de->proc_iops)
inode->i_op = de->proc_iops;
- if (de->proc_fops)
- inode->i_fop = de->proc_fops;
+ if (de->proc_fops) {
+ if (S_ISREG(inode->i_mode))
+ inode->i_fop = &proc_reg_file_ops;
+ else
+ inode->i_fop = de->proc_fops;
+ }
}
return inode;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 5fd49e47f83a..d24b8d46059a 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -105,6 +105,7 @@ static int uptime_read_proc(char *page, char **start, off_t off,
cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
do_posix_clock_monotonic_gettime(&uptime);
+ monotonic_to_bootbased(&uptime);
cputime_to_timespec(idletime, &idle);
len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime.tv_sec,
@@ -443,12 +444,12 @@ static int show_stat(struct seq_file *p, void *v)
unsigned long jif;
cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
u64 sum = 0;
+ struct timespec boottime;
user = nice = system = idle = iowait =
irq = softirq = steal = cputime64_zero;
- jif = - wall_to_monotonic.tv_sec;
- if (wall_to_monotonic.tv_nsec)
- --jif;
+ getboottime(&boottime);
+ jif = boottime.tv_sec;
for_each_possible_cpu(i) {
int j;
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index b3a473b0a191..22846225acfa 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -69,7 +69,7 @@ static void show_tty_range(struct seq_file *m, struct tty_driver *p,
static int show_tty_driver(struct seq_file *m, void *v)
{
- struct tty_driver *p = v;
+ struct tty_driver *p = list_entry(v, struct tty_driver, tty_drivers);
dev_t from = MKDEV(p->major, p->minor_start);
dev_t to = from + p->num;
@@ -106,22 +106,13 @@ static int show_tty_driver(struct seq_file *m, void *v)
/* iterator */
static void *t_start(struct seq_file *m, loff_t *pos)
{
- struct list_head *p;
- loff_t l = *pos;
-
mutex_lock(&tty_mutex);
- list_for_each(p, &tty_drivers)
- if (!l--)
- return list_entry(p, struct tty_driver, tty_drivers);
- return NULL;
+ return seq_list_start(&tty_drivers, *pos);
}
static void *t_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct list_head *p = ((struct tty_driver *)v)->tty_drivers.next;
- (*pos)++;
- return p==&tty_drivers ? NULL :
- list_entry(p, struct tty_driver, tty_drivers);
+ return seq_list_next(v, &tty_drivers, pos);
}
static void t_stop(struct seq_file *m, void *v)
diff --git a/fs/quota.c b/fs/quota.c
index 9f237d6182c9..e6577ac15a6c 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -10,12 +10,14 @@
#include <linux/slab.h>
#include <asm/current.h>
#include <asm/uaccess.h>
+#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/buffer_head.h>
#include <linux/capability.h>
#include <linux/quotaops.h>
+#include <linux/types.h>
/* Check validity of generic quotactl commands */
static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -384,3 +386,119 @@ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t
return ret;
}
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+ compat_u64 dqb_bhardlimit;
+ compat_u64 dqb_bsoftlimit;
+ compat_u64 dqb_curspace;
+ compat_u64 dqb_ihardlimit;
+ compat_u64 dqb_isoftlimit;
+ compat_u64 dqb_curinodes;
+ compat_u64 dqb_btime;
+ compat_u64 dqb_itime;
+ compat_uint_t dqb_valid;
+};
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+ compat_u64 dqb_bhardlimit;
+ compat_u64 qfs_nblks;
+ compat_uint_t qfs_nextents;
+};
+
+struct compat_fs_quota_stat {
+ __s8 qs_version;
+ __u16 qs_flags;
+ __s8 qs_pad;
+ struct compat_fs_qfilestat qs_uquota;
+ struct compat_fs_qfilestat qs_gquota;
+ compat_uint_t qs_incoredqs;
+ compat_int_t qs_btimelimit;
+ compat_int_t qs_itimelimit;
+ compat_int_t qs_rtbtimelimit;
+ __u16 qs_bwarnlimit;
+ __u16 qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+ qid_t id, void __user *addr)
+{
+ unsigned int cmds;
+ struct if_dqblk __user *dqblk;
+ struct compat_if_dqblk __user *compat_dqblk;
+ struct fs_quota_stat __user *fsqstat;
+ struct compat_fs_quota_stat __user *compat_fsqstat;
+ compat_uint_t data;
+ u16 xdata;
+ long ret;
+
+ cmds = cmd >> SUBCMDSHIFT;
+
+ switch (cmds) {
+ case Q_GETQUOTA:
+ dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+ compat_dqblk = addr;
+ ret = sys_quotactl(cmd, special, id, dqblk);
+ if (ret)
+ break;
+ if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+ get_user(data, &dqblk->dqb_valid) ||
+ put_user(data, &compat_dqblk->dqb_valid))
+ ret = -EFAULT;
+ break;
+ case Q_SETQUOTA:
+ dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+ compat_dqblk = addr;
+ ret = -EFAULT;
+ if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+ get_user(data, &compat_dqblk->dqb_valid) ||
+ put_user(data, &dqblk->dqb_valid))
+ break;
+ ret = sys_quotactl(cmd, special, id, dqblk);
+ break;
+ case Q_XGETQSTAT:
+ fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+ compat_fsqstat = addr;
+ ret = sys_quotactl(cmd, special, id, fsqstat);
+ if (ret)
+ break;
+ ret = -EFAULT;
+ /* Copying qs_version, qs_flags, qs_pad */
+ if (copy_in_user(compat_fsqstat, fsqstat,
+ offsetof(struct compat_fs_quota_stat, qs_uquota)))
+ break;
+ /* Copying qs_uquota */
+ if (copy_in_user(&compat_fsqstat->qs_uquota,
+ &fsqstat->qs_uquota,
+ sizeof(compat_fsqstat->qs_uquota)) ||
+ get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+ put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+ break;
+ /* Copying qs_gquota */
+ if (copy_in_user(&compat_fsqstat->qs_gquota,
+ &fsqstat->qs_gquota,
+ sizeof(compat_fsqstat->qs_gquota)) ||
+ get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+ put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+ break;
+ /* Copying the rest */
+ if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+ &fsqstat->qs_incoredqs,
+ sizeof(struct compat_fs_quota_stat) -
+ offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+ get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+ put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+ break;
+ ret = 0;
+ break;
+ default:
+ ret = sys_quotactl(cmd, special, id, addr);
+ }
+ return ret;
+}
+#endif
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index d40d22b347b7..ef2b46d099ff 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -60,6 +60,7 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
inode->i_blocks = 0;
inode->i_mapping->a_ops = &ramfs_aops;
inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
+ mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) {
default:
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 30eebfb1b2d8..2070aeee2a52 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1305,7 +1305,6 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
*ppos + count > MAX_NON_LFS) {
if (*ppos >= MAX_NON_LFS) {
- send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
if (count > MAX_NON_LFS - (unsigned long)*ppos)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 1272d11399fb..ddde489f1cb2 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -7,6 +7,7 @@
#include <linux/reiserfs_fs.h>
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h>
+#include <linux/exportfs.h>
#include <linux/smp_lock.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index b484d2913c0d..11a0fcc2d402 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -51,8 +51,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
if (IS_RDONLY(inode))
return -EROFS;
- if ((current->fsuid != inode->i_uid)
- && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (get_user(flags, (int __user *)arg))
@@ -81,7 +80,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
case REISERFS_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *)arg);
case REISERFS_IOC_SETVERSION:
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (IS_RDONLY(inode))
return -EROFS;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b4ac9119200e..5a93cfe1a032 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
+#include <linux/exportfs.h>
#include <linux/vfs.h>
#include <linux/mnt_namespace.h>
#include <linux/mount.h>
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 5296a29cc5eb..b7e4fa4539de 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -21,7 +21,7 @@ xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
if (!reiserfs_posixacl(inode->i_sb))
return -EOPNOTSUPP;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
if (value) {
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 49194a4e6b91..bbb19be260ce 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -177,21 +177,23 @@ EXPORT_SYMBOL(seq_read);
static int traverse(struct seq_file *m, loff_t offset)
{
- loff_t pos = 0;
+ loff_t pos = 0, index;
int error = 0;
void *p;
m->version = 0;
- m->index = 0;
+ index = 0;
m->count = m->from = 0;
- if (!offset)
+ if (!offset) {
+ m->index = index;
return 0;
+ }
if (!m->buf) {
m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
if (!m->buf)
return -ENOMEM;
}
- p = m->op->start(m, &m->index);
+ p = m->op->start(m, &index);
while (p) {
error = PTR_ERR(p);
if (IS_ERR(p))
@@ -204,15 +206,17 @@ static int traverse(struct seq_file *m, loff_t offset)
if (pos + m->count > offset) {
m->from = offset - pos;
m->count -= m->from;
+ m->index = index;
break;
}
pos += m->count;
m->count = 0;
if (pos == offset) {
- m->index++;
+ index++;
+ m->index = index;
break;
}
- p = m->op->next(m, p, &m->index);
+ p = m->op->next(m, p, &index);
}
m->op->stop(m, p);
return error;
@@ -260,8 +264,8 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
}
}
}
- mutex_unlock(&m->lock);
file->f_version = m->version;
+ mutex_unlock(&m->lock);
return retval;
}
EXPORT_SYMBOL(seq_lseek);
diff --git a/fs/splice.c b/fs/splice.c
index 6c9828651e6f..53fc2082a468 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1061,8 +1061,9 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
while (len) {
size_t read_len;
+ loff_t pos = sd->pos;
- ret = do_splice_to(in, &sd->pos, pipe, len, flags);
+ ret = do_splice_to(in, &pos, pipe, len, flags);
if (unlikely(ret <= 0))
goto out_release;
@@ -1080,6 +1081,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
bytes += ret;
len -= ret;
+ sd->pos = pos;
if (ret < read_len)
goto out_release;
diff --git a/fs/super.c b/fs/super.c
index 5260d620c555..fc8ebedc6bed 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -884,6 +884,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
error = type->get_sb(type, flags, name, data, mnt);
if (error < 0)
goto out_free_secdata;
+ BUG_ON(!mnt->mnt_sb);
error = security_sb_kern_mount(mnt->mnt_sb, secdata);
if (error)
diff --git a/fs/udf/crc.c b/fs/udf/crc.c
index 1b82a4adc2f7..ef2bfaa19d75 100644
--- a/fs/udf/crc.c
+++ b/fs/udf/crc.c
@@ -106,8 +106,8 @@ int main(void)
{
unsigned short x;
- x = udf_crc16(bytes, sizeof bytes);
- printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
+ x = udf_crc(bytes, sizeof bytes);
+ printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
return 0;
}
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 8206983f2ebf..10f3188738af 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -50,7 +50,7 @@ void udf_free_inode(struct inode * inode)
else
UDF_SB_LVIDIU(sb)->numFiles =
cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1);
-
+
mark_buffer_dirty(sbi->s_lvidbh);
}
mutex_unlock(&sbi->s_alloc_mutex);
@@ -136,6 +136,13 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
UDF_I_EFE(inode) = 0;
UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
}
+ if (!UDF_I_DATA(inode))
+ {
+ iput(inode);
+ *err = -ENOMEM;
+ mutex_unlock(&sbi->s_alloc_mutex);
+ return NULL;
+ }
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index bf7de0bdbab3..5b82e489af78 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -49,6 +49,7 @@ MODULE_LICENSE("GPL");
static mode_t udf_convert_permissions(struct fileEntry *);
static int udf_update_inode(struct inode *, int);
static void udf_fill_inode(struct inode *, struct buffer_head *);
+static int udf_alloc_i_data(struct inode *inode, size_t size);
static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
long *, int *);
static int8_t udf_insert_aext(struct inode *, struct extent_position,
@@ -734,7 +735,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
(*c) ++;
(*endnum) ++;
}
-
+
laarr[curr].extLocation.logicalBlockNum = newblocknum;
if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
laarr[curr].extLocation.partitionReferenceNum =
@@ -836,7 +837,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
{
numalloc -= elen;
if (*endnum > (i+1))
- memmove(&laarr[i], &laarr[i+1],
+ memmove(&laarr[i], &laarr[i+1],
sizeof(long_ad) * (*endnum - (i+1)));
i --;
(*endnum) --;
@@ -1024,7 +1025,7 @@ void udf_truncate(struct inode * inode)
{
block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block);
udf_truncate_extents(inode);
- }
+ }
inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
if (IS_SYNC(inode))
@@ -1087,10 +1088,10 @@ __udf_read_inode(struct inode *inode)
{
kernel_lb_addr loc;
ie = (struct indirectEntry *)ibh->b_data;
-
+
loc = lelb_to_cpu(ie->indirectICB.extLocation);
-
- if (ie->indirectICB.extLength &&
+
+ if (ie->indirectICB.extLength &&
(nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident)))
{
if (ident == TAG_IDENT_FE ||
@@ -1156,14 +1157,22 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
{
UDF_I_EFE(inode) = 1;
UDF_I_USE(inode) = 0;
- UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+ if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)))
+ {
+ make_bad_inode(inode);
+ return;
+ }
memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
}
else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
{
UDF_I_EFE(inode) = 0;
UDF_I_USE(inode) = 0;
- UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+ if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct fileEntry)))
+ {
+ make_bad_inode(inode);
+ return;
+ }
memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
}
else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
@@ -1173,7 +1182,11 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
UDF_I_LENALLOC(inode) =
le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
- UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+ if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)))
+ {
+ make_bad_inode(inode);
+ return;
+ }
memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
return;
}
@@ -1191,7 +1204,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
if (!inode->i_nlink)
inode->i_nlink = 1;
-
+
inode->i_size = le64_to_cpu(fe->informationLength);
UDF_I_LENEXTENTS(inode) = inode->i_size;
@@ -1243,7 +1256,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
}
else
{
- inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
+ inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
if ( udf_stamp_to_time(&convtime, &convtime_usec,
@@ -1374,6 +1387,20 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
}
}
+static int udf_alloc_i_data(struct inode *inode, size_t size)
+{
+ UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL);
+
+ if (!UDF_I_DATA(inode))
+ {
+ printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free memory\n",
+ inode->i_ino);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static mode_t
udf_convert_permissions(struct fileEntry *fe)
{
@@ -2072,7 +2099,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
mark_buffer_dirty_inode(oepos.bh, inode);
}
}
-
+
brelse(epos.bh);
brelse(oepos.bh);
return (elen >> 30);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 6658afb41cc7..d6a504f5d758 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1356,7 +1356,7 @@ udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
case UDF_VIRTUAL_MAP15:
case UDF_VIRTUAL_MAP20:
{
- kernel_lb_addr ino;
+ kernel_lb_addr uninitialized_var(ino);
if (!UDF_SB_LASTBLOCK(sb))
{
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 22ff6ed55ce9..2b3011689e89 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -87,6 +87,7 @@
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include <linux/vfs.h>
+#include <linux/log2.h>
#include "swab.h"
#include "util.h"
@@ -854,7 +855,7 @@ magic_found:
uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
- if (uspi->s_fsize & (uspi->s_fsize - 1)) {
+ if (!is_power_of_2(uspi->s_fsize)) {
printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n",
uspi->s_fsize);
goto failed;
@@ -869,7 +870,7 @@ magic_found:
uspi->s_fsize);
goto failed;
}
- if (uspi->s_bsize & (uspi->s_bsize - 1)) {
+ if (!is_power_of_2(uspi->s_bsize)) {
printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n",
uspi->s_bsize);
goto failed;
diff --git a/fs/utimes.c b/fs/utimes.c
index b3c88952465f..682eb63b20ad 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -106,7 +106,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
if (IS_IMMUTABLE(inode))
goto dput_and_out;
- if (current->fsuid != inode->i_uid) {
+ if (!is_owner_or_cap(inode)) {
if (f) {
if (!(f->f_mode & FMODE_WRITE))
goto dput_and_out;
diff --git a/fs/xattr.c b/fs/xattr.c
index 4523aca79659..a44fd92caca3 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -60,8 +60,7 @@ xattr_permission(struct inode *inode, const char *name, int mask)
if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
return -EPERM;
if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
- (mask & MAY_WRITE) && (current->fsuid != inode->i_uid) &&
- !capable(CAP_FOWNER))
+ (mask & MAY_WRITE) && !is_owner_or_cap(inode))
return -EPERM;
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 2df63622354e..b0f0e58866de 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -35,10 +35,13 @@
#include <linux/freezer.h>
static kmem_zone_t *xfs_buf_zone;
-static struct shrinker *xfs_buf_shake;
STATIC int xfsbufd(void *);
STATIC int xfsbufd_wakeup(int, gfp_t);
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
+static struct shrinker xfs_buf_shake = {
+ .shrink = xfsbufd_wakeup,
+ .seeks = DEFAULT_SEEKS,
+};
static struct workqueue_struct *xfslogd_workqueue;
struct workqueue_struct *xfsdatad_workqueue;
@@ -1832,14 +1835,9 @@ xfs_buf_init(void)
if (!xfsdatad_workqueue)
goto out_destroy_xfslogd_workqueue;
- xfs_buf_shake = set_shrinker(DEFAULT_SEEKS, xfsbufd_wakeup);
- if (!xfs_buf_shake)
- goto out_destroy_xfsdatad_workqueue;
-
+ register_shrinker(&xfs_buf_shake);
return 0;
- out_destroy_xfsdatad_workqueue:
- destroy_workqueue(xfsdatad_workqueue);
out_destroy_xfslogd_workqueue:
destroy_workqueue(xfslogd_workqueue);
out_free_buf_zone:
@@ -1854,7 +1852,7 @@ xfs_buf_init(void)
void
xfs_buf_terminate(void)
{
- remove_shrinker(xfs_buf_shake);
+ unregister_shrinker(&xfs_buf_shake);
destroy_workqueue(xfsdatad_workqueue);
destroy_workqueue(xfslogd_workqueue);
kmem_zone_destroy(xfs_buf_zone);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 06894cf00b12..4528f9a3f304 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -562,6 +562,7 @@ xfssyncd(
bhv_vfs_sync_work_t *work, *n;
LIST_HEAD (tmp);
+ set_freezable();
timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
for (;;) {
timeleft = schedule_timeout_interruptible(timeleft);
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 33dd1ca13245..201cc3273c84 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -18,6 +18,8 @@
#ifndef __XFS_SUPER_H__
#define __XFS_SUPER_H__
+#include <linux/exportfs.h>
+
#ifdef CONFIG_XFS_DMAPI
# define vfs_insertdmapi(vfs) vfs_insertops(vfsp, &xfs_dmops)
# define vfs_initdmapi() dmapi_init()
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 7def4c699343..2d274b23ade5 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -62,7 +62,6 @@ uint ndquot;
kmem_zone_t *qm_dqzone;
kmem_zone_t *qm_dqtrxzone;
-static struct shrinker *xfs_qm_shaker;
static cred_t xfs_zerocr;
@@ -78,6 +77,11 @@ STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
STATIC int xfs_qm_shake(int, gfp_t);
+static struct shrinker xfs_qm_shaker = {
+ .shrink = xfs_qm_shake,
+ .seeks = DEFAULT_SEEKS,
+};
+
#ifdef DEBUG
extern mutex_t qcheck_lock;
#endif
@@ -149,7 +153,7 @@ xfs_Gqm_init(void)
} else
xqm->qm_dqzone = qm_dqzone;
- xfs_qm_shaker = set_shrinker(DEFAULT_SEEKS, xfs_qm_shake);
+ register_shrinker(&xfs_qm_shaker);
/*
* The t_dqinfo portion of transactions.
@@ -181,7 +185,7 @@ xfs_qm_destroy(
ASSERT(xqm != NULL);
ASSERT(xqm->qm_nrefs == 0);
- remove_shrinker(xfs_qm_shaker);
+ unregister_shrinker(&xfs_qm_shaker);
hsize = xqm->qm_dqhashmask + 1;
for (i = 0; i < hsize; i++) {
xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
diff --git a/include/asm-alpha/fb.h b/include/asm-alpha/fb.h
new file mode 100644
index 000000000000..fa9bbb96b2b3
--- /dev/null
+++ b/include/asm-alpha/fb.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/device.h>
+
+/* Caching is off in the I/O space quadrant by design. */
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 21a86f1a05b3..ab5b60dcef19 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -4,6 +4,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <asm/compiler.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -90,6 +91,11 @@ static inline void * phys_to_virt(unsigned long address)
#define page_to_phys(page) page_to_pa(page)
+static inline dma_addr_t __deprecated isa_page_to_bus(struct page *page)
+{
+ return page_to_phys(page);
+}
+
/* This depends on working iommu. */
#define BIO_VMERGE_BOUNDARY (alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
@@ -102,12 +108,12 @@ static inline void * phys_to_virt(unsigned long address)
*
* Note that this only works for a limited range of kernel addresses,
* and very well may not span all memory. Consider this interface
- * deprecated in favour of the mapping functions in <asm/pci.h>.
+ * deprecated in favour of the DMA-mapping API.
*/
extern unsigned long __direct_map_base;
extern unsigned long __direct_map_size;
-static inline unsigned long virt_to_bus(void *address)
+static inline unsigned long __deprecated virt_to_bus(void *address)
{
unsigned long phys = virt_to_phys(address);
unsigned long bus = phys + __direct_map_base;
@@ -115,7 +121,7 @@ static inline unsigned long virt_to_bus(void *address)
}
#define isa_virt_to_bus virt_to_bus
-static inline void *bus_to_virt(unsigned long address)
+static inline void * __deprecated bus_to_virt(unsigned long address)
{
void *virt;
@@ -126,6 +132,7 @@ static inline void *bus_to_virt(unsigned long address)
virt = phys_to_virt(address);
return (long)address <= 0 ? NULL : virt;
}
+#define isa_bus_to_virt bus_to_virt
/*
* There are different chipsets to interface the Alpha CPUs to the world.
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index d2bed3cb33ff..bae7f05716d4 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -17,7 +17,8 @@
extern void clear_page(void *page);
#define clear_user_page(page, vaddr, pg) clear_page(page)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vmaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vmaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
extern void copy_page(void * _to, void * _from);
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 616d20662ff3..99037b032357 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -264,21 +264,15 @@ extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; }
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-extern inline int pte_read(pte_t pte) { return !(pte_val(pte) & _PAGE_FOR); }
extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_FOW); }
-extern inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_FOE); }
extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOR; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOE; return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(__DIRTY_BITS); return pte; }
extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(__ACCESS_BITS); return pte; }
extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_FOW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= ~_PAGE_FOR; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= ~_PAGE_FOE; return pte; }
extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= __DIRTY_BITS; return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; }
diff --git a/include/asm-alpha/termios.h b/include/asm-alpha/termios.h
index 39e492c3bfa3..fa13716a11c3 100644
--- a/include/asm-alpha/termios.h
+++ b/include/asm-alpha/termios.h
@@ -81,7 +81,7 @@ struct termio {
#define user_termio_to_kernel_termios(a_termios, u_termio) \
({ \
- struct termios *k_termios = (a_termios); \
+ struct ktermios *k_termios = (a_termios); \
struct termio k_termio; \
int canon, ret; \
\
@@ -113,7 +113,7 @@ struct termio {
*/
#define kernel_termios_to_user_termio(u_termio, a_termios) \
({ \
- struct termios *k_termios = (a_termios); \
+ struct ktermios *k_termios = (a_termios); \
struct termio k_termio; \
int canon; \
\
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index 0ce6ee98ed0b..d96b10fd449f 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -64,6 +64,7 @@ extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
/* Ethernet (EMAC & MACB) */
struct at91_eth_data {
+ u32 phy_mask;
u8 phy_irq_pin; /* PHY IRQ */
u8 is_rmii; /* using RMII interface? */
};
diff --git a/include/asm-arm/fb.h b/include/asm-arm/fb.h
new file mode 100644
index 000000000000..d92e99cd8c8a
--- /dev/null
+++ b/include/asm-arm/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 21dec9f258d8..d2e8171d1d4e 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -83,14 +83,14 @@
* means that a write to a clean page will cause a permission fault, and
* the Linux MM layer will mark the page dirty via handle_pte_fault().
* For the hardware to notice the permission change, the TLB entry must
- * be flushed, and ptep_establish() does that for us.
+ * be flushed, and ptep_set_access_flags() does that for us.
*
* The "accessed" or "young" bit is emulated by a similar method; we only
* allow accesses to the page if the "young" bit is set. Accesses to the
* page will cause a fault, and handle_pte_fault() will set the young bit
* for us as long as the page is marked present in the corresponding Linux
- * PTE entry. Again, ptep_establish() will ensure that the TLB is up to
- * date.
+ * PTE entry. Again, ptep_set_access_flags() will ensure that the TLB is
+ * up to date.
*
* However, when the "young" bit is cleared, we deny access to the page
* by clearing the hardware PTE. Currently Linux does not flush the TLB
@@ -257,9 +257,7 @@ extern struct page *empty_zero_page;
* Undefined behaviour if not..
*/
#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
-#define pte_read(pte) (pte_val(pte) & L_PTE_USER)
#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
-#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)
#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
@@ -275,12 +273,8 @@ extern struct page *empty_zero_page;
#define PTE_BIT_FUNC(fn,op) \
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
-/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/
-/*PTE_BIT_FUNC(mkread, |= L_PTE_USER);*/
PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
PTE_BIT_FUNC(mkwrite, |= L_PTE_WRITE);
-PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC);
-PTE_BIT_FUNC(mkexec, |= L_PTE_EXEC);
PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY);
PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY);
PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG);
diff --git a/include/asm-arm26/dma-mapping.h b/include/asm-arm26/dma-mapping.h
deleted file mode 100644
index a95eae0aeb77..000000000000
--- a/include/asm-arm26/dma-mapping.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <asm-generic/dma-mapping-broken.h>
-
diff --git a/include/asm-arm26/fb.h b/include/asm-arm26/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-arm26/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-arm26/ioctls.h b/include/asm-arm26/ioctls.h
index ba9c7d81d24e..8a3296200be1 100644
--- a/include/asm-arm26/ioctls.h
+++ b/include/asm-arm26/ioctls.h
@@ -47,6 +47,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index 2b20e9f08857..55a1a697d12b 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -218,9 +218,7 @@ extern struct page *empty_zero_page;
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-#define pte_read(pte) (!(pte_val(pte) & _PAGE_NOT_USER))
#define pte_write(pte) (!(pte_val(pte) & _PAGE_READONLY))
-#define pte_exec(pte) (!(pte_val(pte) & _PAGE_NOT_USER))
#define pte_dirty(pte) (!(pte_val(pte) & _PAGE_CLEAN))
#define pte_young(pte) (!(pte_val(pte) & _PAGE_OLD))
//ONLY when !pte_present() I think. nicked from arm32 (FIXME!)
@@ -231,8 +229,6 @@ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
PTE_BIT_FUNC(wrprotect, |= _PAGE_READONLY);
PTE_BIT_FUNC(mkwrite, &= ~_PAGE_READONLY);
-PTE_BIT_FUNC(exprotect, |= _PAGE_NOT_USER);
-PTE_BIT_FUNC(mkexec, &= ~_PAGE_NOT_USER);
PTE_BIT_FUNC(mkclean, |= _PAGE_CLEAN);
PTE_BIT_FUNC(mkdirty, &= ~_PAGE_CLEAN);
PTE_BIT_FUNC(mkold, |= _PAGE_OLD);
diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h
index f66b51804736..48d2f5c7bcb8 100644
--- a/include/asm-arm26/termbits.h
+++ b/include/asm-arm26/termbits.h
@@ -138,6 +138,7 @@ struct ktermios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
@@ -153,10 +154,12 @@ struct ktermios {
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
diff --git a/include/asm-arm26/termios.h b/include/asm-arm26/termios.h
index 329c324c4040..293e3f1bc3f2 100644
--- a/include/asm-arm26/termios.h
+++ b/include/asm-arm26/termios.h
@@ -82,8 +82,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index 9fd2e32f84b8..974480438849 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -21,6 +21,7 @@ void at32_map_usart(unsigned int hw_id, unsigned int line);
struct platform_device *at32_add_device_usart(unsigned int id);
struct eth_platform_data {
+ u32 phy_mask;
u8 is_rmii;
};
struct platform_device *
diff --git a/include/asm-avr32/fb.h b/include/asm-avr32/fb.h
new file mode 100644
index 000000000000..41baf84ad402
--- /dev/null
+++ b/include/asm-avr32/fb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+ & ~_PAGE_CACHABLE)
+ | (_PAGE_BUFFER | _PAGE_DIRTY));
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-avr32/pgtable.h b/include/asm-avr32/pgtable.h
index f6cc2b0f75c3..c07bdd10b891 100644
--- a/include/asm-avr32/pgtable.h
+++ b/include/asm-avr32/pgtable.h
@@ -201,18 +201,10 @@ extern struct page *empty_zero_page;
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte)
-{
- return pte_val(pte) & _PAGE_USER;
-}
static inline int pte_write(pte_t pte)
{
return pte_val(pte) & _PAGE_RW;
}
-static inline int pte_exec(pte_t pte)
-{
- return pte_val(pte) & _PAGE_EXECUTE;
-}
static inline int pte_dirty(pte_t pte)
{
return pte_val(pte) & _PAGE_DIRTY;
@@ -231,21 +223,11 @@ static inline int pte_file(pte_t pte)
}
/* Mutator functions for PTE bits */
-static inline pte_t pte_rdprotect(pte_t pte)
-{
- set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
- return pte;
-}
static inline pte_t pte_wrprotect(pte_t pte)
{
set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW));
return pte;
}
-static inline pte_t pte_exprotect(pte_t pte)
-{
- set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE));
- return pte;
-}
static inline pte_t pte_mkclean(pte_t pte)
{
set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY));
@@ -256,21 +238,11 @@ static inline pte_t pte_mkold(pte_t pte)
set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED));
return pte;
}
-static inline pte_t pte_mkread(pte_t pte)
-{
- set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
- return pte;
-}
static inline pte_t pte_mkwrite(pte_t pte)
{
set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW));
return pte;
}
-static inline pte_t pte_mkexec(pte_t pte)
-{
- set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE));
- return pte;
-}
static inline pte_t pte_mkdirty(pte_t pte)
{
set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY));
diff --git a/include/asm-blackfin/fb.h b/include/asm-blackfin/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-blackfin/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-cris/fb.h b/include/asm-cris/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-cris/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-cris/ioctls.h b/include/asm-cris/ioctls.h
index 97787c3c575f..4f4e52531fa0 100644
--- a/include/asm-cris/ioctls.h
+++ b/include/asm-cris/ioctls.h
@@ -48,6 +48,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index 9f13c32552bf..0648e3153f81 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -20,7 +20,8 @@
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index c94a7107019c..417f71116215 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -111,9 +111,7 @@ extern unsigned long empty_zero_page;
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
@@ -124,18 +122,6 @@ static inline pte_t pte_wrprotect(pte_t pte)
return pte;
}
-static inline pte_t pte_rdprotect(pte_t pte)
-{
- pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
- return pte;
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
- pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
- return pte;
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
@@ -156,22 +142,6 @@ static inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-static inline pte_t pte_mkread(pte_t pte)
-{
- pte_val(pte) |= _PAGE_READ;
- if (pte_val(pte) & _PAGE_ACCESSED)
- pte_val(pte) |= _PAGE_SILENT_READ;
- return pte;
-}
-
-static inline pte_t pte_mkexec(pte_t pte)
-{
- pte_val(pte) |= _PAGE_READ;
- if (pte_val(pte) & _PAGE_ACCESSED)
- pte_val(pte) |= _PAGE_SILENT_READ;
- return pte;
-}
-
static inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_MODIFIED;
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 6cc2e2736f7b..71c1b36269b8 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -166,6 +166,7 @@ struct ktermios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
diff --git a/include/asm-cris/termios.h b/include/asm-cris/termios.h
index c9dbd4d43368..b0124e6c2e41 100644
--- a/include/asm-cris/termios.h
+++ b/include/asm-cris/termios.h
@@ -81,8 +81,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
diff --git a/include/asm-frv/fb.h b/include/asm-frv/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-frv/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 114aefae2701..147e995bec24 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -377,30 +377,17 @@ static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address)
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return !((pte).pte & _PAGE_SUPER); }
-static inline int pte_exec(pte_t pte) { return !((pte).pte & _PAGE_SUPER); }
static inline int pte_dirty(pte_t pte) { return (pte).pte & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return (pte).pte & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return !((pte).pte & _PAGE_WP); }
-static inline pte_t pte_rdprotect(pte_t pte) { (pte).pte |= _PAGE_SUPER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) { (pte).pte |= _PAGE_SUPER; return pte; }
static inline pte_t pte_mkclean(pte_t pte) { (pte).pte &= ~_PAGE_DIRTY; return pte; }
static inline pte_t pte_mkold(pte_t pte) { (pte).pte &= ~_PAGE_ACCESSED; return pte; }
static inline pte_t pte_wrprotect(pte_t pte) { (pte).pte |= _PAGE_WP; return pte; }
-static inline pte_t pte_mkread(pte_t pte) { (pte).pte &= ~_PAGE_SUPER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) { (pte).pte &= ~_PAGE_SUPER; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte &= ~_PAGE_WP; return pte; }
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
- int i = test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
- asm volatile("dcf %M0" :: "U"(*ptep));
- return i;
-}
-
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
@@ -510,7 +497,6 @@ static inline int pte_file(pte_t pte)
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index d0ea6789b31e..7306c71a8926 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -326,10 +326,14 @@
#define __NR_move_pages 317
#define __NR_getcpu 318
#define __NR_epoll_pwait 319
+#define __NR_utimensat 320
+#define __NR_signalfd 321
+#define __NR_timerfd 322
+#define __NR_eventfd 323
#ifdef __KERNEL__
-#define NR_syscalls 320
+#define NR_syscalls 324
#define __ARCH_WANT_IPC_PARSE_VERSION
/* #define __ARCH_WANT_OLD_READDIR */
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 7f30cce52857..344e3091af24 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -28,7 +28,7 @@ struct bug_entry {
#endif
#ifndef HAVE_ARCH_BUG_ON
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
#endif
#ifndef HAVE_ARCH_WARN_ON
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h
index 29413d3d4605..e2468f894d2a 100644
--- a/include/asm-generic/dma-mapping-broken.h
+++ b/include/asm-generic/dma-mapping-broken.h
@@ -1,24 +1,82 @@
#ifndef _ASM_GENERIC_DMA_MAPPING_H
#define _ASM_GENERIC_DMA_MAPPING_H
-/* This is used for archs that do not support DMA */
+/* define the dma api to allow compilation but not linking of
+ * dma dependent code. Code that depends on the dma-mapping
+ * API needs to set 'depends on HAS_DMA' in its Kconfig
+ */
-static inline void *
+struct scatterlist;
+
+extern void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t flag)
-{
- BUG();
- return NULL;
-}
+ gfp_t flag);
-static inline void
+extern void
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t dma_handle)
-{
- BUG();
-}
+ dma_addr_t dma_handle);
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+extern dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction);
+
+extern void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction);
+
+extern int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction);
+
+extern void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction);
+
+extern dma_addr_t
+dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+ size_t size, enum dma_data_direction direction);
+
+extern void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction);
+
+extern void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction);
+
+extern void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction);
+
+extern void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction);
+
+#define dma_sync_single_for_device dma_sync_single_for_cpu
+#define dma_sync_single_range_for_device dma_sync_single_range_for_cpu
+#define dma_sync_sg_for_device dma_sync_sg_for_cpu
+
+extern int
+dma_mapping_error(dma_addr_t dma_addr);
+
+extern int
+dma_supported(struct device *dev, u64 mask);
+
+extern int
+dma_set_mask(struct device *dev, u64 mask);
+
+extern int
+dma_get_cache_alignment(void);
+
+extern int
+dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+
+extern void
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction direction);
+
#endif /* _ASM_GENERIC_DMA_MAPPING_H */
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index c154b9d6e7e5..b8477414c5c8 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -48,6 +48,9 @@
#ifndef O_NOATIME
#define O_NOATIME 01000000
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 02000000 /* set close_on_exec */
+#endif
#ifndef O_NDELAY
#define O_NDELAY O_NONBLOCK
#endif
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 7d7bcf990e99..f605e8d0eed3 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -3,25 +3,6 @@
#ifndef __ASSEMBLY__
-#ifndef __HAVE_ARCH_PTEP_ESTABLISH
-/*
- * Establish a new mapping:
- * - flush the old one
- * - update the page tables
- * - inform the TLB about the new one
- *
- * We hold the mm semaphore for reading, and the pte lock.
- *
- * Note: the old pte is known to not be writable, so we don't need to
- * worry about dirty bits etc getting lost.
- */
-#define ptep_establish(__vma, __address, __ptep, __entry) \
-do { \
- set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
- flush_tlb_page(__vma, __address); \
-} while (0)
-#endif
-
#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
/*
* Largely same as above, but only sets the access flags (dirty,
@@ -68,31 +49,6 @@ do { \
})
#endif
-#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __address, __ptep) \
-({ \
- pte_t __pte = *__ptep; \
- int r = 1; \
- if (!pte_dirty(__pte)) \
- r = 0; \
- else \
- set_pte_at((__vma)->vm_mm, (__address), (__ptep), \
- pte_mkclean(__pte)); \
- r; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
-({ \
- int __dirty; \
- __dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep); \
- if (__dirty) \
- flush_tlb_page(__vma, __address); \
- __dirty; \
-})
-#endif
-
#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define ptep_get_and_clear(__mm, __address, __ptep) \
({ \
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 09ec447fe2af..16a466e50681 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -18,7 +18,8 @@
#define get_unaligned(ptr) \
__get_unaligned((ptr), sizeof(*(ptr)))
#define put_unaligned(x,ptr) \
- __put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
+ ((void)sizeof(*(ptr)=(x)),\
+ __put_unaligned((__force __u64)(x), (ptr), sizeof(*(ptr))))
/*
* This function doesn't actually exist. The idea is that when
@@ -95,21 +96,21 @@ static inline void __ustw(__u16 val, __u16 *addr)
default: \
bad_unaligned_access_length(); \
}; \
- (__typeof__(*(ptr)))val; \
+ (__force __typeof__(*(ptr)))val; \
})
#define __put_unaligned(val, ptr, size) \
-do { \
+({ \
void *__gu_p = ptr; \
switch (size) { \
case 1: \
- *(__u8 *)__gu_p = val; \
+ *(__u8 *)__gu_p = (__force __u8)val; \
break; \
case 2: \
- __ustw(val, __gu_p); \
+ __ustw((__force __u16)val, __gu_p); \
break; \
case 4: \
- __ustl(val, __gu_p); \
+ __ustl((__force __u32)val, __gu_p); \
break; \
case 8: \
__ustq(val, __gu_p); \
@@ -117,6 +118,7 @@ do { \
default: \
bad_unaligned_access_length(); \
}; \
-} while(0)
+ (void)0; \
+})
#endif /* _ASM_GENERIC_UNALIGNED_H */
diff --git a/include/asm-h8300/dma-mapping.h b/include/asm-h8300/dma-mapping.h
deleted file mode 100644
index d00e40099165..000000000000
--- a/include/asm-h8300/dma-mapping.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/dma-mapping-broken.h>
diff --git a/include/asm-h8300/fb.h b/include/asm-h8300/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-h8300/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-h8300/ioctls.h b/include/asm-h8300/ioctls.h
index ac20457e5978..98a53d067269 100644
--- a/include/asm-h8300/ioctls.h
+++ b/include/asm-h8300/ioctls.h
@@ -47,6 +47,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index 3b4f2903f91d..c8cc81a3aca5 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -22,7 +22,8 @@
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h
index e877b40ac5ba..31eca81db3f7 100644
--- a/include/asm-h8300/termbits.h
+++ b/include/asm-h8300/termbits.h
@@ -141,6 +141,7 @@ struct ktermios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
@@ -156,10 +157,12 @@ struct ktermios {
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
+#define IBSHIFT 16 /* shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
diff --git a/include/asm-h8300/termios.h b/include/asm-h8300/termios.h
index fb2925d08c49..70eea64b4213 100644
--- a/include/asm-h8300/termios.h
+++ b/include/asm-h8300/termios.h
@@ -82,8 +82,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index 45f09dc9caff..aee4009a498e 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -92,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_MEMDIE 5
+#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -99,6 +100,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
diff --git a/include/asm-i386/fb.h b/include/asm-i386/fb.h
new file mode 100644
index 000000000000..d1c6297d4a61
--- /dev/null
+++ b/include/asm-i386/fb.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+extern int fb_is_primary_device(struct fb_info *info);
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ if (boot_cpu_data.x86 > 3)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052ee3a4..249e753ac805 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,8 @@ extern unsigned long __FIXADDR_TOP;
enum fixed_addresses {
FIX_HOLE,
FIX_VDSO,
+ FIX_DBGP_BASE,
+ FIX_EARLYCON_MEM_BASE,
#ifdef CONFIG_X86_LOCAL_APIC
FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
#endif
diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h
index 0fc240c80f49..e7817a3d6578 100644
--- a/include/asm-i386/ide.h
+++ b/include/asm-i386/ide.h
@@ -40,14 +40,13 @@ static __inline__ int ide_default_irq(unsigned long base)
static __inline__ unsigned long ide_default_io_base(int index)
{
- struct pci_dev *pdev;
/*
* If PCI is present then it is not safe to poke around
* the other legacy IDE ports. Only 0x1f0 and 0x170 are
* defined compatibility mode ports for PCI. A user can
* override this using ide= but we must default safe.
*/
- if ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL)) == NULL) {
+ if (no_pci_devices()) {
switch(index) {
case 2: return 0x1e8;
case 3: return 0x168;
@@ -55,7 +54,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
case 5: return 0x160;
}
}
- pci_dev_put(pdev);
switch (index) {
case 0: return 0x1f0;
case 1: return 0x170;
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index e797586a5bfc..7b65b5b00034 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -129,6 +129,7 @@ extern void iounmap(volatile void __iomem *addr);
*/
extern void *bt_ioremap(unsigned long offset, unsigned long size);
extern void bt_iounmap(void *addr, unsigned long size);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
/* Use early IO mappings for DMI because it's initialized early */
#define dmi_ioremap bt_ioremap
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 818ac8bf01e2..99cf5d3692a9 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -34,7 +34,8 @@
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index a50fd1773de8..84b03cf56a79 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -57,14 +57,6 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp)
#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
/*
- * All present user pages are user-executable:
- */
-static inline int pte_exec(pte_t pte)
-{
- return pte_user(pte);
-}
-
-/*
* All present pages are kernel-executable:
*/
static inline int pte_exec_kernel(pte_t pte)
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index eb0f1d7e96a1..948a33414118 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -20,26 +20,11 @@
#define pud_present(pud) 1
/*
- * Is the pte executable?
- */
-static inline int pte_x(pte_t pte)
-{
- return !(pte_val(pte) & _PAGE_NX);
-}
-
-/*
- * All present user-pages with !NX bit are user-executable:
- */
-static inline int pte_exec(pte_t pte)
-{
- return pte_user(pte) && pte_x(pte);
-}
-/*
* All present pages with !NX bit are kernel-executable:
*/
static inline int pte_exec_kernel(pte_t pte)
{
- return pte_x(pte);
+ return !(pte_val(pte) & _PAGE_NX);
}
/* Rules for using set_pte: the pte being assigned *must* be
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 628fa7747d0c..c7fefa6b12fd 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -79,7 +79,7 @@ void paging_init(void);
* area for the same reason. ;)
*/
#define VMALLOC_OFFSET (8*1024*1024)
-#define VMALLOC_START (((unsigned long) high_memory + vmalloc_earlyreserve + \
+#define VMALLOC_START (((unsigned long) high_memory + \
2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
@@ -218,8 +218,6 @@ extern unsigned long pg0[];
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_user(pte_t pte) { return (pte).pte_low & _PAGE_USER; }
-static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_USER; }
static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; }
@@ -230,13 +228,9 @@ static inline int pte_huge(pte_t pte) { return (pte).pte_low & _PAGE_PSE; }
*/
static inline int pte_file(pte_t pte) { return (pte).pte_low & _PAGE_FILE; }
-static inline pte_t pte_rdprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; }
static inline pte_t pte_mkclean(pte_t pte) { (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
static inline pte_t pte_mkold(pte_t pte) { (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
static inline pte_t pte_wrprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_RW; return pte; }
-static inline pte_t pte_mkread(pte_t pte) { (pte).pte_low |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; }
@@ -295,17 +289,6 @@ static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
__changed; \
})
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(vma, addr, ptep) ({ \
- int __ret = 0; \
- if (pte_dirty(*(ptep))) \
- __ret = test_and_clear_bit(_PAGE_BIT_DIRTY, \
- &(ptep)->pte_low); \
- if (__ret) \
- pte_update((vma)->vm_mm, addr, ptep); \
- __ret; \
-})
-
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define ptep_test_and_clear_young(vma, addr, ptep) ({ \
int __ret = 0; \
@@ -317,27 +300,6 @@ static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
__ret; \
})
-/*
- * Rules for using ptep_establish: the pte MUST be a user pte, and
- * must be a present->present transition.
- */
-#define __HAVE_ARCH_PTEP_ESTABLISH
-#define ptep_establish(vma, address, ptep, pteval) \
-do { \
- set_pte_present((vma)->vm_mm, address, ptep, pteval); \
- flush_tlb_page(vma, address); \
-} while (0)
-
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(vma, address, ptep) \
-({ \
- int __dirty; \
- __dirty = ptep_test_and_clear_dirty((vma), (address), (ptep)); \
- if (__dirty) \
- flush_tlb_page(vma, address); \
- __dirty; \
-})
-
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
#define ptep_clear_flush_young(vma, address, ptep) \
({ \
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 94e0c147c165..422cffef00c9 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -228,6 +228,10 @@ extern int bootloader_type;
#define HAVE_ARCH_PICK_MMAP_LAYOUT
+extern void hard_disable_TSC(void);
+extern void disable_TSC(void);
+extern void hard_enable_TSC(void);
+
/*
* Size of io_bitmap.
*/
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 4cb0f91ae64f..54424e045e01 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -137,6 +137,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_DEBUG 17 /* uses debug registers */
#define TIF_IO_BITMAP 18 /* uses I/O bitmap */
#define TIF_FREEZE 19 /* is freezing for suspend */
+#define TIF_NOTSC 20 /* TSC is not accessible in userland */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -151,6 +152,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
#define _TIF_FREEZE (1<<TIF_FREEZE)
+#define _TIF_NOTSC (1<<TIF_NOTSC)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
@@ -160,7 +162,8 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
/* flags to check in __switch_to() */
-#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
+#define _TIF_WORK_CTXSW_NEXT (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUG)
+#define _TIF_WORK_CTXSW_PREV (_TIF_IO_BITMAP | _TIF_NOTSC)
/*
* Thread-synchronous status.
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index 40d01d80610d..0f6e5264ab8f 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -31,8 +31,10 @@ typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 __attribute__((aligned(4))) compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 __attribute__((aligned(4))) compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-ia64/fb.h b/include/asm-ia64/fb.h
new file mode 100644
index 000000000000..89a397cee90a
--- /dev/null
+++ b/include/asm-ia64/fb.h
@@ -0,0 +1,23 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <linux/efi.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-ia64/ioctls.h b/include/asm-ia64/ioctls.h
index 31ee521aeb7a..f41b636a0bf6 100644
--- a/include/asm-ia64/ioctls.h
+++ b/include/asm-ia64/ioctls.h
@@ -53,6 +53,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 485759ba9e36..d6345464a2b3 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -87,12 +87,13 @@ do { \
} while (0)
-#define alloc_zeroed_user_highpage(vma, vaddr) \
-({ \
- struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \
- if (page) \
- flush_dcache_page(page); \
- page; \
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+({ \
+ struct page *page = alloc_page_vma( \
+ GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr); \
+ if (page) \
+ flush_dcache_page(page); \
+ page; \
})
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 6580f31b3135..de6d01e24dd0 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -297,8 +297,6 @@ ia64_phys_addr_valid (unsigned long addr)
/*
* The following have defined behavior only work if pte_present() is true.
*/
-#define pte_user(pte) ((pte_val(pte) & _PAGE_PL_MASK) == _PAGE_PL_3)
-#define pte_read(pte) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) < 6)
#define pte_write(pte) ((unsigned) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) - 2) <= 4)
#define pte_exec(pte) ((pte_val(pte) & _PAGE_AR_RX) != 0)
#define pte_dirty(pte) ((pte_val(pte) & _PAGE_D) != 0)
@@ -310,7 +308,6 @@ ia64_phys_addr_valid (unsigned long addr)
*/
#define pte_wrprotect(pte) (__pte(pte_val(pte) & ~_PAGE_AR_RW))
#define pte_mkwrite(pte) (__pte(pte_val(pte) | _PAGE_AR_RW))
-#define pte_mkexec(pte) (__pte(pte_val(pte) | _PAGE_AR_RX))
#define pte_mkold(pte) (__pte(pte_val(pte) & ~_PAGE_A))
#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_A))
#define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D))
@@ -398,22 +395,6 @@ ptep_test_and_clear_young (struct vm_area_struct *vma, unsigned long addr, pte_t
#endif
}
-static inline int
-ptep_test_and_clear_dirty (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- if (!pte_dirty(*ptep))
- return 0;
- return test_and_clear_bit(_PAGE_D_BIT, ptep);
-#else
- pte_t pte = *ptep;
- if (!pte_dirty(pte))
- return 0;
- set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
- return 1;
-#endif
-}
-
static inline pte_t
ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
@@ -546,8 +527,10 @@ extern void lazy_mmu_prot_update (pte_t pte);
# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
({ \
int __changed = !pte_same(*(__ptep), __entry); \
- if (__changed) \
- ptep_establish(__vma, __addr, __ptep, __entry); \
+ if (__changed) { \
+ set_pte_at((__vma)->vm_mm, (__addr), __ptep, __entry); \
+ flush_tlb_page(__vma, __addr); \
+ } \
__changed; \
})
#endif
@@ -591,7 +574,6 @@ extern void lazy_mmu_prot_update (pte_t pte);
#endif
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h
index 7fae3109ef47..9f162e0089ad 100644
--- a/include/asm-ia64/termbits.h
+++ b/include/asm-ia64/termbits.h
@@ -149,6 +149,7 @@ struct ktermios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
@@ -164,10 +165,12 @@ struct ktermios {
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
diff --git a/include/asm-ia64/termios.h b/include/asm-ia64/termios.h
index 08750c2d3607..689d218c0c28 100644
--- a/include/asm-ia64/termios.h
+++ b/include/asm-ia64/termios.h
@@ -87,8 +87,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
# endif /* __KERNEL__ */
diff --git a/include/asm-m32r/dma-mapping.h b/include/asm-m32r/dma-mapping.h
deleted file mode 100644
index f9b58ebba361..000000000000
--- a/include/asm-m32r/dma-mapping.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_M32R_DMA_MAPPING_H
-#define _ASM_M32R_DMA_MAPPING_H
-
-#include <asm-generic/dma-mapping-broken.h>
-
-#endif /* _ASM_M32R_DMA_MAPPING_H */
diff --git a/include/asm-m32r/fb.h b/include/asm-m32r/fb.h
new file mode 100644
index 000000000000..d92e99cd8c8a
--- /dev/null
+++ b/include/asm-m32r/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m32r/ioctls.h b/include/asm-m32r/ioctls.h
index d23cfc45738a..b9f54bb5d7cf 100644
--- a/include/asm-m32r/ioctls.h
+++ b/include/asm-m32r/ioctls.h
@@ -47,6 +47,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 6f6ecf7d14a3..04fd183a2c58 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -15,7 +15,8 @@ extern void copy_page(void *to, void *from);
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 6604303fc47c..92d7266783fd 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -191,16 +191,6 @@ extern unsigned long empty_zero_page[1024];
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte)
-{
- return pte_val(pte) & _PAGE_READ;
-}
-
-static inline int pte_exec(pte_t pte)
-{
- return pte_val(pte) & _PAGE_EXEC;
-}
-
static inline int pte_dirty(pte_t pte)
{
return pte_val(pte) & _PAGE_DIRTY;
@@ -224,18 +214,6 @@ static inline int pte_file(pte_t pte)
return pte_val(pte) & _PAGE_FILE;
}
-static inline pte_t pte_rdprotect(pte_t pte)
-{
- pte_val(pte) &= ~_PAGE_READ;
- return pte;
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
- pte_val(pte) &= ~_PAGE_EXEC;
- return pte;
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~_PAGE_DIRTY;
@@ -254,18 +232,6 @@ static inline pte_t pte_wrprotect(pte_t pte)
return pte;
}
-static inline pte_t pte_mkread(pte_t pte)
-{
- pte_val(pte) |= _PAGE_READ;
- return pte;
-}
-
-static inline pte_t pte_mkexec(pte_t pte)
-{
- pte_val(pte) |= _PAGE_EXEC;
- return pte;
-}
-
static inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_DIRTY;
@@ -284,11 +250,6 @@ static inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
- return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
-}
-
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
@@ -382,7 +343,6 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
remap_pfn_range(vma, vaddr, pfn, size, prot)
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index 6be3b8a39841..bc104008b55b 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -140,6 +140,7 @@ struct ktermios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
@@ -155,11 +156,13 @@ struct ktermios {
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CIBAUD 002003600000 /** input baud rate */
#define CTVB 004000000000 /* VisioBraille Terminal flow control */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
diff --git a/include/asm-m32r/termios.h b/include/asm-m32r/termios.h
index 4943dd8db44d..93ce79fd342a 100644
--- a/include/asm-m32r/termios.h
+++ b/include/asm-m32r/termios.h
@@ -81,8 +81,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
diff --git a/include/asm-m68k/atari_SLM.h b/include/asm-m68k/atari_SLM.h
deleted file mode 100644
index 42f4fcdd8bc7..000000000000
--- a/include/asm-m68k/atari_SLM.h
+++ /dev/null
@@ -1,28 +0,0 @@
-
-#ifndef _ATARI_SLM_H
-#define _ATARI_SLM_H
-
-/* Atari SLM laser printer specific ioctls */
-
-#define SLMIOGSTAT 0xa100
-#define SLMIOGPSIZE 0xa101
-#define SLMIOGMFEED 0xa102
-
-#define SLMIORESET 0xa140
-
-#define SLMIOSPSIZE 0xa181
-#define SLMIOSMFEED 0xa182
-
-/* Status returning structure (SLMIOGSTAT) */
-struct SLM_status {
- int stat; /* numeric status code */
- char str[40]; /* status string */
-};
-
-/* Paper size structure (SLMIO[GS]PSIZE) */
-struct SLM_paper_size {
- int width;
- int height;
-};
-
-#endif /* _ATARI_SLM_H */
diff --git a/include/asm-m68k/atari_acsi.h b/include/asm-m68k/atari_acsi.h
deleted file mode 100644
index 10fea68f191a..000000000000
--- a/include/asm-m68k/atari_acsi.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _ASM_ATARI_ACSI_H
-#define _ASM_ATARI_ACSI_H
-
-/* Functions exported by drivers/block/acsi.c */
-
-void acsi_delay_start( void );
-void acsi_delay_end( long usec );
-int acsi_wait_for_IRQ( unsigned timeout );
-int acsi_wait_for_noIRQ( unsigned timeout );
-int acsicmd_nodma( const char *cmd, int enable);
-int acsi_getstatus( void );
-int acsi_extstatus( char *buffer, int cnt );
-void acsi_end_extstatus( void );
-int acsi_extcmd( unsigned char *buffer, int cnt );
-
-/* The ACSI buffer is guarantueed to reside in ST-RAM and may be used by other
- * drivers that work on the ACSI bus, too. It's data are valid only as long as
- * the ST-DMA is locked. */
-extern char *acsi_buffer;
-extern unsigned long phys_acsi_buffer;
-
-/* Utility macros */
-
-/* Send one data byte over the bus and set mode for next operation
- * with one move.l -- Atari recommends this...
- */
-
-#define DMA_LONG_WRITE(data,mode) \
- do { \
- *((unsigned long *)&dma_wd.fdc_acces_seccount) = \
- ((data)<<16) | (mode); \
- } while(0)
-
-#define ENABLE_IRQ() atari_turnon_irq( IRQ_MFP_ACSI )
-#define DISABLE_IRQ() atari_turnoff_irq( IRQ_MFP_ACSI )
-
-#endif /* _ASM_ATARI_ACSI_H */
diff --git a/include/asm-m68k/fb.h b/include/asm-m68k/fb.h
new file mode 100644
index 000000000000..380b97ae8157
--- /dev/null
+++ b/include/asm-m68k/fb.h
@@ -0,0 +1,34 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_SUN3
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
+}
+#else
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ if (CPU_IS_020_OR_030)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
+ if (CPU_IS_040_OR_060) {
+ pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
+ /* Use no-cache mode, serialized */
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
+ }
+}
+#endif /* CONFIG_SUN3 */
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
index b5b78c01eb6c..d029b75bcf04 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -164,21 +164,15 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return 1; }
static inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_RONLY); }
-static inline int pte_exec(pte_t pte) { return 1; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RONLY; return pte; }
-static inline pte_t pte_rdprotect(pte_t pte) { return pte; }
-static inline pte_t pte_exprotect(pte_t pte) { return pte; }
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_RONLY; return pte; }
-static inline pte_t pte_mkread(pte_t pte) { return pte; }
-static inline pte_t pte_mkexec(pte_t pte) { return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mknocache(pte_t pte)
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
index b9e62c1e7ae3..b766fc261bde 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -165,21 +165,15 @@ static inline void pgd_clear (pgd_t *pgdp) {}
* Undefined behaviour if not...
* [we have the full set here even if they don't change from m68k]
*/
-static inline int pte_read(pte_t pte) { return 1; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & SUN3_PAGE_WRITEABLE; }
-static inline int pte_exec(pte_t pte) { return 1; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & SUN3_PAGE_MODIFIED; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
-static inline pte_t pte_rdprotect(pte_t pte) { return pte; }
-static inline pte_t pte_exprotect(pte_t pte) { return pte; }
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= SUN3_PAGE_WRITEABLE; return pte; }
-static inline pte_t pte_mkread(pte_t pte) { return pte; }
-static inline pte_t pte_mkexec(pte_t pte) { return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= SUN3_PAGE_MODIFIED; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= SUN3_PAGE_ACCESSED; return pte; }
static inline pte_t pte_mknocache(pte_t pte) { pte_val(pte) |= SUN3_PAGE_NOCACHE; return pte; }
diff --git a/include/asm-m68knommu/fb.h b/include/asm-m68knommu/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-m68knommu/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 2a1b8bdcb29c..9efa0a9851b1 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -22,7 +22,8 @@
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 67c3f8ec0303..568c76cdd900 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -37,8 +37,10 @@ typedef s32 compat_key_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-mips/fb.h b/include/asm-mips/fb.h
new file mode 100644
index 000000000000..bd3f68c9ddfc
--- /dev/null
+++ b/include/asm-mips/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 27d77d981937..2e2d70d13ff6 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -178,9 +178,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_user(pte_t pte) { BUG(); return 0; }
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
-static inline int pte_read(pte_t pte) { return pte.pte_low & _PAGE_READ; }
static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; }
static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; }
static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; }
@@ -193,13 +191,6 @@ static inline pte_t pte_wrprotect(pte_t pte)
return pte;
}
-static inline pte_t pte_rdprotect(pte_t pte)
-{
- pte.pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
- pte.pte_high &= ~_PAGE_SILENT_READ;
- return pte;
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte.pte_low &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
@@ -224,16 +215,6 @@ static inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-static inline pte_t pte_mkread(pte_t pte)
-{
- pte.pte_low |= _PAGE_READ;
- if (pte.pte_low & _PAGE_ACCESSED) {
- pte.pte_low |= _PAGE_SILENT_READ;
- pte.pte_high |= _PAGE_SILENT_READ;
- }
- return pte;
-}
-
static inline pte_t pte_mkdirty(pte_t pte)
{
pte.pte_low |= _PAGE_MODIFIED;
@@ -253,7 +234,6 @@ static inline pte_t pte_mkyoung(pte_t pte)
return pte;
}
#else
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
@@ -265,12 +245,6 @@ static inline pte_t pte_wrprotect(pte_t pte)
return pte;
}
-static inline pte_t pte_rdprotect(pte_t pte)
-{
- pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
- return pte;
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
@@ -291,14 +265,6 @@ static inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-static inline pte_t pte_mkread(pte_t pte)
-{
- pte_val(pte) |= _PAGE_READ;
- if (pte_val(pte) & _PAGE_ACCESSED)
- pte_val(pte) |= _PAGE_SILENT_READ;
- return pte;
-}
-
static inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_MODIFIED;
diff --git a/include/asm-mips/sibyte/bcm1480_regs.h b/include/asm-mips/sibyte/bcm1480_regs.h
index bda391d3af85..2738c1366f66 100644
--- a/include/asm-mips/sibyte/bcm1480_regs.h
+++ b/include/asm-mips/sibyte/bcm1480_regs.h
@@ -220,17 +220,25 @@
#define A_BCM1480_DUART(chan) ((((chan)&2) == 0)? A_BCM1480_DUART0 : A_BCM1480_DUART1)
#define BCM1480_DUART_CHANREG_SPACING 0x100
-#define A_BCM1480_DUART_CHANREG(chan,reg) (A_BCM1480_DUART(chan) \
- + BCM1480_DUART_CHANREG_SPACING*((chan)&1) \
- + (reg))
-#define R_BCM1480_DUART_CHANREG(chan,reg) (BCM1480_DUART_CHANREG_SPACING*((chan)&1) + (reg))
-
-#define R_BCM1480_DUART_IMRREG(chan) (R_DUART_IMR_A + ((chan)&1)*DUART_IMRISR_SPACING)
-#define R_BCM1480_DUART_ISRREG(chan) (R_DUART_ISR_A + ((chan)&1)*DUART_IMRISR_SPACING)
-
-#define A_BCM1480_DUART_IMRREG(chan) (A_BCM1480_DUART(chan) + R_BCM1480_DUART_IMRREG(chan))
-#define A_BCM1480_DUART_ISRREG(chan) (A_BCM1480_DUART(chan) + R_BCM1480_DUART_ISRREG(chan))
-#define A_BCM1480_DUART_IN_PORT(chan) (A_BCM1480_DUART(chan) + R_DUART_INP_ORT)
+#define A_BCM1480_DUART_CHANREG(chan, reg) \
+ (A_BCM1480_DUART(chan) + \
+ BCM1480_DUART_CHANREG_SPACING * (((chan) & 1) + 1) + (reg))
+#define A_BCM1480_DUART_CTRLREG(chan, reg) \
+ (A_BCM1480_DUART(chan) + \
+ BCM1480_DUART_CHANREG_SPACING * 3 + (reg))
+
+#define R_BCM1480_DUART_IMRREG(chan) \
+ (R_DUART_IMR_A + ((chan) & 1) * DUART_IMRISR_SPACING)
+#define R_BCM1480_DUART_ISRREG(chan) \
+ (R_DUART_ISR_A + ((chan) & 1) * DUART_IMRISR_SPACING)
+
+#define A_BCM1480_DUART_IMRREG(chan) \
+ (A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_IMRREG(chan)))
+#define A_BCM1480_DUART_ISRREG(chan) \
+ (A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_ISRREG(chan)))
+
+#define A_BCM1480_DUART_IN_PORT(chan) \
+ (A_BCM1480_DUART_CTRLREG((chan), R_DUART_IN_PORT))
/*
* These constants are the absolute addresses.
diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/include/asm-mips/sibyte/sb1250_regs.h
index da7c188993c9..220b7e94f1bf 100644
--- a/include/asm-mips/sibyte/sb1250_regs.h
+++ b/include/asm-mips/sibyte/sb1250_regs.h
@@ -272,59 +272,69 @@
********************************************************************* */
-#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */
+#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */
#define R_DUART_NUM_PORTS 2
#define A_DUART 0x0010060000
#define DUART_CHANREG_SPACING 0x100
-#define A_DUART_CHANREG(chan,reg) (A_DUART + DUART_CHANREG_SPACING*(chan) + (reg))
-#define R_DUART_CHANREG(chan,reg) (DUART_CHANREG_SPACING*(chan) + (reg))
+
+#define A_DUART_CHANREG(chan, reg) \
+ (A_DUART + DUART_CHANREG_SPACING * ((chan) + 1) + (reg))
#endif /* 1250 & 112x */
-#define R_DUART_MODE_REG_1 0x100
-#define R_DUART_MODE_REG_2 0x110
-#define R_DUART_STATUS 0x120
-#define R_DUART_CLK_SEL 0x130
-#define R_DUART_CMD 0x150
-#define R_DUART_RX_HOLD 0x160
-#define R_DUART_TX_HOLD 0x170
+#define R_DUART_MODE_REG_1 0x000
+#define R_DUART_MODE_REG_2 0x010
+#define R_DUART_STATUS 0x020
+#define R_DUART_CLK_SEL 0x030
+#define R_DUART_CMD 0x050
+#define R_DUART_RX_HOLD 0x060
+#define R_DUART_TX_HOLD 0x070
#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
-#define R_DUART_FULL_CTL 0x140
-#define R_DUART_OPCR_X 0x180
-#define R_DUART_AUXCTL_X 0x190
-#endif /* 1250 PASS2 || 112x PASS1 || 1480*/
+#define R_DUART_FULL_CTL 0x040
+#define R_DUART_OPCR_X 0x080
+#define R_DUART_AUXCTL_X 0x090
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
/*
* The IMR and ISR can't be addressed with A_DUART_CHANREG,
- * so use this macro instead.
+ * so use these macros instead.
*/
-#define R_DUART_AUX_CTRL 0x310
-#define R_DUART_ISR_A 0x320
-#define R_DUART_IMR_A 0x330
-#define R_DUART_ISR_B 0x340
-#define R_DUART_IMR_B 0x350
-#define R_DUART_OUT_PORT 0x360
-#define R_DUART_OPCR 0x370
-#define R_DUART_IN_PORT 0x380
+#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */
+#define DUART_IMRISR_SPACING 0x20
+#define DUART_INCHNG_SPACING 0x10
-#define R_DUART_SET_OPR 0x3B0
-#define R_DUART_CLEAR_OPR 0x3C0
+#define A_DUART_CTRLREG(reg) \
+ (A_DUART + DUART_CHANREG_SPACING * 3 + (reg))
-#define DUART_IMRISR_SPACING 0x20
+#define R_DUART_IMRREG(chan) \
+ (R_DUART_IMR_A + (chan) * DUART_IMRISR_SPACING)
+#define R_DUART_ISRREG(chan) \
+ (R_DUART_ISR_A + (chan) * DUART_IMRISR_SPACING)
+#define R_DUART_INCHREG(chan) \
+ (R_DUART_IN_CHNG_A + (chan) * DUART_INCHNG_SPACING)
-#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */
-#define R_DUART_IMRREG(chan) (R_DUART_IMR_A + (chan)*DUART_IMRISR_SPACING)
-#define R_DUART_ISRREG(chan) (R_DUART_ISR_A + (chan)*DUART_IMRISR_SPACING)
-
-#define A_DUART_IMRREG(chan) (A_DUART + R_DUART_IMRREG(chan))
-#define A_DUART_ISRREG(chan) (A_DUART + R_DUART_ISRREG(chan))
+#define A_DUART_IMRREG(chan) A_DUART_CTRLREG(R_DUART_IMRREG(chan))
+#define A_DUART_ISRREG(chan) A_DUART_CTRLREG(R_DUART_ISRREG(chan))
+#define A_DUART_INCHREG(chan) A_DUART_CTRLREG(R_DUART_INCHREG(chan))
#endif /* 1250 & 112x */
-
+#define R_DUART_AUX_CTRL 0x010
+#define R_DUART_ISR_A 0x020
+#define R_DUART_IMR_A 0x030
+#define R_DUART_ISR_B 0x040
+#define R_DUART_IMR_B 0x050
+#define R_DUART_OUT_PORT 0x060
+#define R_DUART_OPCR 0x070
+#define R_DUART_IN_PORT 0x080
+
+#define R_DUART_SET_OPR 0x0B0
+#define R_DUART_CLEAR_OPR 0x0C0
+#define R_DUART_IN_CHNG_A 0x0D0
+#define R_DUART_IN_CHNG_B 0x0E0
/*
diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/include/asm-mips/sibyte/sb1250_uart.h
index e87045e62bf0..cf74fedcbef1 100644
--- a/include/asm-mips/sibyte/sb1250_uart.h
+++ b/include/asm-mips/sibyte/sb1250_uart.h
@@ -75,7 +75,8 @@
#define V_DUART_PARITY_MODE_ADD_FIXED V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD_FIXED)
#define V_DUART_PARITY_MODE_NONE V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_NONE)
-#define M_DUART_ERR_MODE _SB_MAKEMASK1(5) /* must be zero */
+#define M_DUART_TX_IRQ_SEL_TXRDY 0
+#define M_DUART_TX_IRQ_SEL_TXEMPT _SB_MAKEMASK1(5)
#define M_DUART_RX_IRQ_SEL_RXRDY 0
#define M_DUART_RX_IRQ_SEL_RXFULL _SB_MAKEMASK1(6)
@@ -246,10 +247,13 @@
#define M_DUART_ISR_BRK_A _SB_MAKEMASK1(2)
#define M_DUART_ISR_IN_A _SB_MAKEMASK1(3)
+#define M_DUART_ISR_ALL_A _SB_MAKEMASK(4,0)
+
#define M_DUART_ISR_TX_B _SB_MAKEMASK1(4)
#define M_DUART_ISR_RX_B _SB_MAKEMASK1(5)
#define M_DUART_ISR_BRK_B _SB_MAKEMASK1(6)
#define M_DUART_ISR_IN_B _SB_MAKEMASK1(7)
+#define M_DUART_ISR_ALL_B _SB_MAKEMASK(4,4)
/*
* DUART Channel A Interrupt Status Register (Table 10-17)
@@ -262,6 +266,7 @@
#define M_DUART_ISR_RX _SB_MAKEMASK1(1)
#define M_DUART_ISR_BRK _SB_MAKEMASK1(2)
#define M_DUART_ISR_IN _SB_MAKEMASK1(3)
+#define M_DUART_ISR_ALL _SB_MAKEMASK(4,0)
#define M_DUART_ISR_RESERVED _SB_MAKEMASK(4,4)
/*
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 11f4222597a0..5a85d1b025c8 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -31,8 +31,10 @@ typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-parisc/fb.h b/include/asm-parisc/fb.h
new file mode 100644
index 000000000000..4d503a023ab2
--- /dev/null
+++ b/include/asm-parisc/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h
index 317851fa78f3..1e1c824764ee 100644
--- a/include/asm-parisc/fcntl.h
+++ b/include/asm-parisc/fcntl.h
@@ -3,21 +3,22 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_APPEND 00000010
-#define O_BLKSEEK 00000100 /* HPUX only */
-#define O_CREAT 00000400 /* not fcntl */
-#define O_EXCL 00002000 /* not fcntl */
-#define O_LARGEFILE 00004000
-#define O_SYNC 00100000
-#define O_NONBLOCK 00200004 /* HPUX has separate NDELAY & NONBLOCK */
-#define O_NOCTTY 00400000 /* not fcntl */
-#define O_DSYNC 01000000 /* HPUX only */
-#define O_RSYNC 02000000 /* HPUX only */
-#define O_NOATIME 04000000
+#define O_APPEND 000000010
+#define O_BLKSEEK 000000100 /* HPUX only */
+#define O_CREAT 000000400 /* not fcntl */
+#define O_EXCL 000002000 /* not fcntl */
+#define O_LARGEFILE 000004000
+#define O_SYNC 000100000
+#define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */
+#define O_NOCTTY 000400000 /* not fcntl */
+#define O_DSYNC 001000000 /* HPUX only */
+#define O_RSYNC 002000000 /* HPUX only */
+#define O_NOATIME 004000000
+#define O_CLOEXEC 010000000 /* set close_on_exec */
-#define O_DIRECTORY 00010000 /* must be a directory */
-#define O_NOFOLLOW 00000200 /* don't follow links */
-#define O_INVISIBLE 04000000 /* invisible I/O, for DMAPI/XDSM */
+#define O_DIRECTORY 000010000 /* must be a directory */
+#define O_NOFOLLOW 000000200 /* don't follow links */
+#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */
#define F_GETLK64 8
#define F_SETLK64 9
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index beb2adb979d9..e88cacd63724 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -335,18 +335,14 @@ extern inline void pgd_clear(pgd_t * pgdp) { }
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-extern inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_READ; return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; return pte; }
extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
@@ -451,21 +447,6 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
#endif
}
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- if (!pte_dirty(*ptep))
- return 0;
- return test_and_clear_bit(xlate_pabit(_PAGE_DIRTY_BIT), &pte_val(*ptep));
-#else
- pte_t pte = *ptep;
- if (!pte_dirty(pte))
- return 0;
- set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
- return 1;
-#endif
-}
-
extern spinlock_t pa_dbit_lock;
struct mm_struct;
@@ -533,7 +514,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#define HAVE_ARCH_UNMAPPED_AREA
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTE_SAME
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
index 642be62cf393..53507046a1b1 100644
--- a/include/asm-powerpc/cache.h
+++ b/include/asm-powerpc/cache.h
@@ -34,5 +34,9 @@ struct ppc64_caches {
extern struct ppc64_caches ppc64_caches;
#endif /* __powerpc64__ && ! __ASSEMBLY__ */
+#if !defined(__ASSEMBLY__)
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#endif
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_CACHE_H */
diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h
index aacaabd28ac1..64ab1ddbdf85 100644
--- a/include/asm-powerpc/compat.h
+++ b/include/asm-powerpc/compat.h
@@ -33,8 +33,10 @@ typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 82d595a52109..3dc8e2dfca84 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -111,7 +111,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
/* CPU kernel features */
/* Retain the 32b definitions all use bottom half of word */
-#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001)
+#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000000000000001)
#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002)
#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004)
#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008)
@@ -135,6 +135,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000)
#define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000)
#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000)
+#define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000)
/*
* Add the 64-bit processor unique features in the top half of the word;
@@ -154,7 +155,6 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000)
#define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000)
#define CPU_FTR_SMT LONG_ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE LONG_ASM_CONST(0x0000020000000000)
#define CPU_FTR_LOCKLESS_TLBIE LONG_ASM_CONST(0x0000040000000000)
#define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000)
#define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000)
@@ -206,164 +206,149 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
!defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
!defined(CONFIG_BOOKE))
-#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_603 (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_604 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
CPU_FTR_PPC_LE)
-#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_740 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740 (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
CPU_FTR_PPC_LE)
-#define CPU_FTRS_750 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750 (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
CPU_FTR_PPC_LE)
-#define CPU_FTRS_750CL (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX2 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750GX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750CL (CPU_FTRS_750 | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750FX1 (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX2 (CPU_FTRS_750 | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \
+ CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750GX (CPU_FTRS_750FX)
+#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7400 (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447A (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7448 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7448 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_PPC_LE)
-#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_82XX (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
-#define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_G2_LE (CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
-#define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_COMMON)
-#define CPU_FTRS_E300C2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300C2 (CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
-#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
-#define CPU_FTRS_40X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_44X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_8XX (CPU_FTR_USE_TB)
+#define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500_2 (CPU_FTR_USE_TB | \
CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
/* 64-bit CPUs */
-#define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER3 (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
CPU_FTR_MMCRA | CPU_FTR_CTRL)
-#define CPU_FTRS_POWER4 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA)
-#define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
-#define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR)
-#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
CPU_FTR_DSCR)
-#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_CELL (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
-#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
CPU_FTR_PURR | CPU_FTR_REAL_LE)
-#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
#ifdef __powerpc64__
diff --git a/include/asm-powerpc/fb.h b/include/asm-powerpc/fb.h
new file mode 100644
index 000000000000..411af8d17a69
--- /dev/null
+++ b/include/asm-powerpc/fb.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index afa700ded877..34146f0eea63 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -29,7 +29,7 @@
#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
#include <linux/pci.h>
-#include <asm/ppc-pci.h> /* for ppc64_isabridge_dev */
+#include <asm/ppc-pci.h> /* for isa_bridge_pcidev */
#define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
@@ -139,12 +139,12 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
if (bus_addr
&& (addr != prev_addr || size != prev_size || dir != prev_dir)) {
/* different from last time -- unmap prev */
- pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
+ pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
bus_addr = 0;
}
if (!bus_addr) /* need to map it */
- bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
+ bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
/* remember this one as prev */
prev_addr = addr;
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 62efd9d7a43d..bf6cd7cb996c 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -206,6 +206,7 @@
#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
#define H_QUERY_INT_STATE 0x1E4
#define H_POLL_PENDING 0x1D8
+#define H_ILLAN_ATTRIBUTES 0x244
#define H_JOIN 0x298
#define H_VASI_STATE 0x2A4
#define H_ENABLE_CRQ 0x2B0
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 350c9bdb31dc..bb8d965f96c6 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -607,9 +607,9 @@ static inline void iosync(void)
*
* * iounmap undoes such a mapping and can be hooked
*
- * * __ioremap_explicit (and the pending __iounmap_explicit) are low level
- * functions to create hand-made mappings for use only by the PCI code
- * and cannot currently be hooked.
+ * * __ioremap_at (and the pending __iounmap_at) are low level functions to
+ * create hand-made mappings for use only by the PCI code and cannot
+ * currently be hooked. Must be page aligned.
*
* * __ioremap is the low level implementation used by ioremap and
* ioremap_flags and cannot be hooked (but can be used by a hook on one
@@ -629,19 +629,9 @@ extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
unsigned long flags);
extern void __iounmap(volatile void __iomem *addr);
-extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr,
- unsigned long size, unsigned long flags);
-extern int __iounmap_explicit(volatile void __iomem *start,
- unsigned long size);
-
-extern void __iomem * reserve_phb_iospace(unsigned long size);
-
-/* Those are more 32 bits only functions */
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
- unsigned int size, int flags);
-
+extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
+ unsigned long size, unsigned long flags);
+extern void __iounmap_at(void *ea, unsigned long size);
/*
* When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
@@ -651,8 +641,8 @@ extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
*/
#define HAVE_ARCH_PIO_SIZE 1
#define PIO_OFFSET 0x00000000UL
-#define PIO_MASK 0x3fffffffUL
-#define PIO_RESERVED 0x40000000UL
+#define PIO_MASK (FULL_IO_SIZE - 1)
+#define PIO_RESERVED (FULL_IO_SIZE)
#define mmio_read16be(addr) readw_be(addr)
#define mmio_read32be(addr) readl_be(addr)
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 05dd5a3eb3aa..0485c53db2b5 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -223,6 +223,15 @@ extern void irq_dispose_mapping(unsigned int virq);
extern unsigned int irq_find_mapping(struct irq_host *host,
irq_hw_number_t hwirq);
+/**
+ * irq_create_direct_mapping - Allocate a virq for direct mapping
+ * @host: host to allocate the virq for or NULL for default host
+ *
+ * This routine is used for irq controllers which can choose the hardware
+ * interrupt numbers they generate. In such a case it's simplest to use
+ * the linux virq as the hardware interrupt number.
+ */
+extern unsigned int irq_create_direct_mapping(struct irq_host *host);
/**
* irq_radix_revmap - Find a linux virq from a hw irq number.
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index b0e40ff32ee0..9537fda238b8 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -65,10 +65,10 @@ typedef unsigned int kprobe_opcode_t;
} else if (name[0] != '.') \
addr = *(kprobe_opcode_t **)addr; \
} else { \
- char dot_name[KSYM_NAME_LEN+1]; \
+ char dot_name[KSYM_NAME_LEN]; \
dot_name[0] = '.'; \
dot_name[1] = '\0'; \
- strncat(dot_name, name, KSYM_NAME_LEN); \
+ strncat(dot_name, name, KSYM_NAME_LEN - 2); \
addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
} \
}
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h
index 821ea0c512b4..567ed92cd91f 100644
--- a/include/asm-powerpc/lppaca.h
+++ b/include/asm-powerpc/lppaca.h
@@ -98,7 +98,7 @@ struct lppaca {
u64 saved_gpr5; // Saved GPR5 x30-x37
u8 reserved4; // Reserved x38-x38
- u8 cpuctls_task_attrs; // Task attributes for cpuctls x39-x39
+ u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39
u8 fpregs_in_use; // FP regs in use x3A-x3A
u8 pmcregs_in_use; // PMC regs in use x3B-x3B
volatile u32 saved_decr; // Saved Decr Value x3C-x3F
diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h
index f733beeea63a..81713acf7529 100644
--- a/include/asm-powerpc/lv1call.h
+++ b/include/asm-powerpc/lv1call.h
@@ -238,6 +238,7 @@ LV1_CALL(destruct_virtual_address_space, 1, 0, 10 )
LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 )
LV1_CALL(connect_irq_plug_ext, 5, 0, 12 )
LV1_CALL(release_memory, 1, 0, 13 )
+LV1_CALL(put_iopte, 5, 0, 15 )
LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 )
LV1_CALL(construct_event_receive_port, 0, 1, 18 )
LV1_CALL(destruct_event_receive_port, 1, 0, 19 )
@@ -268,6 +269,8 @@ LV1_CALL(remove_repository_node, 4, 0, 93 )
LV1_CALL(read_htab_entries, 2, 5, 95 )
LV1_CALL(set_dabr, 2, 0, 96 )
LV1_CALL(get_total_execution_time, 2, 1, 103 )
+LV1_CALL(allocate_io_segment, 3, 1, 116 )
+LV1_CALL(release_io_segment, 2, 0, 117 )
LV1_CALL(construct_io_irq_outlet, 1, 1, 120 )
LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 )
LV1_CALL(map_htab, 1, 1, 122 )
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 6cf1a831f550..71c6e7eb2a26 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -218,7 +218,7 @@ struct machdep_calls {
int (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
/* Called in indirect_* to avoid touching devices */
- int (*pci_exclude_device)(unsigned char, unsigned char);
+ int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
/* Called at then very end of pcibios_init() */
void (*pcibios_after_init)(void);
diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h
new file mode 100644
index 000000000000..952bd8899f2f
--- /dev/null
+++ b/include/asm-powerpc/mmu-8xx.h
@@ -0,0 +1,147 @@
+#ifndef _ASM_POWERPC_MMU_8XX_H_
+#define _ASM_POWERPC_MMU_8XX_H_
+/*
+ * PPC8xx support
+ */
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read. A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define SPRN_MI_CTR 784 /* Instruction TLB control register */
+#define MI_GPM 0x80000000 /* Set domain manager mode */
+#define MI_PPM 0x40000000 /* Set subpage protection */
+#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */
+#define MI_RESETVAL 0x00000000 /* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books. For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MI_AP 786
+#define MI_Ks 0x80000000 /* Should not be set */
+#define MI_Kp 0x40000000 /* Should always be set */
+
+/* The effective page number register. When read, contains the information
+ * about the last instruction TLB miss. When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MI_EPN 787
+#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */
+#define MI_EVALID 0x00000200 /* Entry is valid */
+#define MI_ASIDMASK 0x0000000f /* ASID match value */
+ /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define SPRN_MI_TWC 789
+#define MI_APG 0x000001e0 /* Access protection group (0) */
+#define MI_GUARDED 0x00000010 /* Guarded storage */
+#define MI_PSMASK 0x0000000c /* Mask of page size bits */
+#define MI_PS8MEG 0x0000000c /* 8M page size */
+#define MI_PS512K 0x00000004 /* 512K page size */
+#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */
+#define MI_SVALID 0x00000001 /* Segment entry is valid */
+ /* Reset value is undefined */
+
+/* Real page number. Defined by the pte. Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define SPRN_MI_RPN 790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization. This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT 0x000001fd
+
+#define SPRN_MD_CTR 792 /* Data TLB control register */
+#define MD_GPM 0x80000000 /* Set domain manager mode */
+#define MD_PPM 0x40000000 /* Set subpage protection */
+#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */
+#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */
+#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */
+#define MD_RESETVAL 0x04000000 /* Value of register at reset */
+
+#define SPRN_M_CASID 793 /* Address space ID (context) to match */
+#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books. For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MD_AP 794
+#define MD_Ks 0x80000000 /* Should not be set */
+#define MD_Kp 0x40000000 /* Should always be set */
+
+/* The effective page number register. When read, contains the information
+ * about the last instruction TLB miss. When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MD_EPN 795
+#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */
+#define MD_EVALID 0x00000200 /* Entry is valid */
+#define MD_ASIDMASK 0x0000000f /* ASID match value */
+ /* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define SPRN_M_TWB 796
+#define M_L1TB 0xfffff000 /* Level 1 table base address */
+#define M_L1INDX 0x00000ffc /* Level 1 index, when read */
+ /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written. It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define SPRN_MD_TWC 797
+#define MD_L2TB 0xfffff000 /* Level 2 table base address */
+#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */
+#define MD_APG 0x000001e0 /* Access protection group (0) */
+#define MD_GUARDED 0x00000010 /* Guarded storage */
+#define MD_PSMASK 0x0000000c /* Mask of page size bits */
+#define MD_PS8MEG 0x0000000c /* 8M page size */
+#define MD_PS512K 0x00000004 /* 512K page size */
+#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */
+#define MD_WT 0x00000002 /* Use writethrough page attribute */
+#define MD_SVALID 0x00000001 /* Segment entry is valid */
+ /* Reset value is undefined */
+
+
+/* Real page number. Defined by the pte. Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define SPRN_MD_RPN 798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define SPRN_M_TW 799
+
+#ifndef __ASSEMBLY__
+typedef unsigned long phys_addr_t;
+
+typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_8XX_H_ */
diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h
new file mode 100644
index 000000000000..37580004cd7a
--- /dev/null
+++ b/include/asm-powerpc/mmu-fsl-booke.h
@@ -0,0 +1,88 @@
+#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_
+#define _ASM_POWERPC_MMU_FSL_BOOKE_H_
+/*
+ * Freescale Book-E MMU support
+ */
+
+/* Book-E defined page sizes */
+#define BOOKE_PAGESZ_1K 0
+#define BOOKE_PAGESZ_4K 1
+#define BOOKE_PAGESZ_16K 2
+#define BOOKE_PAGESZ_64K 3
+#define BOOKE_PAGESZ_256K 4
+#define BOOKE_PAGESZ_1M 5
+#define BOOKE_PAGESZ_4M 6
+#define BOOKE_PAGESZ_16M 7
+#define BOOKE_PAGESZ_64M 8
+#define BOOKE_PAGESZ_256M 9
+#define BOOKE_PAGESZ_1GB 10
+#define BOOKE_PAGESZ_4GB 11
+#define BOOKE_PAGESZ_16GB 12
+#define BOOKE_PAGESZ_64GB 13
+#define BOOKE_PAGESZ_256GB 14
+#define BOOKE_PAGESZ_1TB 15
+
+#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000)
+#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000)
+#define MAS0_NV(x) ((x) & 0x00000FFF)
+
+#define MAS1_VALID 0x80000000
+#define MAS1_IPROT 0x40000000
+#define MAS1_TID(x) ((x << 16) & 0x3FFF0000)
+#define MAS1_TS 0x00001000
+#define MAS1_TSIZE(x) ((x << 8) & 0x00000F00)
+
+#define MAS2_EPN 0xFFFFF000
+#define MAS2_X0 0x00000040
+#define MAS2_X1 0x00000020
+#define MAS2_W 0x00000010
+#define MAS2_I 0x00000008
+#define MAS2_M 0x00000004
+#define MAS2_G 0x00000002
+#define MAS2_E 0x00000001
+
+#define MAS3_RPN 0xFFFFF000
+#define MAS3_U0 0x00000200
+#define MAS3_U1 0x00000100
+#define MAS3_U2 0x00000080
+#define MAS3_U3 0x00000040
+#define MAS3_UX 0x00000020
+#define MAS3_SX 0x00000010
+#define MAS3_UW 0x00000008
+#define MAS3_SW 0x00000004
+#define MAS3_UR 0x00000002
+#define MAS3_SR 0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL 0x000F0000
+#define MAS4_TSIZED(x) MAS1_TSIZE(x)
+#define MAS4_X0D 0x00000040
+#define MAS4_X1D 0x00000020
+#define MAS4_WD 0x00000010
+#define MAS4_ID 0x00000008
+#define MAS4_MD 0x00000004
+#define MAS4_GD 0x00000002
+#define MAS4_ED 0x00000001
+
+#define MAS6_SPID0 0x3FFF0000
+#define MAS6_SPID1 0x00007FFE
+#define MAS6_SAS 0x00000001
+#define MAS6_SPID MAS6_SPID0
+
+#define MAS7_RPN 0xFFFFFFFF
+
+#ifndef __ASSEMBLY__
+
+#ifndef CONFIG_PHYS_64BIT
+typedef unsigned long phys_addr_t;
+#else
+typedef unsigned long long phys_addr_t;
+#endif
+
+typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */
diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h
new file mode 100644
index 000000000000..4bd735be3833
--- /dev/null
+++ b/include/asm-powerpc/mmu-hash32.h
@@ -0,0 +1,91 @@
+#ifndef _ASM_POWERPC_MMU_HASH32_H_
+#define _ASM_POWERPC_MMU_HASH32_H_
+/*
+ * 32-bit hash table MMU support
+ */
+
+/*
+ * BATs
+ */
+
+/* Block size masks */
+#define BL_128K 0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M 0x007
+#define BL_2M 0x00F
+#define BL_4M 0x01F
+#define BL_8M 0x03F
+#define BL_16M 0x07F
+#define BL_32M 0x0FF
+#define BL_64M 0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX 0x00 /* No access */
+#define BPP_RX 0x01 /* Read only */
+#define BPP_RW 0x02 /* Read/write */
+
+#ifndef __ASSEMBLY__
+struct ppc_bat {
+ struct {
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+ } batu; /* Upper register */
+ struct {
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+ } batl; /* Lower register */
+};
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * Hash table
+ */
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX 0 /* Supervisor read/write, User none */
+#define PP_RWRX 1 /* Supervisor read/write, User read */
+#define PP_RWRW 2 /* Supervisor read/write, User read/write */
+#define PP_RXRX 3 /* Supervisor read, User read */
+
+#ifndef __ASSEMBLY__
+
+/* Hardware Page Table Entry */
+struct hash_pte {
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+ unsigned long rpn:20; /* Real (physical) page number */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+};
+
+typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+} mm_context_t;
+
+typedef unsigned long phys_addr_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
index b8dca30bd0b5..695962f02059 100644
--- a/include/asm-powerpc/mmu-hash64.h
+++ b/include/asm-powerpc/mmu-hash64.h
@@ -94,6 +94,9 @@ extern char initial_stab[];
#define HPTE_R_C ASM_CONST(0x0000000000000080)
#define HPTE_R_R ASM_CONST(0x0000000000000100)
+#define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000)
+#define HPTE_V_VRMA_MASK ASM_CONST(0x4001ffffff000000)
+
/* Values for PP (assumes Ks=0, Kp=1) */
/* pp0 will always be 0 for linux */
#define PP_RWXX 0 /* Supervisor read/write, User none */
@@ -103,12 +106,12 @@ extern char initial_stab[];
#ifndef __ASSEMBLY__
-typedef struct {
+struct hash_pte {
unsigned long v;
unsigned long r;
-} hpte_t;
+};
-extern hpte_t *htab_address;
+extern struct hash_pte *htab_address;
extern unsigned long htab_size_bytes;
extern unsigned long htab_hash_mask;
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index fe510fff8907..d44d211e7588 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -5,13 +5,18 @@
#ifdef CONFIG_PPC64
/* 64-bit classic hash table MMU */
# include <asm/mmu-hash64.h>
+#elif defined(CONFIG_PPC_STD_MMU)
+/* 32-bit classic hash table MMU */
+# include <asm/mmu-hash32.h>
#elif defined(CONFIG_44x)
/* 44x-style software loaded TLB */
# include <asm/mmu-44x.h>
-#else
-/* Other 32-bit. FIXME: split up the other 32-bit MMU types, and
- * revise for arch/powerpc */
-# include <asm-ppc/mmu.h>
+#elif defined(CONFIG_FSL_BOOKE)
+/* Freescale Book-E software loaded TLB */
+# include <asm/mmu-fsl-booke.h>
+#elif defined (CONFIG_PPC_8xx)
+/* Motorola/Freescale 8xx software loaded TLB */
+# include <asm/mmu-8xx.h>
#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
index 40c9e5a13ff1..f863ac21409e 100644
--- a/include/asm-powerpc/mmu_context.h
+++ b/include/asm-powerpc/mmu_context.h
@@ -2,16 +2,210 @@
#define __ASM_POWERPC_MMU_CONTEXT_H
#ifdef __KERNEL__
+#include <asm/mmu.h>
+#include <asm/cputable.h>
+#include <asm-generic/mm_hooks.h>
+
#ifndef CONFIG_PPC64
-#include <asm-ppc/mmu_context.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+
+/*
+ * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
+ * (virtual segment identifiers) for each context. Although the
+ * hardware supports 24-bit VSIDs, and thus >1 million contexts,
+ * we only use 32,768 of them. That is ample, since there can be
+ * at most around 30,000 tasks in the system anyway, and it means
+ * that we can use a bitmap to indicate which contexts are in use.
+ * Using a bitmap means that we entirely avoid all of the problems
+ * that we used to have when the context number overflowed,
+ * particularly on SMP systems.
+ * -- paulus.
+ */
+
+/*
+ * This function defines the mapping from contexts to VSIDs (virtual
+ * segment IDs). We use a skew on both the context and the high 4 bits
+ * of the 32-bit virtual address (the "effective segment ID") in order
+ * to spread out the entries in the MMU hash table. Note, if this
+ * function is changed then arch/ppc/mm/hashtable.S will have to be
+ * changed to correspond.
+ */
+#define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
+ & 0xffffff)
+
+/*
+ The MPC8xx has only 16 contexts. We rotate through them on each
+ task switch. A better way would be to keep track of tasks that
+ own contexts, and implement an LRU usage. That way very active
+ tasks don't always have to pay the TLB reload overhead. The
+ kernel pages are mapped shared, so the kernel can run on behalf
+ of any task that makes a kernel entry. Shared does not mean they
+ are not protected, just that the ASID comparison is not performed.
+ -- Dan
+
+ The IBM4xx has 256 contexts, so we can just rotate through these
+ as a way of "switching" contexts. If the TID of the TLB is zero,
+ the PID/TID comparison is disabled, so we can use a TID of zero
+ to represent all kernel pages as shared among all contexts.
+ -- Dan
+ */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#ifdef CONFIG_8xx
+#define NO_CONTEXT 16
+#define LAST_CONTEXT 15
+#define FIRST_CONTEXT 0
+
+#elif defined(CONFIG_4xx)
+#define NO_CONTEXT 256
+#define LAST_CONTEXT 255
+#define FIRST_CONTEXT 1
+
+#elif defined(CONFIG_E200) || defined(CONFIG_E500)
+#define NO_CONTEXT 256
+#define LAST_CONTEXT 255
+#define FIRST_CONTEXT 1
+
+#else
+
+/* PPC 6xx, 7xx CPUs */
+#define NO_CONTEXT ((unsigned long) -1)
+#define LAST_CONTEXT 32767
+#define FIRST_CONTEXT 1
+#endif
+
+/*
+ * Set the current MMU context.
+ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by
+ * loading up the segment registers for the user part of the address space.
+ *
+ * Since the PGD is immediately available, it is much faster to simply
+ * pass this along as a second parameter, which is required for 8xx and
+ * can be used for debugging on all processors (if you happen to have
+ * an Abatron).
+ */
+extern void set_context(unsigned long contextid, pgd_t *pgd);
+
+/*
+ * Bitmap of contexts in use.
+ * The size of this bitmap is LAST_CONTEXT + 1 bits.
+ */
+extern unsigned long context_map[];
+
+/*
+ * This caches the next context number that we expect to be free.
+ * Its use is an optimization only, we can't rely on this context
+ * number to be free, but it usually will be.
+ */
+extern unsigned long next_mmu_context;
+
+/*
+ * If we don't have sufficient contexts to give one to every task
+ * that could be in the system, we need to be able to steal contexts.
+ * These variables support that.
+ */
+#if LAST_CONTEXT < 30000
+#define FEW_CONTEXTS 1
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+#endif
+
+/*
+ * Get a new mmu context for the address space described by `mm'.
+ */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+ unsigned long ctx;
+
+ if (mm->context.id != NO_CONTEXT)
+ return;
+#ifdef FEW_CONTEXTS
+ while (atomic_dec_if_positive(&nr_free_contexts) < 0)
+ steal_context();
+#endif
+ ctx = next_mmu_context;
+ while (test_and_set_bit(ctx, context_map)) {
+ ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+ if (ctx > LAST_CONTEXT)
+ ctx = 0;
+ }
+ next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+ mm->context.id = ctx;
+#ifdef FEW_CONTEXTS
+ context_mm[ctx] = mm;
+#endif
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+static inline int init_new_context(struct task_struct *t, struct mm_struct *mm)
+{
+ mm->context.id = NO_CONTEXT;
+ mm->context.vdso_base = 0;
+ return 0;
+}
+
+/*
+ * We're finished using the context for an address space.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+ preempt_disable();
+ if (mm->context.id != NO_CONTEXT) {
+ clear_bit(mm->context.id, context_map);
+ mm->context.id = NO_CONTEXT;
+#ifdef FEW_CONTEXTS
+ atomic_inc(&nr_free_contexts);
+#endif
+ }
+ preempt_enable();
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
+{
+#ifdef CONFIG_ALTIVEC
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ asm volatile ("dssall;\n"
+#ifndef CONFIG_POWER4
+ "sync;\n" /* G4 needs a sync here, G5 apparently not */
+#endif
+ : : );
+#endif /* CONFIG_ALTIVEC */
+
+ tsk->thread.pgdir = next->pgd;
+
+ /* No need to flush userspace segments if the mm doesnt change */
+ if (prev == next)
+ return;
+
+ /* Setup new userspace context */
+ get_mmu_context(next);
+ set_context(next->context.id, next->pgd);
+}
+
+#define deactivate_mm(tsk,mm) do { } while (0)
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, current)
+
+extern void mmu_context_init(void);
+
+
#else
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
-#include <asm/mmu.h>
-#include <asm/cputable.h>
-#include <asm-generic/mm_hooks.h>
/*
* Copyright (C) 2001 PPC 64 Team, IBM Corp
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
index b85df45b1a84..15f650f987e7 100644
--- a/include/asm-powerpc/mpc86xx.h
+++ b/include/asm-powerpc/mpc86xx.h
@@ -19,12 +19,6 @@
#ifdef CONFIG_PPC_86xx
-#define _IO_BASE isa_io_base
-#define _ISA_MEM_BASE isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#endif
-
#define CPU0_BOOT_RELEASE 0x01000000
#define CPU1_BOOT_RELEASE 0x02000000
#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
diff --git a/include/asm-powerpc/mpc8xx.h b/include/asm-powerpc/mpc8xx.h
index 580371120e1a..2be014b6f57c 100644
--- a/include/asm-powerpc/mpc8xx.h
+++ b/include/asm-powerpc/mpc8xx.h
@@ -23,6 +23,10 @@
#include <platforms/8xx/mpc885ads.h>
#endif
+#ifdef CONFIG_PCMCIA_M8XX
+extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
#endif /* CONFIG_8xx */
#endif /* __CONFIG_8xx_DEFS */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index d9bf5aba96cb..e72c2a60853c 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -2,12 +2,91 @@
#define _ASM_POWERPC_PCI_BRIDGE_H
#ifdef __KERNEL__
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+
#ifndef CONFIG_PPC64
-#include <asm-ppc/pci-bridge.h>
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+ struct pci_bus *bus;
+ char is_dynamic;
+ void *arch_data;
+ struct list_head list_node;
+ struct device *parent;
+
+ int first_busno;
+ int last_busno;
+ int self_busno;
+
+ void __iomem *io_base_virt;
+ resource_size_t io_base_phys;
+
+ /* Some machines (PReP) have a non 1:1 mapping of
+ * the PCI memory space in the CPU bus space
+ */
+ resource_size_t pci_mem_offset;
+
+ struct pci_ops *ops;
+ volatile unsigned int __iomem *cfg_addr;
+ volatile void __iomem *cfg_data;
+
+ /*
+ * Used for variants of PCI indirect handling and possible quirks:
+ * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
+ * EXT_REG - provides access to PCI-e extended registers
+ * SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS
+ * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
+ * to determine which bus number to match on when generating type0
+ * config cycles
+ */
+#define PPC_INDIRECT_TYPE_SET_CFG_TYPE (0x00000001)
+#define PPC_INDIRECT_TYPE_EXT_REG (0x00000002)
+#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS (0x00000004)
+ u32 indirect_type;
+
+ /* Currently, we limit ourselves to 1 IO range and 3 mem
+ * ranges since the common pci_bus structure can't handle more
+ */
+ struct resource io_resource;
+ struct resource mem_resources[3];
+ int global_number; /* PCI domain number */
+};
+
+static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
+{
+ return bus->sysdata;
+}
+
+/* These are used for config access before all the PCI probing
+ has been done. */
+int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+ int where, u8 *val);
+int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn,
+ int where, u16 *val);
+int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+ int where, u32 *val);
+int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+ int where, u8 val);
+int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn,
+ int where, u16 val);
+int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+ int where, u32 val);
+
+extern void setup_indirect_pci_nomap(struct pci_controller* hose,
+ void __iomem *cfg_addr, void __iomem *cfg_data);
+extern void setup_indirect_pci(struct pci_controller* hose,
+ u32 cfg_addr, u32 cfg_data);
+extern void setup_grackle(struct pci_controller *hose);
+
#else
-#include <linux/pci.h>
-#include <linux/list.h>
/*
* This program is free software; you can redistribute it and/or
@@ -31,6 +110,7 @@ struct pci_controller {
int last_busno;
void __iomem *io_base_virt;
+ void *io_base_alloc;
resource_size_t io_base_phys;
/* Some machines have a non 1:1 mapping of
@@ -48,8 +128,7 @@ struct pci_controller {
*/
struct resource io_resource;
struct resource mem_resources[3];
- int global_number;
- int local_number;
+ int global_number;
unsigned long buid;
unsigned long dma_window_base_cur;
unsigned long dma_window_size;
@@ -70,19 +149,22 @@ struct pci_dn {
int devfn; /* pci device and function number */
int class_code; /* pci device class */
-#ifdef CONFIG_PPC_PSERIES
+ struct pci_controller *phb; /* for pci devices */
+ struct iommu_table *iommu_table; /* for phb's or bridges */
+ struct pci_dev *pcidev; /* back-pointer to the pci device */
+ struct device_node *node; /* back-pointer to the device_node */
+
+ int pci_ext_config_space; /* for pci devices */
+
+#ifdef CONFIG_EEH
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
int eeh_config_addr;
int eeh_pe_config_addr; /* new-style partition endpoint address */
int eeh_check_count; /* # times driver ignored error */
int eeh_freeze_count; /* # times this device froze up. */
-#endif
- int pci_ext_config_space; /* for pci devices */
- struct pci_controller *phb; /* for pci devices */
- struct iommu_table *iommu_table; /* for phb's or bridges */
- struct pci_dev *pcidev; /* back-pointer to the pci device */
- struct device_node *node; /* back-pointer to the device_node */
+ int eeh_false_positives; /* # times this device reported #ff's */
u32 config_space[16]; /* saved PCI config space */
+#endif
};
/* Get the pointer to a device_node's pci_dn */
@@ -128,9 +210,6 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
/** Find the bus corresponding to the indicated device node */
struct pci_bus * pcibios_find_pci_bus(struct device_node *dn);
-extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int primary);
-
/** Remove all of the PCI devices under this bus */
void pcibios_remove_pci_devices(struct pci_bus *bus);
@@ -148,13 +227,38 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
return PCI_DN(busdn)->phb;
}
+extern void pcibios_free_controller(struct pci_controller *phb);
+
+extern void isa_bridge_find_early(struct pci_controller *hose);
+
+extern int pcibios_unmap_io_space(struct pci_bus *bus);
+extern int pcibios_map_io_space(struct pci_bus *bus);
+
+/* Return values for ppc_md.pci_probe_mode function */
+#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
+#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
+#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */
+
+#ifdef CONFIG_NUMA
+#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE))
+#else
+#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1)
+#endif
+
+#endif /* CONFIG_PPC64 */
+
+/* Get the PCI host controller for an OF device */
extern struct pci_controller*
pci_find_hose_for_OF_device(struct device_node* node);
+/* Fill up host controller resources from the OF node */
+extern void
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+ struct device_node *dev, int primary);
+
+/* Allocate a new PCI host bridge structure */
extern struct pci_controller *
pcibios_alloc_controller(struct device_node *dev);
-extern void pcibios_free_controller(struct pci_controller *phb);
-
#ifdef CONFIG_PCI
extern unsigned long pci_address_to_pio(phys_addr_t address);
#else
@@ -164,17 +268,7 @@ static inline unsigned long pci_address_to_pio(phys_addr_t address)
}
#endif
-/* Return values for ppc_md.pci_probe_mode function */
-#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
-#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
-#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */
-#ifdef CONFIG_NUMA
-#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE))
-#else
-#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1)
-#endif
-#endif /* CONFIG_PPC64 */
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index e16e7bc9ab5c..7b11765c6865 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -95,8 +95,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
#define get_pci_dma_ops() NULL
#endif
-extern int pci_domain_nr(struct pci_bus *bus);
-
/* Decide whether to display the domain number in /proc */
extern int pci_proc_domain(struct pci_bus *bus);
@@ -112,9 +110,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
-/* Return the index of the PCI controller for device PDEV. */
-#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-
/* Set the name of the bus as it appears in /proc/bus/pci */
static inline int pci_proc_domain(struct pci_bus *bus)
{
@@ -123,6 +118,8 @@ static inline int pci_proc_domain(struct pci_bus *bus)
#endif /* CONFIG_PPC64 */
+extern int pci_domain_nr(struct pci_bus *bus);
+
struct vm_area_struct;
/* Map a range of PCI memory or I/O space for a device into user space */
int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
@@ -202,10 +199,6 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
return root;
}
-extern int unmap_bus_range(struct pci_bus *bus);
-
-extern int remap_bus_range(struct pci_bus *bus);
-
extern void pcibios_fixup_device_resources(struct pci_dev *dev,
struct pci_bus *bus);
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index 7fb730c62f83..86a54a4a8a2a 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -6,11 +6,7 @@
#ifndef __ASSEMBLY__
#include <linux/sched.h>
#include <linux/threads.h>
-#include <asm/processor.h> /* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
#include <asm/io.h> /* For sub-arch specific PPC_PIN_SIZE */
-struct mm_struct;
extern unsigned long va_to_phys(unsigned long address);
extern pte_t *va_to_pte(unsigned long address);
@@ -488,14 +484,6 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
#define pfn_pte(pfn, prot) __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
pgprot_val(prot))
#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[1024];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-
#endif /* __ASSEMBLY__ */
#define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
@@ -512,9 +500,7 @@ extern unsigned long empty_zero_page[1024];
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
@@ -522,21 +508,13 @@ static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
-static inline pte_t pte_rdprotect(pte_t pte) {
- pte_val(pte) &= ~_PAGE_USER; return pte; }
static inline pte_t pte_wrprotect(pte_t pte) {
pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
- pte_val(pte) &= ~_PAGE_EXEC; return pte; }
static inline pte_t pte_mkclean(pte_t pte) {
pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
static inline pte_t pte_mkold(pte_t pte) {
pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) {
- pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
- pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) {
pte_val(pte) |= _PAGE_RW; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) {
@@ -643,13 +621,6 @@ static inline int __ptep_test_and_clear_young(unsigned int context, unsigned lon
#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
- unsigned long addr, pte_t *ptep)
-{
- return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
-}
-
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
@@ -734,10 +705,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-extern void paging_init(void);
-
/*
* Encode and decode a swap entry.
* Note that the bits we use in a PTE for representing a swap entry
@@ -755,40 +722,6 @@ extern void paging_init(void);
#define pte_to_pgoff(pte) (pte_val(pte) >> 3)
#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE })
-/* CONFIG_APUS */
-/* For virtual address to physical address conversion */
-extern void cache_clear(__u32 addr, int length);
-extern void cache_push(__u32 addr, int length);
-extern int mm_end_of_chunk (unsigned long addr, int len);
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-
-/* Values for nocacheflag and cmode */
-/* These are not used by the APUS kernel_map, but prevents
- compilation errors. */
-#define KERNELMAP_FULL_CACHING 0
-#define KERNELMAP_NOCACHE_SER 1
-#define KERNELMAP_NOCACHE_NONSER 2
-#define KERNELMAP_NO_COPYBACK 3
-
-/*
- * Map some physical address range into the kernel address space.
- */
-extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
- int nocacheflag, unsigned long *memavailp );
-
-/*
- * Set cache mode of (kernel space) address range.
- */
-extern void kernel_set_cachemode (unsigned long address, unsigned long size,
- unsigned int cmode);
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr) (1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
- remap_pfn_range(vma, vaddr, pfn, size, prot)
-
/*
* No page table caches to initialise
*/
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 3cfd98f44bfe..300f9a199bf2 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -7,11 +7,7 @@
#ifndef __ASSEMBLY__
#include <linux/stddef.h>
-#include <asm/processor.h> /* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
#include <asm/tlbflush.h>
-struct mm_struct;
#endif /* __ASSEMBLY__ */
#ifdef CONFIG_PPC_64K_PAGES
@@ -27,7 +23,7 @@ struct mm_struct;
*/
#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
-#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
#if TASK_SIZE_USER64 > PGTABLE_RANGE
#error TASK_SIZE_USER64 exceeds pagetable range
@@ -37,19 +33,28 @@ struct mm_struct;
#error TASK_SIZE_USER64 exceeds user VSID range
#endif
+
/*
* Define the address range of the vmalloc VM area.
*/
#define VMALLOC_START ASM_CONST(0xD000000000000000)
-#define VMALLOC_SIZE ASM_CONST(0x80000000000)
+#define VMALLOC_SIZE (PGTABLE_RANGE >> 1)
#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
/*
- * Define the address range of the imalloc VM area.
+ * Define the address ranges for MMIO and IO space :
+ *
+ * ISA_IO_BASE = VMALLOC_END, 64K reserved area
+ * PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
+ * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
*/
-#define PHBS_IO_BASE VMALLOC_END
-#define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */
-#define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE)
+#define FULL_IO_SIZE 0x80000000ul
+#define ISA_IO_BASE (VMALLOC_END)
+#define ISA_IO_END (VMALLOC_END + 0x10000ul)
+#define PHB_IO_BASE (ISA_IO_END)
+#define PHB_IO_END (VMALLOC_END + FULL_IO_SIZE)
+#define IOREMAP_BASE (PHB_IO_END)
+#define IOREMAP_END (VMALLOC_START + PGTABLE_RANGE)
/*
* Region IDs
@@ -134,16 +139,6 @@ struct mm_struct;
#define __S110 PAGE_SHARED_X
#define __S111 PAGE_SHARED_X
-#ifndef __ASSEMBLY__
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-#endif /* __ASSEMBLY__ */
-
#ifdef CONFIG_HUGETLB_PAGE
#define HAVE_ARCH_UNMAPPED_AREA
@@ -232,9 +227,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER;}
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC;}
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
@@ -242,20 +235,12 @@ static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
-static inline pte_t pte_rdprotect(pte_t pte) {
- pte_val(pte) &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
- pte_val(pte) &= ~_PAGE_EXEC; return pte; }
static inline pte_t pte_wrprotect(pte_t pte) {
pte_val(pte) &= ~(_PAGE_RW); return pte; }
static inline pte_t pte_mkclean(pte_t pte) {
pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
static inline pte_t pte_mkold(pte_t pte) {
pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) {
- pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
- pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) {
pte_val(pte) |= _PAGE_RW; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) {
@@ -307,29 +292,6 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
__r; \
})
-/*
- * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
- * moment we always flush but we need to fix hpte_update and test if the
- * optimisation is worth it.
- */
-static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm,
- unsigned long addr, pte_t *ptep)
-{
- unsigned long old;
-
- if ((pte_val(*ptep) & _PAGE_DIRTY) == 0)
- return 0;
- old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0);
- return (old & _PAGE_DIRTY) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __addr, __ptep) \
-({ \
- int __r; \
- __r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
- __r; \
-})
-
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
@@ -357,14 +319,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
__young; \
})
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
-({ \
- int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
- __ptep); \
- __dirty; \
-})
-
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
@@ -442,10 +396,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-extern pgd_t swapper_pg_dir[];
-
-extern void paging_init(void);
-
/* Encode and de-code a swap entry */
#define __swp_type(entry) (((entry).val >> 1) & 0x3f)
#define __swp_offset(entry) ((entry).val >> 8)
@@ -456,17 +406,6 @@ extern void paging_init(void);
#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT)
-/*
- * kern_addr_valid is intended to indicate whether an address is a valid
- * kernel address. Most 32-bit archs define it as always true (like this)
- * but most 64-bit archs actually perform a test. What should we do here?
- * The only use is in fs/ncpfs/dir.c
- */
-#define kern_addr_valid(addr) (1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
- remap_pfn_range(vma, vaddr, pfn, size, prot)
-
void pgtable_cache_init(void);
/*
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
index 78bf4ae712a6..d18ffe7bc7c4 100644
--- a/include/asm-powerpc/pgtable.h
+++ b/include/asm-powerpc/pgtable.h
@@ -2,6 +2,13 @@
#define _ASM_POWERPC_PGTABLE_H
#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#include <asm/processor.h> /* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+struct mm_struct;
+#endif /* !__ASSEMBLY__ */
+
#if defined(CONFIG_PPC64)
# include <asm/pgtable-ppc64.h>
#else
@@ -9,6 +16,27 @@
#endif
#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[];
+
+extern void paging_init(void);
+
+/*
+ * kern_addr_valid is intended to indicate whether an address is a valid
+ * kernel address. Most 32-bit archs define it as always true (like this)
+ * but most 64-bit archs actually perform a test. What should we do here?
+ */
+#define kern_addr_valid(addr) (1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
#include <asm-generic/pgtable.h>
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index 8e2005159ffd..b847aa10074b 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -26,7 +26,7 @@ extern int global_phb_number;
extern void find_and_init_phbs(void);
-extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */
+extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */
/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
#define BUID_HI(buid) ((buid) >> 32)
@@ -47,8 +47,8 @@ extern void init_pci_config_tokens (void);
extern unsigned long get_phb_buid (struct device_node *);
extern int rtas_setup_phb(struct pci_controller *phb);
-/* From pSeries_pci.h */
-extern void pSeries_final_fixup(void);
+/* From iSeries PCI */
+extern void iSeries_pcibios_init(void);
extern unsigned long pci_probe_only;
@@ -139,6 +139,9 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag);
*/
struct device_node * find_device_pe(struct device_node *dn);
+void eeh_sysfs_add_device(struct pci_dev *pdev);
+void eeh_sysfs_remove_device(struct pci_dev *pdev);
+
#endif /* CONFIG_EEH */
#else /* CONFIG_PCI */
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index d947b1609491..e28b10805159 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -43,14 +43,6 @@ extern int _chrp_type;
/* what kind of prep workstation we are */
extern int _prep_type;
-/*
- * This is used to identify the board type from a given PReP board
- * vendor. Board revision is also made available. This will be moved
- * elsewhere soon
- */
-extern unsigned char ucBoardRev;
-extern unsigned char ucBoardRevMaj, ucBoardRevMin;
-
#endif /* CONFIG_PPC_PREP */
#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 6845af93ba91..1632baa17dc6 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -98,10 +98,19 @@ struct device_node {
extern struct device_node *of_chosen;
/* flag descriptions */
-#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+#define OF_DETACHED 2 /* node has been detached from the device tree */
+
+static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
+{
+ return test_bit(flag, &n->_flags);
+}
+
+static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
+{
+ set_bit(flag, &n->_flags);
+}
-#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
-#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
#define HAVE_ARCH_DEVTREE_FIXUPS
@@ -124,6 +133,9 @@ extern struct device_node *of_find_node_by_type(struct device_node *from,
dn = of_find_node_by_type(dn, type))
extern struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
+#define for_each_compatible_node(dn, type, compatible) \
+ for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+ dn = of_find_compatible_node(dn, type, compatible))
extern struct device_node *of_find_node_by_path(const char *path);
extern struct device_node *of_find_node_by_phandle(phandle handle);
extern struct device_node *of_find_all_nodes(struct device_node *prev);
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 1e04651eedc4..a6f3f5ee7ca7 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -35,7 +35,8 @@ union ps3_firmware_version {
};
};
-int ps3_get_firmware_version(union ps3_firmware_version *v);
+void ps3_get_firmware_version(union ps3_firmware_version *v);
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev);
/* 'Other OS' area */
@@ -48,18 +49,6 @@ enum ps3_param_av_multi_out {
enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void);
-/**
- * struct ps3_device_id - HV bus device identifier from the system repository
- * @bus_id: HV bus id, {1..} (zero invalid)
- * @dev_id: HV device id, {0..}
- */
-
-struct ps3_device_id {
- unsigned int bus_id;
- unsigned int dev_id;
-};
-
-
/* dma routines */
enum ps3_dma_page_size {
@@ -74,6 +63,8 @@ enum ps3_dma_region_type {
PS3_DMA_INTERNAL = 2,
};
+struct ps3_dma_region_ops;
+
/**
* struct ps3_dma_region - A per device dma state variables structure
* @did: The HV device id.
@@ -81,21 +72,42 @@ enum ps3_dma_region_type {
* @region_type: The HV region type.
* @bus_addr: The 'translated' bus address of the region.
* @len: The length in bytes of the region.
+ * @offset: The offset from the start of memory of the region.
+ * @ioid: The IOID of the device who owns this region
* @chunk_list: Opaque variable used by the ioc page manager.
+ * @region_ops: struct ps3_dma_region_ops - dma region operations
*/
struct ps3_dma_region {
- struct ps3_device_id did;
+ struct ps3_system_bus_device *dev;
+ /* device variables */
+ const struct ps3_dma_region_ops *region_ops;
+ unsigned char ioid;
enum ps3_dma_page_size page_size;
enum ps3_dma_region_type region_type;
- unsigned long bus_addr;
unsigned long len;
+ unsigned long offset;
+
+ /* driver variables (set by ps3_dma_region_create) */
+ unsigned long bus_addr;
struct {
spinlock_t lock;
struct list_head head;
} chunk_list;
};
+struct ps3_dma_region_ops {
+ int (*create)(struct ps3_dma_region *);
+ int (*free)(struct ps3_dma_region *);
+ int (*map)(struct ps3_dma_region *,
+ unsigned long virt_addr,
+ unsigned long len,
+ unsigned long *bus_addr,
+ u64 iopte_pp);
+ int (*unmap)(struct ps3_dma_region *,
+ unsigned long bus_addr,
+ unsigned long len);
+};
/**
* struct ps3_dma_region_init - Helper to initialize structure variables
*
@@ -103,18 +115,16 @@ struct ps3_dma_region {
* ps3_system_bus_device_register.
*/
-static inline void ps3_dma_region_init(struct ps3_dma_region *r,
- const struct ps3_device_id* did, enum ps3_dma_page_size page_size,
- enum ps3_dma_region_type region_type)
-{
- r->did = *did;
- r->page_size = page_size;
- r->region_type = region_type;
-}
+struct ps3_system_bus_device;
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+ struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+ enum ps3_dma_region_type region_type, void *addr, unsigned long len);
int ps3_dma_region_create(struct ps3_dma_region *r);
int ps3_dma_region_free(struct ps3_dma_region *r);
int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr);
+ unsigned long len, unsigned long *bus_addr,
+ u64 iopte_pp);
int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
unsigned long len);
@@ -125,6 +135,7 @@ enum ps3_mmio_page_size {
PS3_MMIO_64K = 16U
};
+struct ps3_mmio_region_ops;
/**
* struct ps3_mmio_region - a per device mmio state variables structure
*
@@ -132,13 +143,18 @@ enum ps3_mmio_page_size {
*/
struct ps3_mmio_region {
- struct ps3_device_id did;
+ struct ps3_system_bus_device *dev;
+ const struct ps3_mmio_region_ops *mmio_ops;
unsigned long bus_addr;
unsigned long len;
enum ps3_mmio_page_size page_size;
unsigned long lpar_addr;
};
+struct ps3_mmio_region_ops {
+ int (*create)(struct ps3_mmio_region *);
+ int (*free)(struct ps3_mmio_region *);
+};
/**
* struct ps3_mmio_region_init - Helper to initialize structure variables
*
@@ -146,15 +162,9 @@ struct ps3_mmio_region {
* ps3_system_bus_device_register.
*/
-static inline void ps3_mmio_region_init(struct ps3_mmio_region *r,
- const struct ps3_device_id* did, unsigned long bus_addr,
- unsigned long len, enum ps3_mmio_page_size page_size)
-{
- r->did = *did;
- r->bus_addr = bus_addr;
- r->len = len;
- r->page_size = page_size;
-}
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+ struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+ enum ps3_mmio_page_size page_size);
int ps3_mmio_region_create(struct ps3_mmio_region *r);
int ps3_free_mmio_region(struct ps3_mmio_region *r);
unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr);
@@ -187,11 +197,10 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
unsigned int class, unsigned int *virq);
int ps3_spe_irq_destroy(unsigned int virq);
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
- const struct ps3_device_id *did, unsigned int interrupt_id,
- unsigned int *virq);
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
- unsigned int interrupt_id, unsigned int virq);
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+ enum ps3_cpu_binding cpu, unsigned int *virq);
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+ unsigned int virq);
/* lv1 result codes */
@@ -289,11 +298,33 @@ static inline const char* ps3_result(int result)
/* system bus routines */
enum ps3_match_id {
- PS3_MATCH_ID_EHCI = 1,
- PS3_MATCH_ID_OHCI,
- PS3_MATCH_ID_GELIC,
- PS3_MATCH_ID_AV_SETTINGS,
- PS3_MATCH_ID_SYSTEM_MANAGER,
+ PS3_MATCH_ID_EHCI = 1,
+ PS3_MATCH_ID_OHCI = 2,
+ PS3_MATCH_ID_GELIC = 3,
+ PS3_MATCH_ID_AV_SETTINGS = 4,
+ PS3_MATCH_ID_SYSTEM_MANAGER = 5,
+ PS3_MATCH_ID_STOR_DISK = 6,
+ PS3_MATCH_ID_STOR_ROM = 7,
+ PS3_MATCH_ID_STOR_FLASH = 8,
+ PS3_MATCH_ID_SOUND = 9,
+ PS3_MATCH_ID_GRAPHICS = 10,
+};
+
+#define PS3_MODULE_ALIAS_EHCI "ps3:1"
+#define PS3_MODULE_ALIAS_OHCI "ps3:2"
+#define PS3_MODULE_ALIAS_GELIC "ps3:3"
+#define PS3_MODULE_ALIAS_AV_SETTINGS "ps3:4"
+#define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5"
+#define PS3_MODULE_ALIAS_STOR_DISK "ps3:6"
+#define PS3_MODULE_ALIAS_STOR_ROM "ps3:7"
+#define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8"
+#define PS3_MODULE_ALIAS_SOUND "ps3:9"
+#define PS3_MODULE_ALIAS_GRAPHICS "ps3:10"
+
+enum ps3_system_bus_device_type {
+ PS3_DEVICE_TYPE_IOC0 = 1,
+ PS3_DEVICE_TYPE_SB,
+ PS3_DEVICE_TYPE_VUART,
};
/**
@@ -302,14 +333,23 @@ enum ps3_match_id {
struct ps3_system_bus_device {
enum ps3_match_id match_id;
- struct ps3_device_id did;
- unsigned int interrupt_id;
-/* struct iommu_table *iommu_table; -- waiting for Ben's cleanups */
- struct ps3_dma_region *d_region;
- struct ps3_mmio_region *m_region;
+ enum ps3_system_bus_device_type dev_type;
+
+ unsigned int bus_id; /* SB */
+ unsigned int dev_id; /* SB */
+ unsigned int interrupt_id; /* SB */
+ struct ps3_dma_region *d_region; /* SB, IOC0 */
+ struct ps3_mmio_region *m_region; /* SB, IOC0*/
+ unsigned int port_number; /* VUART */
+
+/* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */
struct device core;
+ void *driver_priv; /* private driver variables */
};
+int ps3_open_hv_device(struct ps3_system_bus_device *dev);
+int ps3_close_hv_device(struct ps3_system_bus_device *dev);
+
/**
* struct ps3_system_bus_driver - a driver for a device on the system bus
*/
@@ -319,6 +359,7 @@ struct ps3_system_bus_driver {
struct device_driver core;
int (*probe)(struct ps3_system_bus_device *);
int (*remove)(struct ps3_system_bus_device *);
+ int (*shutdown)(struct ps3_system_bus_device *);
/* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
/* int (*resume)(struct ps3_system_bus_device *); */
};
@@ -326,16 +367,24 @@ struct ps3_system_bus_driver {
int ps3_system_bus_device_register(struct ps3_system_bus_device *dev);
int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv);
void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv);
-static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver(
+
+static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv(
struct device_driver *_drv)
{
return container_of(_drv, struct ps3_system_bus_driver, core);
}
-static inline struct ps3_system_bus_device *to_ps3_system_bus_device(
+static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev(
struct device *_dev)
{
return container_of(_dev, struct ps3_system_bus_device, core);
}
+static inline struct ps3_system_bus_driver *
+ ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev)
+{
+ BUG_ON(!_dev);
+ BUG_ON(!_dev->core.driver);
+ return ps3_drv_to_system_bus_drv(_dev->core.driver);
+}
/**
* ps3_system_bus_set_drvdata -
@@ -358,32 +407,17 @@ static inline void *ps3_system_bus_get_driver_data(
extern struct bus_type ps3_system_bus_type;
-/* vuart routines */
-
-struct ps3_vuart_port_priv;
-
-/**
- * struct ps3_vuart_port_device - a device on a vuart port
- */
-
-struct ps3_vuart_port_device {
- enum ps3_match_id match_id;
- struct device core;
- struct ps3_vuart_port_priv* priv; /* private driver variables */
+/* system manager */
+struct ps3_sys_manager_ops {
+ struct ps3_system_bus_device *dev;
+ void (*power_off)(struct ps3_system_bus_device *dev);
+ void (*restart)(struct ps3_system_bus_device *dev);
};
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
-
-/* system manager */
-
-#ifdef CONFIG_PS3_SYS_MANAGER
-void ps3_sys_manager_restart(void);
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
void ps3_sys_manager_power_off(void);
-#else
-static inline void ps3_sys_manager_restart(void) {}
-static inline void ps3_sys_manager_power_off(void) {}
-#endif
+void ps3_sys_manager_restart(void);
struct ps3_prealloc {
const char *name;
@@ -393,5 +427,7 @@ struct ps3_prealloc {
};
extern struct ps3_prealloc ps3fb_videomemory;
+extern struct ps3_prealloc ps3flash_bounce_buffer;
+
#endif
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
index 9efc40f1c778..7df4250802de 100644
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -1,20 +1,23 @@
/*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ * PS3 AV backend support.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
*
- * 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.
+ * 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.
*
- * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#ifndef _ASM_POWERPC_PS3AV_H_
#define _ASM_POWERPC_PS3AV_H_
@@ -159,6 +162,9 @@
#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000
/* video_out_format */
#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000
+/* video_cl_cnv */
+#define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT 0x0000
+#define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT 0x0010
/* video_sync */
#define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001
#define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004
@@ -311,6 +317,8 @@
#define PS3AV_MODE_MASK 0x000F
#define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */
#define PS3AV_MODE_DITHER 0x0800
+#define PS3AV_MODE_COLOR 0x0400
+#define PS3AV_MODE_WHITE 0x0200
#define PS3AV_MODE_FULL 0x0080
#define PS3AV_MODE_DVI 0x0040
#define PS3AV_MODE_RGB 0x0020
@@ -529,9 +537,9 @@ struct ps3av_pkt_video_mode {
u32 video_out_format; /* in: out format */
u32 video_format; /* in: input frame buffer format */
u8 reserved3;
- u8 reserved4;
+ u8 video_cl_cnv; /* in: color conversion */
u16 video_order; /* in: input RGB order */
- u32 reserved5;
+ u32 reserved4;
};
/* video: format */
@@ -539,7 +547,8 @@ struct ps3av_pkt_video_format {
struct ps3av_send_hdr send_hdr;
u32 video_head; /* in: head */
u32 video_format; /* in: frame buffer format */
- u16 reserved;
+ u8 reserved;
+ u8 video_cl_cnv; /* in: color conversion */
u16 video_order; /* in: input RGB order */
};
@@ -698,12 +707,6 @@ static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_
extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
u32);
-struct ps3_vuart_port_device;
-extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
- const void *buf, unsigned long size);
-extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
- unsigned long size, int timeout);
-
extern int ps3av_set_video_mode(u32, int);
extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
extern int ps3av_get_auto_mode(int);
@@ -716,5 +719,8 @@ extern int ps3av_video_mute(int);
extern int ps3av_audio_mute(int);
extern int ps3av_dev_open(void);
extern int ps3av_dev_close(void);
+extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+ void *flip_data);
+extern void ps3av_flip_ctl(int on);
#endif /* _ASM_POWERPC_PS3AV_H_ */
diff --git a/include/asm-powerpc/ps3fb.h b/include/asm-powerpc/ps3fb.h
index ad81cf431964..3f121fe4010d 100644
--- a/include/asm-powerpc/ps3fb.h
+++ b/include/asm-powerpc/ps3fb.h
@@ -41,16 +41,4 @@ struct ps3fb_ioctl_res {
__u32 num_frames; /* num of frame buffers */
};
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FB_PS3
-extern void ps3fb_flip_ctl(int on);
-extern void ps3fb_cleanup(void);
-#else
-static inline void ps3fb_flip_ctl(int on) {}
-static inline void ps3fb_cleanup(void) {}
-#endif
-
-#endif /* __KERNEL__ */
-
#endif /* _ASM_POWERPC_PS3FB_H_ */
diff --git a/include/asm-powerpc/ps3stor.h b/include/asm-powerpc/ps3stor.h
new file mode 100644
index 000000000000..6fcaf714fa50
--- /dev/null
+++ b/include/asm-powerpc/ps3stor.h
@@ -0,0 +1,71 @@
+/*
+ * PS3 Storage Devices
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _ASM_POWERPC_PS3STOR_H_
+#define _ASM_POWERPC_PS3STOR_H_
+
+#include <linux/interrupt.h>
+
+#include <asm/ps3.h>
+
+
+struct ps3_storage_region {
+ unsigned int id;
+ u64 start;
+ u64 size;
+};
+
+struct ps3_storage_device {
+ struct ps3_system_bus_device sbd;
+
+ struct ps3_dma_region dma_region;
+ unsigned int irq;
+ u64 blk_size;
+
+ u64 tag;
+ u64 lv1_status;
+ struct completion done;
+
+ unsigned long bounce_size;
+ void *bounce_buf;
+ u64 bounce_lpar;
+ dma_addr_t bounce_dma;
+
+ unsigned int num_regions;
+ unsigned long accessible_regions;
+ unsigned int region_idx; /* first accessible region */
+ struct ps3_storage_region regions[0]; /* Must be last */
+};
+
+static inline struct ps3_storage_device *to_ps3_storage_device(struct device *dev)
+{
+ return container_of(dev, struct ps3_storage_device, sbd.core);
+}
+
+extern int ps3stor_setup(struct ps3_storage_device *dev,
+ irq_handler_t handler);
+extern void ps3stor_teardown(struct ps3_storage_device *dev);
+extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+ u64 start_sector, u64 sectors,
+ int write);
+extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
+ u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+
+#endif /* _ASM_POWERPC_PS3STOR_H_ */
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
index 4ad77a13f865..13fccc5a4119 100644
--- a/include/asm-powerpc/ptrace.h
+++ b/include/asm-powerpc/ptrace.h
@@ -92,6 +92,11 @@ extern unsigned long profile_pc(struct pt_regs *regs);
set_thread_flag(TIF_NOERROR); \
} while(0)
+struct task_struct;
+extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+extern int ptrace_put_reg(struct task_struct *task, int regno,
+ unsigned long data);
+
/*
* We use the least-significant bit of the trap field to indicate
* whether we have saved the full set of registers, or only a
@@ -158,9 +163,7 @@ do { \
#define PT_NIP 32
#define PT_MSR 33
-#ifdef __KERNEL__
#define PT_ORIG_R3 34
-#endif
#define PT_CTR 35
#define PT_LNK 36
#define PT_XER 37
@@ -169,11 +172,12 @@ do { \
#define PT_MQ 39
#else
#define PT_SOFTE 39
+#endif
#define PT_TRAP 40
#define PT_DAR 41
#define PT_DSISR 42
#define PT_RESULT 43
-#endif
+#define PT_REGS_COUNT 44
#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
@@ -229,7 +233,17 @@ do { \
#define PTRACE_GET_DEBUGREG 25
#define PTRACE_SET_DEBUGREG 26
-/* Additional PTRACE requests implemented on PowerPC. */
+/* (new) PTRACE requests using the same numbers as x86 and the same
+ * argument ordering. Additionally, they support more registers too
+ */
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_GETREGS64 22
+#define PTRACE_SETREGS64 23
+
+/* (old) PTRACE requests with inverted arguments */
#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */
#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */
#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 749c7f953b58..281011e953ec 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -453,6 +453,8 @@
#define SPRN_MMCRA 0x312
#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */
#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */
+#define MMCRA_SLOT 0x07000000UL /* SLOT bits (37-39) */
+#define MMCRA_SLOT_SHIFT 24
#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
#define POWER6_MMCRA_SIHV 0x0000040000000000ULL
#define POWER6_MMCRA_SIPR 0x0000020000000000ULL
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 31d5054be20f..eedc828cef2d 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -106,6 +106,14 @@ struct spu_context;
struct spu_runqueue;
struct device_node;
+enum spu_utilization_state {
+ SPU_UTIL_SYSTEM,
+ SPU_UTIL_USER,
+ SPU_UTIL_IOWAIT,
+ SPU_UTIL_IDLE,
+ SPU_UTIL_MAX
+};
+
struct spu {
const char *name;
unsigned long local_store_phys;
@@ -156,6 +164,21 @@ struct spu {
u64 shadow_int_mask_RW[3];
struct sys_device sysdev;
+
+ struct {
+ /* protected by interrupt reentrancy */
+ enum spu_utilization_state utilization_state;
+ unsigned long tstamp; /* time of last ctx switch */
+ unsigned long times[SPU_UTIL_MAX];
+ unsigned long long vol_ctx_switch;
+ unsigned long long invol_ctx_switch;
+ unsigned long long min_flt;
+ unsigned long long maj_flt;
+ unsigned long long hash_flt;
+ unsigned long long slb_flt;
+ unsigned long long class2_intr;
+ unsigned long long libassist;
+ } stats;
};
struct spu *spu_alloc(void);
@@ -448,6 +471,7 @@ struct spu_priv1 {
#define MFC_STATE1_PROBLEM_STATE_MASK 0x08ull
#define MFC_STATE1_RELOCATE_MASK 0x10ull
#define MFC_STATE1_MASTER_RUN_CONTROL_MASK 0x20ull
+#define MFC_STATE1_TABLE_SEARCH_MASK 0x40ull
u64 mfc_lpid_RW; /* 0x008 */
u64 spu_idr_RW; /* 0x010 */
u64 mfc_vr_RO; /* 0x018 */
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
index c2fe79d4f90f..b3ca41fc8bb1 100644
--- a/include/asm-powerpc/syscalls.h
+++ b/include/asm-powerpc/syscalls.h
@@ -43,16 +43,9 @@ asmlinkage long ppc_newuname(struct new_utsname __user * name);
asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
size_t sigsetsize);
-
-#ifndef __powerpc64__
-asmlinkage long sys_sigaltstack(const stack_t __user *uss,
- stack_t __user *uoss, int r5, int r6, int r7, int r8,
- struct pt_regs *regs);
-#else /* __powerpc64__ */
asmlinkage long sys_sigaltstack(const stack_t __user *uss,
stack_t __user *uoss, unsigned long r5, unsigned long r6,
unsigned long r7, unsigned long r8, struct pt_regs *regs);
-#endif /* __powerpc64__ */
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_SYSCALLS_H */
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 09621f611dbc..32aa42b748be 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -43,7 +43,7 @@
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
-#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory")
+#define smp_wmb() eieio()
#define smp_read_barrier_depends() read_barrier_depends()
#else
#define smp_mb() barrier()
@@ -559,5 +559,7 @@ static inline void create_function_call(unsigned long addr, void * func)
extern void account_system_vtime(struct task_struct *);
#endif
+extern struct dentry *powerpc_debugfs_root;
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_SYSTEM_H */
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h
index 5e79198f7d18..6698188ca550 100644
--- a/include/asm-powerpc/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -152,6 +152,10 @@ struct ktermios {
#define B3000000 00034
#define B3500000 00035
#define B4000000 00036
+#define BOTHER 00037
+
+#define CIBAUD 077600000
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
#define CSIZE 00001400
#define CS5 00000000
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 3f32ca8bfec9..9d9aeca8ad22 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -113,8 +113,8 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_32BIT 5 /* 32 bit binary */
-#define TIF_RUNLATCH 6 /* Is the runlatch enabled? */
-#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */
+#define TIF_PERFMON_WORK 6 /* work for pfm_handle_work() */
+#define TIF_PERFMON_CTXSW 7 /* perfmon needs ctxsw calls */
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
#define TIF_SINGLESTEP 9 /* singlestepping active */
#define TIF_MEMDIE 10
@@ -123,6 +123,8 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOERROR 14 /* Force successful syscall return */
#define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */
#define TIF_FREEZE 16 /* Freezing for suspend */
+#define TIF_RUNLATCH 17 /* Is the runlatch enabled? */
+#define TIF_ABI_PENDING 18 /* 32/64 bit switch needed */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -131,8 +133,8 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_32BIT (1<<TIF_32BIT)
-#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
-#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
+#define _TIF_PERFMON_WORK (1<<TIF_PERFMON_WORK)
+#define _TIF_PERFMON_CTXSW (1<<TIF_PERFMON_CTXSW)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
@@ -140,6 +142,8 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_FREEZE (1<<TIF_FREEZE)
+#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
+#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index 3fd57c048f59..d7f5ddfbaac7 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -232,7 +232,7 @@ extern void account_process_vtime(struct task_struct *tsk);
#define account_process_vtime(tsk) do { } while (0)
#endif
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING)
extern void calculate_steal_time(void);
extern void snapshot_timebases(void);
#else
@@ -240,5 +240,7 @@ extern void snapshot_timebases(void);
#define snapshot_timebases() do { } while (0)
#endif
+extern void iSeries_time_init_early(void);
+
#endif /* __KERNEL__ */
#endif /* __POWERPC_TIME_H */
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index 86e6266a028b..99a0439baa50 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -155,6 +155,11 @@ static inline void flush_tlb_kernel_range(unsigned long start,
{
}
+/* Private function for use by PCI IO mapping code */
+extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end);
+
+
#endif
/*
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 9d0ce9ff5840..c159315d2c8f 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -533,9 +533,7 @@ static inline int pgd_present(pgd_t pgd) { return 1; }
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
@@ -543,21 +541,13 @@ static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
-static inline pte_t pte_rdprotect(pte_t pte) {
- pte_val(pte) &= ~_PAGE_USER; return pte; }
static inline pte_t pte_wrprotect(pte_t pte) {
pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
- pte_val(pte) &= ~_PAGE_EXEC; return pte; }
static inline pte_t pte_mkclean(pte_t pte) {
pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
static inline pte_t pte_mkold(pte_t pte) {
pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) {
- pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkexec(pte_t pte) {
- pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) {
pte_val(pte) |= _PAGE_RW; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) {
@@ -664,13 +654,6 @@ static inline int __ptep_test_and_clear_young(unsigned int context, unsigned lon
#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
- unsigned long addr, pte_t *ptep)
-{
- return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
-}
-
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index 296f4f1a20e1..7f4ad623f7d5 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -60,8 +60,10 @@ typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-s390/dma-mapping.h b/include/asm-s390/dma-mapping.h
deleted file mode 100644
index 3f8c12fde0f0..000000000000
--- a/include/asm-s390/dma-mapping.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * include/asm-s390/dma-mapping.h
- *
- * S390 version
- *
- * This file exists so that #include <dma-mapping.h> doesn't break anything.
- */
-
-#ifndef _ASM_DMA_MAPPING_H
-#define _ASM_DMA_MAPPING_H
-
-#endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-s390/fb.h b/include/asm-s390/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-s390/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 05ea6f172786..f326451ed6ec 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -64,7 +64,8 @@ static inline void copy_page(void *to, void *from)
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 0a307bb2f353..3208dc6c412c 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -530,14 +530,6 @@ static inline int pte_young(pte_t pte)
return 0;
}
-static inline int pte_read(pte_t pte)
-{
- /* All pages are readable since we don't use the fetch
- * protection bit in the storage key.
- */
- return 1;
-}
-
/*
* pgd/pmd/pte modification functions
*/
@@ -677,19 +669,6 @@ ptep_clear_flush_young(struct vm_area_struct *vma,
return ptep_test_and_clear_young(vma, address, ptep);
}
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
- return 0;
-}
-
-static inline int
-ptep_clear_flush_dirty(struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep)
-{
- /* No need to flush TLB; bits are in storage key */
- return ptep_test_and_clear_dirty(vma, address, ptep);
-}
-
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;
@@ -715,16 +694,19 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
pte_val(*ptep) = _PAGE_TYPE_EMPTY;
}
-static inline pte_t
-ptep_clear_flush(struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep)
+static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
{
- pte_t pte = *ptep;
- pte_t *shadow_pte = get_shadow_pte(ptep);
-
__ptep_ipte(address, ptep);
- if (shadow_pte)
- __ptep_ipte(address, shadow_pte);
+ ptep = get_shadow_pte(ptep);
+ if (ptep)
+ __ptep_ipte(address, ptep);
+}
+
+static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ ptep_invalidate(address, ptep);
return pte;
}
@@ -734,21 +716,14 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
}
-static inline void
-ptep_establish(struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep,
- pte_t entry)
-{
- ptep_clear_flush(vma, address, ptep);
- set_pte(ptep, entry);
-}
-
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({ \
- int __changed = !pte_same(*(__ptep), __entry); \
- if (__changed) \
- ptep_establish(__vma, __address, __ptep, __entry); \
- __changed; \
+#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ ptep_invalidate(__addr, __ptep); \
+ set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry); \
+ } \
+ __changed; \
})
/*
@@ -948,12 +923,9 @@ extern int remove_shared_memory(unsigned long start, unsigned long size);
#define __HAVE_ARCH_MEMMAP_INIT
extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
-#define __HAVE_ARCH_PTEP_ESTABLISH
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index 5a117ec43c77..aeee8da9c54f 100644
--- a/include/asm-sh/bugs.h
+++ b/include/asm-sh/bugs.h
@@ -22,7 +22,7 @@ static void __init check_bugs(void)
current_cpu_data.loops_per_jiffy = loops_per_jiffy;
switch (current_cpu_data.type) {
- case CPU_SH7604 ... CPU_SH7619:
+ case CPU_SH7619:
*p++ = '2';
break;
case CPU_SH7206:
@@ -35,7 +35,7 @@ static void __init check_bugs(void)
case CPU_SH7750 ... CPU_SH4_501:
*p++ = '4';
break;
- case CPU_SH7770 ... CPU_SH7785:
+ case CPU_SH7770 ... CPU_SHX3:
*p++ = '4';
*p++ = 'a';
break;
diff --git a/include/asm-sh/cache.h b/include/asm-sh/cache.h
index 9a3cb6ba9d15..7a18649d1ccb 100644
--- a/include/asm-sh/cache.h
+++ b/include/asm-sh/cache.h
@@ -9,6 +9,7 @@
#define __ASM_SH_CACHE_H
#ifdef __KERNEL__
+#include <linux/init.h>
#include <asm/cpu/cache.h>
#define SH_CACHE_VALID 1
@@ -48,6 +49,9 @@ struct cache_info {
unsigned long flags;
};
+
+int __init detect_cpu_and_cache_system(void);
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __ASM_SH_CACHE_H */
diff --git a/include/asm-sh/cpu-sh2/cache.h b/include/asm-sh/cpu-sh2/cache.h
index 20b9796842dc..f02ba7a672b2 100644
--- a/include/asm-sh/cpu-sh2/cache.h
+++ b/include/asm-sh/cpu-sh2/cache.h
@@ -12,23 +12,7 @@
#define L1_CACHE_SHIFT 4
-#if defined(CONFIG_CPU_SUBTYPE_SH7604)
-#define CCR 0xfffffe92 /* Address of Cache Control Register */
-
-#define CCR_CACHE_CE 0x01 /* Cache enable */
-#define CCR_CACHE_ID 0x02 /* Instruction Replacement disable */
-#define CCR_CACHE_OD 0x04 /* Data Replacement disable */
-#define CCR_CACHE_TW 0x08 /* Two-way mode */
-#define CCR_CACHE_CP 0x10 /* Cache purge */
-
-#define CACHE_OC_ADDRESS_ARRAY 0x60000000
-
-#define CCR_CACHE_ENABLE CCR_CACHE_CE
-#define CCR_CACHE_INVALIDATE CCR_CACHE_CP
-#define CCR_CACHE_ORA CCR_CACHE_TW
-#define CCR_CACHE_WT 0x00 /* SH-2 is _always_ write-through */
-
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#if defined(CONFIG_CPU_SUBTYPE_SH7619)
#define CCR1 0xffffffec
#define CCR CCR1
@@ -49,5 +33,5 @@
#define CCR_CACHE_ENABLE CCR_CACHE_CE
#define CCR_CACHE_INVALIDATE CCR_CACHE_CF
#endif
-#endif /* __ASM_CPU_SH2_CACHE_H */
+#endif /* __ASM_CPU_SH2_CACHE_H */
diff --git a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h
index b2394cf76f49..4928b08f9d19 100644
--- a/include/asm-sh/cpu-sh3/timer.h
+++ b/include/asm-sh/cpu-sh3/timer.h
@@ -29,7 +29,7 @@
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
-#define TMU_TSTR 0xa412fe92 /* Byte access */
+#define TMU_012_TSTR 0xa412fe92 /* Byte access */
#define TMU0_TCOR 0xa412fe94 /* Long access */
#define TMU0_TCNT 0xa412fe98 /* Long access */
@@ -44,7 +44,7 @@
#define TMU2_TCR 0xa412feb4 /* Word access */
#else
-#define TMU_TSTR 0xfffffe92 /* Byte access */
+#define TMU_012_TSTR 0xfffffe92 /* Byte access */
#define TMU0_TCOR 0xfffffe94 /* Long access */
#define TMU0_TCNT 0xfffffe98 /* Long access */
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index 39f41fcd509d..026025b51cea 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -22,6 +22,8 @@
#define FRQCR0 0xffc80000
#define FRQCR1 0xffc80004
#define FRQMR1 0xffc80014
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+#define FRQCR 0xffc00014
#else
#define FRQCR 0xffc00000
#define FRQCR_PSTBY 0x0200
diff --git a/include/asm-sh/cpu-sh4/timer.h b/include/asm-sh/cpu-sh4/timer.h
index 8a4af126c890..d1e796b96888 100644
--- a/include/asm-sh/cpu-sh4/timer.h
+++ b/include/asm-sh/cpu-sh4/timer.h
@@ -1,7 +1,7 @@
/*
* include/asm-sh/cpu-sh4/timer.h
*
- * Copyright (C) 2004 Lineo Solutions, Inc.
+ * Copyright (C) 2004 Lineo Solutions, Inc.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -16,36 +16,45 @@
* SH7750S/SH7750R
* SH7751/SH7751R
* SH7760
+ * SH-X3
* ---------------------------------------------------------------------------
*/
-
-#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define TMU_TOCR 0xffd80000 /* Byte access */
+#ifdef CONFIG_CPU_SUBTYPE_SHX3
+#define TMU_012_BASE 0xffc10000
+#define TMU_345_BASE 0xffc20000
+#else
+#define TMU_012_BASE 0xffd80000
+#define TMU_345_BASE 0xfe100000
#endif
-#define TMU_TSTR 0xffd80004 /* Byte access */
-#define TMU0_TCOR 0xffd80008 /* Long access */
-#define TMU0_TCNT 0xffd8000c /* Long access */
-#define TMU0_TCR 0xffd80010 /* Word access */
+#define TMU_TOCR TMU_012_BASE /* Not supported on all CPUs */
-#define TMU1_TCOR 0xffd80014 /* Long access */
-#define TMU1_TCNT 0xffd80018 /* Long access */
-#define TMU1_TCR 0xffd8001c /* Word access */
+#define TMU_012_TSTR (TMU_012_BASE + 0x04)
+#define TMU_345_TSTR (TMU_345_BASE + 0x04)
-#define TMU2_TCOR 0xffd80020 /* Long access */
-#define TMU2_TCNT 0xffd80024 /* Long access */
-#define TMU2_TCR 0xffd80028 /* Word access */
-#define TMU2_TCPR 0xffd8002c /* Long access */
+#define TMU0_TCOR (TMU_012_BASE + 0x08)
+#define TMU0_TCNT (TMU_012_BASE + 0x0c)
+#define TMU0_TCR (TMU_012_BASE + 0x10)
-#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
-#define TMU3_TCOR 0xfe100008 /* Long access */
-#define TMU3_TCNT 0xfe10000c /* Long access */
-#define TMU3_TCR 0xfe100010 /* Word access */
+#define TMU1_TCOR (TMU_012_BASE + 0x14)
+#define TMU1_TCNT (TMU_012_BASE + 0x18)
+#define TMU1_TCR (TMU_012_BASE + 0x1c)
-#define TMU4_TCOR 0xfe100014 /* Long access */
-#define TMU4_TCNT 0xfe100018 /* Long access */
-#define TMU4_TCR 0xfe10001c /* Word access */
-#endif
+#define TMU2_TCOR (TMU_012_BASE + 0x20)
+#define TMU2_TCNT (TMU_012_BASE + 0x24)
+#define TMU2_TCR (TMU_012_BASE + 0x28)
+#define TMU2_TCPR (TMU_012_BASE + 0x2c)
-#endif /* __ASM_CPU_SH4_TIMER_H */
+#define TMU3_TCOR (TMU_345_BASE + 0x08)
+#define TMU3_TCNT (TMU_345_BASE + 0x0c)
+#define TMU3_TCR (TMU_345_BASE + 0x10)
+#define TMU4_TCOR (TMU_345_BASE + 0x14)
+#define TMU4_TCNT (TMU_345_BASE + 0x18)
+#define TMU4_TCR (TMU_345_BASE + 0x1c)
+
+#define TMU5_TCOR (TMU_345_BASE + 0x20)
+#define TMU5_TCNT (TMU_345_BASE + 0x24)
+#define TMU5_TCR (TMU_345_BASE + 0x28)
+
+#endif /* __ASM_CPU_SH4_TIMER_H */
diff --git a/include/asm-sh/fb.h b/include/asm-sh/fb.h
new file mode 100644
index 000000000000..d92e99cd8c8a
--- /dev/null
+++ b/include/asm-sh/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sh/futex-irq.h b/include/asm-sh/futex-irq.h
new file mode 100644
index 000000000000..a9f16a7f9aea
--- /dev/null
+++ b/include/asm-sh/futex-irq.h
@@ -0,0 +1,111 @@
+#ifndef __ASM_SH_FUTEX_IRQ_H
+#define __ASM_SH_FUTEX_IRQ_H
+
+#include <asm/system.h>
+
+static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+ int *oldval)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+
+ ret = get_user(*oldval, uaddr);
+ if (!ret)
+ ret = put_user(oparg, uaddr);
+
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+ int *oldval)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+
+ ret = get_user(*oldval, uaddr);
+ if (!ret)
+ ret = put_user(*oldval + oparg, uaddr);
+
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+ int *oldval)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+
+ ret = get_user(*oldval, uaddr);
+ if (!ret)
+ ret = put_user(*oldval | oparg, uaddr);
+
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+ int *oldval)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+
+ ret = get_user(*oldval, uaddr);
+ if (!ret)
+ ret = put_user(*oldval & oparg, uaddr);
+
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+ int *oldval)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+
+ ret = get_user(*oldval, uaddr);
+ if (!ret)
+ ret = put_user(*oldval ^ oparg, uaddr);
+
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
+ int oldval, int newval)
+{
+ unsigned long flags;
+ int ret, prev = 0;
+
+ local_irq_save(flags);
+
+ ret = get_user(prev, uaddr);
+ if (!ret && oldval == prev)
+ ret = put_user(newval, uaddr);
+
+ local_irq_restore(flags);
+
+ if (ret)
+ return ret;
+
+ return prev;
+}
+
+#endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
index 6a332a9f099c..74ed3681d33c 100644
--- a/include/asm-sh/futex.h
+++ b/include/asm-sh/futex.h
@@ -1,6 +1,77 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef __ASM_SH_FUTEX_H
+#define __ASM_SH_FUTEX_H
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
-#endif
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+/* XXX: UP variants, fix for SH-4A and SMP.. */
+#include <asm/futex-irq.h>
+
+static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ pagefault_disable();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ADD:
+ ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_OR:
+ ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ANDN:
+ ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_XOR:
+ ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ pagefault_enable();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+ case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ default: ret = -ENOSYS;
+ }
+ }
+
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_FUTEX_H */
diff --git a/include/asm-sh/hd64461.h b/include/asm-sh/hd64461.h
index 27e5c34e2659..4dd8592ca014 100644
--- a/include/asm-sh/hd64461.h
+++ b/include/asm-sh/hd64461.h
@@ -1,200 +1,241 @@
#ifndef __ASM_SH_HD64461
#define __ASM_SH_HD64461
/*
- * $Id: hd64461.h,v 1.5 2004/03/16 00:07:51 lethal Exp $
+ * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ * Copyright (C) 2004 Paul Mundt
* Copyright (C) 2000 YAEGASHI Takeshi
- * Hitachi HD64461 companion chip support
+ *
+ * Hitachi HD64461 companion chip support
+ * (please note manual reference 0x10000000 = 0xb0000000)
*/
/* Constants for PCMCIA mappings */
-#define HD64461_PCC_WINDOW 0x01000000
-
-#define HD64461_PCC0_BASE 0xb8000000 /* area 6 */
-#define HD64461_PCC0_ATTR (HD64461_PCC0_BASE)
-#define HD64461_PCC0_COMM (HD64461_PCC0_BASE+HD64461_PCC_WINDOW)
-#define HD64461_PCC0_IO (HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)
-
-#define HD64461_PCC1_BASE 0xb4000000 /* area 5 */
-#define HD64461_PCC1_ATTR (HD64461_PCC1_BASE)
-#define HD64461_PCC1_COMM (HD64461_PCC1_BASE+HD64461_PCC_WINDOW)
-
-#define HD64461_STBCR 0x10000
-#define HD64461_STBCR_CKIO_STBY 0x2000
-#define HD64461_STBCR_SAFECKE_IST 0x1000
-#define HD64461_STBCR_SLCKE_IST 0x0800
-#define HD64461_STBCR_SAFECKE_OST 0x0400
-#define HD64461_STBCR_SLCKE_OST 0x0200
-#define HD64461_STBCR_SMIAST 0x0100
-#define HD64461_STBCR_SLCDST 0x0080
-#define HD64461_STBCR_SPC0ST 0x0040
-#define HD64461_STBCR_SPC1ST 0x0020
-#define HD64461_STBCR_SAFEST 0x0010
-#define HD64461_STBCR_STM0ST 0x0008
-#define HD64461_STBCR_STM1ST 0x0004
-#define HD64461_STBCR_SIRST 0x0002
-#define HD64461_STBCR_SURTST 0x0001
-
-#define HD64461_SYSCR 0x10002
-#define HD64461_SCPUCR 0x10004
-
-#define HD64461_LCDCBAR 0x11000
-#define HD64461_LCDCLOR 0x11002
-#define HD64461_LCDCCR 0x11004
-#define HD64461_LCDCCR_STBACK 0x0400
-#define HD64461_LCDCCR_STREQ 0x0100
-#define HD64461_LCDCCR_MOFF 0x0080
-#define HD64461_LCDCCR_REFSEL 0x0040
-#define HD64461_LCDCCR_EPON 0x0020
-#define HD64461_LCDCCR_SPON 0x0010
-
-#define HD64461_LDR1 0x11010
-#define HD64461_LDR1_DON 0x01
-#define HD64461_LDR1_DINV 0x80
-
-#define HD64461_LDR2 0x11012
-#define HD64461_LDHNCR 0x11014
-#define HD64461_LDHNSR 0x11016
-#define HD64461_LDVNTR 0x11018
-#define HD64461_LDVNDR 0x1101a
-#define HD64461_LDVSPR 0x1101c
-#define HD64461_LDR3 0x1101e
-
-#define HD64461_CPTWAR 0x11030
-#define HD64461_CPTWDR 0x11032
-#define HD64461_CPTRAR 0x11034
-#define HD64461_CPTRDR 0x11036
-
-#define HD64461_GRDOR 0x11040
-#define HD64461_GRSCR 0x11042
-#define HD64461_GRCFGR 0x11044
-#define HD64461_GRCFGR_ACCSTATUS 0x10
-#define HD64461_GRCFGR_ACCRESET 0x08
-#define HD64461_GRCFGR_ACCSTART_BITBLT 0x06
-#define HD64461_GRCFGR_ACCSTART_LINE 0x04
-#define HD64461_GRCFGR_COLORDEPTH16 0x01
-
-#define HD64461_LNSARH 0x11046
-#define HD64461_LNSARL 0x11048
-#define HD64461_LNAXLR 0x1104a
-#define HD64461_LNDGR 0x1104c
-#define HD64461_LNAXR 0x1104e
-#define HD64461_LNERTR 0x11050
-#define HD64461_LNMDR 0x11052
-#define HD64461_BBTSSARH 0x11054
-#define HD64461_BBTSSARL 0x11056
-#define HD64461_BBTDSARH 0x11058
-#define HD64461_BBTDSARL 0x1105a
-#define HD64461_BBTDWR 0x1105c
-#define HD64461_BBTDHR 0x1105e
-#define HD64461_BBTPARH 0x11060
-#define HD64461_BBTPARL 0x11062
-#define HD64461_BBTMARH 0x11064
-#define HD64461_BBTMARL 0x11066
-#define HD64461_BBTROPR 0x11068
-#define HD64461_BBTMDR 0x1106a
+#define HD64461_PCC_WINDOW 0x01000000
+
+/* Area 6 - Slot 0 - memory and/or IO card */
+#define HD64461_PCC0_BASE (CONFIG_HD64461_IOBASE + 0x8000000)
+#define HD64461_PCC0_ATTR (HD64461_PCC0_BASE) /* 0xb80000000 */
+#define HD64461_PCC0_COMM (HD64461_PCC0_BASE+HD64461_PCC_WINDOW) /* 0xb90000000 */
+#define HD64461_PCC0_IO (HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW) /* 0xba0000000 */
+
+/* Area 5 - Slot 1 - memory card only */
+#define HD64461_PCC1_BASE (CONFIG_HD64461_IOBASE + 0x4000000)
+#define HD64461_PCC1_ATTR (HD64461_PCC1_BASE) /* 0xb4000000 */
+#define HD64461_PCC1_COMM (HD64461_PCC1_BASE+HD64461_PCC_WINDOW) /* 0xb5000000 */
+
+/* Standby Control Register for HD64461 */
+#define HD64461_STBCR CONFIG_HD64461_IOBASE
+#define HD64461_STBCR_CKIO_STBY 0x2000
+#define HD64461_STBCR_SAFECKE_IST 0x1000
+#define HD64461_STBCR_SLCKE_IST 0x0800
+#define HD64461_STBCR_SAFECKE_OST 0x0400
+#define HD64461_STBCR_SLCKE_OST 0x0200
+#define HD64461_STBCR_SMIAST 0x0100
+#define HD64461_STBCR_SLCDST 0x0080
+#define HD64461_STBCR_SPC0ST 0x0040
+#define HD64461_STBCR_SPC1ST 0x0020
+#define HD64461_STBCR_SAFEST 0x0010
+#define HD64461_STBCR_STM0ST 0x0008
+#define HD64461_STBCR_STM1ST 0x0004
+#define HD64461_STBCR_SIRST 0x0002
+#define HD64461_STBCR_SURTST 0x0001
+
+/* System Configuration Register */
+#define HD64461_SYSCR (CONFIG_HD64461_IOBASE + 0x02)
+
+/* CPU Data Bus Control Register */
+#define HD64461_SCPUCR (CONFIG_HD64461_IOBASE + 0x04)
+
+/* Base Adress Register */
+#define HD64461_LCDCBAR (CONFIG_HD64461_IOBASE + 0x1000)
+
+/* Line increment adress */
+#define HD64461_LCDCLOR (CONFIG_HD64461_IOBASE + 0x1002)
+
+/* Controls LCD controller */
+#define HD64461_LCDCCR (CONFIG_HD64461_IOBASE + 0x1004)
+
+/* LCCDR control bits */
+#define HD64461_LCDCCR_STBACK 0x0400 /* Standby Back */
+#define HD64461_LCDCCR_STREQ 0x0100 /* Standby Request */
+#define HD64461_LCDCCR_MOFF 0x0080 /* Memory Off */
+#define HD64461_LCDCCR_REFSEL 0x0040 /* Refresh Select */
+#define HD64461_LCDCCR_EPON 0x0020 /* End Power On */
+#define HD64461_LCDCCR_SPON 0x0010 /* Start Power On */
+
+/* Controls LCD (1) */
+#define HD64461_LDR1 (CONFIG_HD64461_IOBASE + 0x1010)
+#define HD64461_LDR1_DON 0x01 /* Display On */
+#define HD64461_LDR1_DINV 0x80 /* Display Invert */
+
+/* Controls LCD (2) */
+#define HD64461_LDR2 (CONFIG_HD64461_IOBASE + 0x1012)
+#define HD64461_LDHNCR (CONFIG_HD64461_IOBASE + 0x1014) /* Number of horizontal characters */
+#define HD64461_LDHNSR (CONFIG_HD64461_IOBASE + 0x1016) /* Specify output start position + width of CL1 */
+#define HD64461_LDVNTR (CONFIG_HD64461_IOBASE + 0x1018) /* Specify total vertical lines */
+#define HD64461_LDVNDR (CONFIG_HD64461_IOBASE + 0x101a) /* specify number of display vertical lines */
+#define HD64461_LDVSPR (CONFIG_HD64461_IOBASE + 0x101c) /* specify vertical synchronization pos and AC nr */
+
+/* Controls LCD (3) */
+#define HD64461_LDR3 (CONFIG_HD64461_IOBASE + 0x101e)
+
+/* Palette Registers */
+#define HD64461_CPTWAR (CONFIG_HD64461_IOBASE + 0x1030) /* Color Palette Write Adress Register */
+#define HD64461_CPTWDR (CONFIG_HD64461_IOBASE + 0x1032) /* Color Palette Write Data Register */
+#define HD64461_CPTRAR (CONFIG_HD64461_IOBASE + 0x1034) /* Color Palette Read Adress Register */
+#define HD64461_CPTRDR (CONFIG_HD64461_IOBASE + 0x1036) /* Color Palette Read Data Register */
+
+#define HD64461_GRDOR (CONFIG_HD64461_IOBASE + 0x1040) /* Display Resolution Offset Register */
+#define HD64461_GRSCR (CONFIG_HD64461_IOBASE + 0x1042) /* Solid Color Register */
+#define HD64461_GRCFGR (CONFIG_HD64461_IOBASE + 0x1044) /* Accelerator Configuration Register */
+
+#define HD64461_GRCFGR_ACCSTATUS 0x10 /* Accelerator Status */
+#define HD64461_GRCFGR_ACCRESET 0x08 /* Accelerator Reset */
+#define HD64461_GRCFGR_ACCSTART_BITBLT 0x06 /* Accelerator Start BITBLT */
+#define HD64461_GRCFGR_ACCSTART_LINE 0x04 /* Accelerator Start Line Drawing */
+#define HD64461_GRCFGR_COLORDEPTH16 0x01 /* Sets Colordepth 16 for Accelerator */
+#define HD64461_GRCFGR_COLORDEPTH8 0x01 /* Sets Colordepth 8 for Accelerator */
+
+/* Line Drawing Registers */
+#define HD64461_LNSARH (CONFIG_HD64461_IOBASE + 0x1046) /* Line Start Adress Register (H) */
+#define HD64461_LNSARL (CONFIG_HD64461_IOBASE + 0x1048) /* Line Start Adress Register (L) */
+#define HD64461_LNAXLR (CONFIG_HD64461_IOBASE + 0x104a) /* Axis Pixel Length Register */
+#define HD64461_LNDGR (CONFIG_HD64461_IOBASE + 0x104c) /* Diagonal Register */
+#define HD64461_LNAXR (CONFIG_HD64461_IOBASE + 0x104e) /* Axial Register */
+#define HD64461_LNERTR (CONFIG_HD64461_IOBASE + 0x1050) /* Start Error Term Register */
+#define HD64461_LNMDR (CONFIG_HD64461_IOBASE + 0x1052) /* Line Mode Register */
+
+/* BitBLT Registers */
+#define HD64461_BBTSSARH (CONFIG_HD64461_IOBASE + 0x1054) /* Source Start Adress Register (H) */
+#define HD64461_BBTSSARL (CONFIG_HD64461_IOBASE + 0x1056) /* Source Start Adress Register (L) */
+#define HD64461_BBTDSARH (CONFIG_HD64461_IOBASE + 0x1058) /* Destination Start Adress Register (H) */
+#define HD64461_BBTDSARL (CONFIG_HD64461_IOBASE + 0x105a) /* Destination Start Adress Register (L) */
+#define HD64461_BBTDWR (CONFIG_HD64461_IOBASE + 0x105c) /* Destination Block Width Register */
+#define HD64461_BBTDHR (CONFIG_HD64461_IOBASE + 0x105e) /* Destination Block Height Register */
+#define HD64461_BBTPARH (CONFIG_HD64461_IOBASE + 0x1060) /* Pattern Start Adress Register (H) */
+#define HD64461_BBTPARL (CONFIG_HD64461_IOBASE + 0x1062) /* Pattern Start Adress Register (L) */
+#define HD64461_BBTMARH (CONFIG_HD64461_IOBASE + 0x1064) /* Mask Start Adress Register (H) */
+#define HD64461_BBTMARL (CONFIG_HD64461_IOBASE + 0x1066) /* Mask Start Adress Register (L) */
+#define HD64461_BBTROPR (CONFIG_HD64461_IOBASE + 0x1068) /* ROP Register */
+#define HD64461_BBTMDR (CONFIG_HD64461_IOBASE + 0x106a) /* BitBLT Mode Register */
/* PC Card Controller Registers */
-#define HD64461_PCC0ISR 0x12000 /* socket 0 interface status */
-#define HD64461_PCC0GCR 0x12002 /* socket 0 general control */
-#define HD64461_PCC0CSCR 0x12004 /* socket 0 card status change */
-#define HD64461_PCC0CSCIER 0x12006 /* socket 0 card status change interrupt enable */
-#define HD64461_PCC0SCR 0x12008 /* socket 0 software control */
-#define HD64461_PCC1ISR 0x12010 /* socket 1 interface status */
-#define HD64461_PCC1GCR 0x12012 /* socket 1 general control */
-#define HD64461_PCC1CSCR 0x12014 /* socket 1 card status change */
-#define HD64461_PCC1CSCIER 0x12016 /* socket 1 card status change interrupt enable */
-#define HD64461_PCC1SCR 0x12018 /* socket 1 software control */
+/* Maps to Physical Area 6 */
+#define HD64461_PCC0ISR (CONFIG_HD64461_IOBASE + 0x2000) /* socket 0 interface status */
+#define HD64461_PCC0GCR (CONFIG_HD64461_IOBASE + 0x2002) /* socket 0 general control */
+#define HD64461_PCC0CSCR (CONFIG_HD64461_IOBASE + 0x2004) /* socket 0 card status change */
+#define HD64461_PCC0CSCIER (CONFIG_HD64461_IOBASE + 0x2006) /* socket 0 card status change interrupt enable */
+#define HD64461_PCC0SCR (CONFIG_HD64461_IOBASE + 0x2008) /* socket 0 software control */
+/* Maps to Physical Area 5 */
+#define HD64461_PCC1ISR (CONFIG_HD64461_IOBASE + 0x2010) /* socket 1 interface status */
+#define HD64461_PCC1GCR (CONFIG_HD64461_IOBASE + 0x2012) /* socket 1 general control */
+#define HD64461_PCC1CSCR (CONFIG_HD64461_IOBASE + 0x2014) /* socket 1 card status change */
+#define HD64461_PCC1CSCIER (CONFIG_HD64461_IOBASE + 0x2016) /* socket 1 card status change interrupt enable */
+#define HD64461_PCC1SCR (CONFIG_HD64461_IOBASE + 0x2018) /* socket 1 software control */
/* PCC Interface Status Register */
-#define HD64461_PCCISR_READY 0x80 /* card ready */
-#define HD64461_PCCISR_MWP 0x40 /* card write-protected */
-#define HD64461_PCCISR_VS2 0x20 /* voltage select pin 2 */
-#define HD64461_PCCISR_VS1 0x10 /* voltage select pin 1 */
-#define HD64461_PCCISR_CD2 0x08 /* card detect 2 */
-#define HD64461_PCCISR_CD1 0x04 /* card detect 1 */
-#define HD64461_PCCISR_BVD2 0x02 /* battery 1 */
-#define HD64461_PCCISR_BVD1 0x01 /* battery 1 */
-
-#define HD64461_PCCISR_PCD_MASK 0x0c /* card detect */
-#define HD64461_PCCISR_BVD_MASK 0x03 /* battery voltage */
-#define HD64461_PCCISR_BVD_BATGOOD 0x03 /* battery good */
-#define HD64461_PCCISR_BVD_BATWARN 0x01 /* battery low warning */
-#define HD64461_PCCISR_BVD_BATDEAD1 0x02 /* battery dead */
-#define HD64461_PCCISR_BVD_BATDEAD2 0x00 /* battery dead */
+#define HD64461_PCCISR_READY 0x80 /* card ready */
+#define HD64461_PCCISR_MWP 0x40 /* card write-protected */
+#define HD64461_PCCISR_VS2 0x20 /* voltage select pin 2 */
+#define HD64461_PCCISR_VS1 0x10 /* voltage select pin 1 */
+#define HD64461_PCCISR_CD2 0x08 /* card detect 2 */
+#define HD64461_PCCISR_CD1 0x04 /* card detect 1 */
+#define HD64461_PCCISR_BVD2 0x02 /* battery 1 */
+#define HD64461_PCCISR_BVD1 0x01 /* battery 1 */
+
+#define HD64461_PCCISR_PCD_MASK 0x0c /* card detect */
+#define HD64461_PCCISR_BVD_MASK 0x03 /* battery voltage */
+#define HD64461_PCCISR_BVD_BATGOOD 0x03 /* battery good */
+#define HD64461_PCCISR_BVD_BATWARN 0x01 /* battery low warning */
+#define HD64461_PCCISR_BVD_BATDEAD1 0x02 /* battery dead */
+#define HD64461_PCCISR_BVD_BATDEAD2 0x00 /* battery dead */
/* PCC General Control Register */
-#define HD64461_PCCGCR_DRVE 0x80 /* output drive */
-#define HD64461_PCCGCR_PCCR 0x40 /* PC card reset */
-#define HD64461_PCCGCR_PCCT 0x20 /* PC card type, 1=IO&mem, 0=mem */
-#define HD64461_PCCGCR_VCC0 0x10 /* voltage control pin VCC0SEL0 */
-#define HD64461_PCCGCR_PMMOD 0x08 /* memory mode */
-#define HD64461_PCCGCR_PA25 0x04 /* pin A25 */
-#define HD64461_PCCGCR_PA24 0x02 /* pin A24 */
-#define HD64461_PCCGCR_REG 0x01 /* pin PCC0REG# */
+#define HD64461_PCCGCR_DRVE 0x80 /* output drive */
+#define HD64461_PCCGCR_PCCR 0x40 /* PC card reset */
+#define HD64461_PCCGCR_PCCT 0x20 /* PC card type, 1=IO&mem, 0=mem */
+#define HD64461_PCCGCR_VCC0 0x10 /* voltage control pin VCC0SEL0 */
+#define HD64461_PCCGCR_PMMOD 0x08 /* memory mode */
+#define HD64461_PCCGCR_PA25 0x04 /* pin A25 */
+#define HD64461_PCCGCR_PA24 0x02 /* pin A24 */
+#define HD64461_PCCGCR_REG 0x01 /* pin PCC0REG# */
/* PCC Card Status Change Register */
-#define HD64461_PCCCSCR_SCDI 0x80 /* sw card detect intr */
-#define HD64461_PCCCSCR_SRV1 0x40 /* reserved */
-#define HD64461_PCCCSCR_IREQ 0x20 /* IREQ intr req */
-#define HD64461_PCCCSCR_SC 0x10 /* STSCHG (status change) pin */
-#define HD64461_PCCCSCR_CDC 0x08 /* CD (card detect) change */
-#define HD64461_PCCCSCR_RC 0x04 /* READY change */
-#define HD64461_PCCCSCR_BW 0x02 /* battery warning change */
-#define HD64461_PCCCSCR_BD 0x01 /* battery dead change */
+#define HD64461_PCCCSCR_SCDI 0x80 /* sw card detect intr */
+#define HD64461_PCCCSCR_SRV1 0x40 /* reserved */
+#define HD64461_PCCCSCR_IREQ 0x20 /* IREQ intr req */
+#define HD64461_PCCCSCR_SC 0x10 /* STSCHG (status change) pin */
+#define HD64461_PCCCSCR_CDC 0x08 /* CD (card detect) change */
+#define HD64461_PCCCSCR_RC 0x04 /* READY change */
+#define HD64461_PCCCSCR_BW 0x02 /* battery warning change */
+#define HD64461_PCCCSCR_BD 0x01 /* battery dead change */
/* PCC Card Status Change Interrupt Enable Register */
-#define HD64461_PCCCSCIER_CRE 0x80 /* change reset enable */
-#define HD64461_PCCCSCIER_IREQE_MASK 0x60 /* IREQ enable */
-#define HD64461_PCCCSCIER_IREQE_DISABLED 0x00 /* IREQ disabled */
-#define HD64461_PCCCSCIER_IREQE_LEVEL 0x20 /* IREQ level-triggered */
-#define HD64461_PCCCSCIER_IREQE_FALLING 0x40 /* IREQ falling-edge-trig */
-#define HD64461_PCCCSCIER_IREQE_RISING 0x60 /* IREQ rising-edge-trig */
-
-#define HD64461_PCCCSCIER_SCE 0x10 /* status change enable */
-#define HD64461_PCCCSCIER_CDE 0x08 /* card detect change enable */
-#define HD64461_PCCCSCIER_RE 0x04 /* ready change enable */
-#define HD64461_PCCCSCIER_BWE 0x02 /* battery warn change enable */
-#define HD64461_PCCCSCIER_BDE 0x01 /* battery dead change enable*/
+#define HD64461_PCCCSCIER_CRE 0x80 /* change reset enable */
+#define HD64461_PCCCSCIER_IREQE_MASK 0x60 /* IREQ enable */
+#define HD64461_PCCCSCIER_IREQE_DISABLED 0x00 /* IREQ disabled */
+#define HD64461_PCCCSCIER_IREQE_LEVEL 0x20 /* IREQ level-triggered */
+#define HD64461_PCCCSCIER_IREQE_FALLING 0x40 /* IREQ falling-edge-trig */
+#define HD64461_PCCCSCIER_IREQE_RISING 0x60 /* IREQ rising-edge-trig */
+
+#define HD64461_PCCCSCIER_SCE 0x10 /* status change enable */
+#define HD64461_PCCCSCIER_CDE 0x08 /* card detect change enable */
+#define HD64461_PCCCSCIER_RE 0x04 /* ready change enable */
+#define HD64461_PCCCSCIER_BWE 0x02 /* battery warn change enable */
+#define HD64461_PCCCSCIER_BDE 0x01 /* battery dead change enable*/
/* PCC Software Control Register */
-#define HD64461_PCCSCR_VCC1 0x02 /* voltage control pin 1 */
-#define HD64461_PCCSCR_SWP 0x01 /* write protect */
-
-#define HD64461_P0OCR 0x1202a
-#define HD64461_P1OCR 0x1202c
-#define HD64461_PGCR 0x1202e
-
-#define HD64461_GPACR 0x14000
-#define HD64461_GPBCR 0x14002
-#define HD64461_GPCCR 0x14004
-#define HD64461_GPDCR 0x14006
-#define HD64461_GPADR 0x14010
-#define HD64461_GPBDR 0x14012
-#define HD64461_GPCDR 0x14014
-#define HD64461_GPDDR 0x14016
-#define HD64461_GPAICR 0x14020
-#define HD64461_GPBICR 0x14022
-#define HD64461_GPCICR 0x14024
-#define HD64461_GPDICR 0x14026
-#define HD64461_GPAISR 0x14040
-#define HD64461_GPBISR 0x14042
-#define HD64461_GPCISR 0x14044
-#define HD64461_GPDISR 0x14046
-
-#define HD64461_NIRR 0x15000
-#define HD64461_NIMR 0x15002
-
-#define HD64461_IRQBASE OFFCHIP_IRQ_BASE
-#define HD64461_IRQ_NUM 16
-
-#define HD64461_IRQ_UART (HD64461_IRQBASE+5)
-#define HD64461_IRQ_IRDA (HD64461_IRQBASE+6)
-#define HD64461_IRQ_TMU1 (HD64461_IRQBASE+9)
-#define HD64461_IRQ_TMU0 (HD64461_IRQBASE+10)
-#define HD64461_IRQ_GPIO (HD64461_IRQBASE+11)
-#define HD64461_IRQ_AFE (HD64461_IRQBASE+12)
-#define HD64461_IRQ_PCC1 (HD64461_IRQBASE+13)
-#define HD64461_IRQ_PCC0 (HD64461_IRQBASE+14)
+#define HD64461_PCCSCR_VCC1 0x02 /* voltage control pin 1 */
+#define HD64461_PCCSCR_SWP 0x01 /* write protect */
+
+/* PCC0 Output Pins Control Register */
+#define HD64461_P0OCR (CONFIG_HD64461_IOBASE + 0x202a)
+
+/* PCC1 Output Pins Control Register */
+#define HD64461_P1OCR (CONFIG_HD64461_IOBASE + 0x202c)
+
+/* PC Card General Control Register */
+#define HD64461_PGCR (CONFIG_HD64461_IOBASE + 0x202e)
+
+/* Port Control Registers */
+#define HD64461_GPACR (CONFIG_HD64461_IOBASE + 0x4000) /* Port A - Handles IRDA/TIMER */
+#define HD64461_GPBCR (CONFIG_HD64461_IOBASE + 0x4002) /* Port B - Handles UART */
+#define HD64461_GPCCR (CONFIG_HD64461_IOBASE + 0x4004) /* Port C - Handles PCMCIA 1 */
+#define HD64461_GPDCR (CONFIG_HD64461_IOBASE + 0x4006) /* Port D - Handles PCMCIA 1 */
+
+/* Port Control Data Registers */
+#define HD64461_GPADR (CONFIG_HD64461_IOBASE + 0x4010) /* A */
+#define HD64461_GPBDR (CONFIG_HD64461_IOBASE + 0x4012) /* B */
+#define HD64461_GPCDR (CONFIG_HD64461_IOBASE + 0x4014) /* C */
+#define HD64461_GPDDR (CONFIG_HD64461_IOBASE + 0x4016) /* D */
+
+/* Interrupt Control Registers */
+#define HD64461_GPAICR (CONFIG_HD64461_IOBASE + 0x4020) /* A */
+#define HD64461_GPBICR (CONFIG_HD64461_IOBASE + 0x4022) /* B */
+#define HD64461_GPCICR (CONFIG_HD64461_IOBASE + 0x4024) /* C */
+#define HD64461_GPDICR (CONFIG_HD64461_IOBASE + 0x4026) /* D */
+
+/* Interrupt Status Registers */
+#define HD64461_GPAISR (CONFIG_HD64461_IOBASE + 0x4040) /* A */
+#define HD64461_GPBISR (CONFIG_HD64461_IOBASE + 0x4042) /* B */
+#define HD64461_GPCISR (CONFIG_HD64461_IOBASE + 0x4044) /* C */
+#define HD64461_GPDISR (CONFIG_HD64461_IOBASE + 0x4046) /* D */
+
+/* Interrupt Request Register & Interrupt Mask Register */
+#define HD64461_NIRR (CONFIG_HD64461_IOBASE + 0x5000)
+#define HD64461_NIMR (CONFIG_HD64461_IOBASE + 0x5002)
+
+#define HD64461_IRQBASE OFFCHIP_IRQ_BASE
+#define HD64461_IRQ_NUM 16
+
+#define HD64461_IRQ_UART (HD64461_IRQBASE+5)
+#define HD64461_IRQ_IRDA (HD64461_IRQBASE+6)
+#define HD64461_IRQ_TMU1 (HD64461_IRQBASE+9)
+#define HD64461_IRQ_TMU0 (HD64461_IRQBASE+10)
+#define HD64461_IRQ_GPIO (HD64461_IRQBASE+11)
+#define HD64461_IRQ_AFE (HD64461_IRQBASE+12)
+#define HD64461_IRQ_PCC1 (HD64461_IRQBASE+13)
+#define HD64461_IRQ_PCC0 (HD64461_IRQBASE+14)
#define __IO_PREFIX hd64461
#include <asm/io_generic.h>
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 80ee1cda7498..4ca3f765bacc 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -5,4 +5,46 @@
extern atomic_t irq_err_count;
+struct intc2_data {
+ unsigned short irq;
+ unsigned char ipr_offset, ipr_shift;
+ unsigned char msk_offset, msk_shift;
+ unsigned char priority;
+};
+
+struct intc2_desc {
+ unsigned long prio_base;
+ unsigned long msk_base;
+ unsigned long mskclr_base;
+ struct intc2_data *intc2_data;
+ unsigned int nr_irqs;
+ struct irq_chip chip;
+};
+
+void register_intc2_controller(struct intc2_desc *);
+void init_IRQ_intc2(void);
+
+struct ipr_data {
+ unsigned char irq;
+ unsigned char ipr_idx; /* Index for the IPR registered */
+ unsigned char shift; /* Number of bits to shift the data */
+ unsigned char priority; /* The priority */
+};
+
+struct ipr_desc {
+ unsigned long *ipr_offsets;
+ unsigned int nr_offsets;
+ struct ipr_data *ipr_data;
+ unsigned int nr_irqs;
+ struct irq_chip chip;
+};
+
+void register_ipr_controller(struct ipr_desc *);
+void init_IRQ_ipr(void);
+
+/*
+ * Enable individual interrupt mode for external IPR IRQs.
+ */
+void ipr_irq_enable_irlm(void);
+
#endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index e81bf21c801e..c61d902b8bff 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -31,47 +31,7 @@ extern unsigned short *irq_mask_register;
* PINT IRQs
*/
void init_IRQ_pint(void);
-
-/*
- * The shift value is now the number of bits to shift, not the number of
- * bits/4. This is to make it easier to read the value directly from the
- * datasheets. The IPR address, addr, will be set from ipr_idx via the
- * map_ipridx_to_addr function.
- */
-struct ipr_data {
- unsigned int irq;
- int ipr_idx; /* Index for the IPR registered */
- int shift; /* Number of bits to shift the data */
- int priority; /* The priority */
- unsigned int addr; /* Address of Interrupt Priority Register */
-};
-
-/*
- * Given an IPR IDX, map the value to an IPR register address.
- */
-unsigned int map_ipridx_to_addr(int idx);
-
-/*
- * Enable individual interrupt mode for external IPR IRQs.
- */
-void ipr_irq_enable_irlm(void);
-
-/*
- * Function for "on chip support modules".
- */
-void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
void make_imask_irq(unsigned int irq);
-void init_IRQ_ipr(void);
-
-struct intc2_data {
- unsigned short irq;
- unsigned char ipr_offset, ipr_shift;
- unsigned char msk_offset, msk_shift;
- unsigned char priority;
-};
-
-void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs);
-void init_IRQ_intc2(void);
static inline int generic_irq_demux(int irq)
{
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
index 70389b72ffef..088698bacf2f 100644
--- a/include/asm-sh/machvec.h
+++ b/include/asm-sh/machvec.h
@@ -13,7 +13,6 @@
#include <linux/types.h>
#include <linux/time.h>
#include <asm/machtypes.h>
-#include <asm/machvec_init.h>
struct device;
@@ -68,4 +67,7 @@ extern struct sh_machine_vector sh_mv;
#define get_system_type() sh_mv.mv_name
+#define __initmv \
+ __attribute_used__ __attribute__((__section__ (".machvec.init")))
+
#endif /* _ASM_SH_MACHVEC_H */
diff --git a/include/asm-sh/machvec_init.h b/include/asm-sh/machvec_init.h
deleted file mode 100644
index e397798ebd94..000000000000
--- a/include/asm-sh/machvec_init.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * include/asm-sh/machvec_init.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * This file has goodies to help simplify instantiation of machine vectors.
- */
-
-#ifndef __SH_MACHVEC_INIT_H
-#define __SH_MACHVEC_INIT_H
-
-
-/*
- * In a GENERIC kernel, we have lots of these vectors floating about,
- * all but one of which we want to go away. In a non-GENERIC kernel,
- * we want only one, ever.
- *
- * Accomplish this in the GENERIC kernel by puting all of the vectors
- * in the .init.data section where they'll go away. We'll copy the
- * one we want to the real alpha_mv vector in setup_arch.
- *
- * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
- * one of the vectors, which will not reside in .init.data. We then
- * alias this one vector to alpha_mv, so no copy is needed.
- *
- * Upshot: set __initdata to nothing for non-GENERIC kernels.
- *
- * Note we do the same thing for the UNKNOWN kernel, as we need to write
- * to the machine vector while setting it up.
- */
-
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
-#define __initmv __attribute__((unused,__section__ (".machvec.init")))
-#define ALIAS_MV(x)
-#else
-#define __initmv
-
-/* GCC actually has a syntax for defining aliases, but is under some
- delusion that you shouldn't be able to declare it extern somewhere
- else beforehand. Fine. We'll do it ourselves. */
-#if 0
-#define ALIAS_MV(system) \
- struct sh_machine_vector sh_mv __attribute__((alias("mv_"#system)));
-#else
-#define ALIAS_MV(system) \
- asm(".global sh_mv\nsh_mv = mv_"#system );
-#endif
-#endif /* GENERIC */
-
-#endif /* __SH_MACHVEC_INIT_H */
diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h
new file mode 100644
index 000000000000..7969f381dff2
--- /dev/null
+++ b/include/asm-sh/mmzone.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_SH_MMZONE_H
+#define __ASM_SH_MMZONE_H
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid) (node_data[nid])
+
+#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
+ NODE_DATA(nid)->node_spanned_pages)
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+ int nid;
+
+ for (nid = 0; nid < MAX_NUMNODES; nid++)
+ if (pfn >= node_start_pfn(nid) && pfn <= node_end_pfn(nid))
+ break;
+
+ return nid;
+}
+
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+ return NODE_DATA(pfn_to_nid(pfn));
+}
+
+/* arch/sh/mm/numa.c */
+void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end);
+#else
+static inline void
+setup_bootmem_node(int nid, unsigned long start, unsigned long end)
+{
+}
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+/* Platform specific mem init */
+void __init plat_mem_setup(void);
+
+/* arch/sh/kernel/setup.c */
+void __init setup_bootmem_allocator(unsigned long start_pfn);
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_MMZONE_H */
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 7464de4ba07d..6bc9bba10105 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -60,6 +60,7 @@ extern void (*copy_page)(void *to, void *from);
extern unsigned long shm_align_mask;
extern unsigned long max_low_pfn, min_low_pfn;
+extern unsigned long memory_start, memory_end;
#ifdef CONFIG_MMU
extern void clear_page_slow(void *to);
@@ -134,7 +135,9 @@ typedef struct { unsigned long pgd; } pgd_t;
#define PFN_START (__MEMORY_START >> PAGE_SHIFT)
#define ARCH_PFN_OFFSET (PFN_START)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#ifdef CONFIG_FLATMEM
#define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
+#endif
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
@@ -148,5 +151,12 @@ typedef struct { unsigned long pgd; } pgd_t;
#define __HAVE_ARCH_GATE_AREA
#endif
+/*
+ * Slub defaults to 8-byte alignment, we're only interested in 4.
+ * Slab defaults to BYTES_PER_WORD, which ends up being the same anyways.
+ */
+#define ARCH_KMALLOC_MINALIGN 4
+#define ARCH_SLAB_MINALIGN 4
+
#endif /* __KERNEL__ */
#endif /* __ASM_SH_PAGE_H */
diff --git a/include/asm-sh/parport.h b/include/asm-sh/parport.h
new file mode 100644
index 000000000000..f67ba60a2acd
--- /dev/null
+++ b/include/asm-sh/parport.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ */
+#ifndef __ASM_SH_PARPORT_H
+#define __ASM_SH_PARPORT_H
+
+static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
+
+static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
+{
+ return parport_pc_find_isa_ports(autoirq, autodma);
+}
+
+#endif /* __ASM_SH_PARPORT_H */
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 5b523c7e7d99..22efffe45019 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -402,12 +402,8 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define pte_file(pte) (pte_val(pte) & _PAGE_FILE)
#ifdef CONFIG_X2TLB
-#define pte_read(pte) ((pte).pte_high & _PAGE_EXT_USER_READ)
-#define pte_exec(pte) ((pte).pte_high & _PAGE_EXT_USER_EXEC)
#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE)
#else
-#define pte_read(pte) (pte_val(pte) & _PAGE_USER)
-#define pte_exec(pte) (pte_val(pte) & _PAGE_USER)
#define pte_write(pte) (pte_val(pte) & _PAGE_RW)
#endif
@@ -420,20 +416,12 @@ static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; }
* individually toggled (and user permissions are entirely decoupled from
* kernel permissions), we attempt to couple them a bit more sanely here.
*/
-PTE_BIT_FUNC(high, rdprotect, &= ~_PAGE_EXT_USER_READ);
-PTE_BIT_FUNC(high, mkread, |= _PAGE_EXT_USER_READ | _PAGE_EXT_KERN_READ);
PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE);
PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
-PTE_BIT_FUNC(high, exprotect, &= ~_PAGE_EXT_USER_EXEC);
-PTE_BIT_FUNC(high, mkexec, |= _PAGE_EXT_USER_EXEC | _PAGE_EXT_KERN_EXEC);
PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
#else
-PTE_BIT_FUNC(low, rdprotect, &= ~_PAGE_USER);
-PTE_BIT_FUNC(low, mkread, |= _PAGE_USER);
PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW);
PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW);
-PTE_BIT_FUNC(low, exprotect, &= ~_PAGE_USER);
-PTE_BIT_FUNC(low, mkexec, |= _PAGE_USER);
PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE);
#endif
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index d42f68e724fa..2252e75daa26 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -36,7 +36,7 @@
*/
enum cpu_type {
/* SH-2 types */
- CPU_SH7604, CPU_SH7619,
+ CPU_SH7619,
/* SH-2A types */
CPU_SH7206,
@@ -52,7 +52,7 @@ enum cpu_type {
CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
/* SH-4A types */
- CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+ CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
/* SH4AL-DSP types */
CPU_SH73180, CPU_SH7343, CPU_SH7722,
@@ -228,11 +228,7 @@ static __inline__ void grab_fpu(struct pt_regs *regs)
regs->sr &= ~SR_FD;
}
-#ifdef CONFIG_CPU_SH4
extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs);
-#else
-#define save_fpu(tsk) do { } while (0)
-#endif
#define unlazy_fpu(tsk, regs) do { \
if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \
diff --git a/include/asm-sh/rwsem.h b/include/asm-sh/rwsem.h
index 4931ba817d73..1987f3ea7f1b 100644
--- a/include/asm-sh/rwsem.h
+++ b/include/asm-sh/rwsem.h
@@ -1,11 +1,15 @@
/*
- * include/asm-ppc/rwsem.h: R/W semaphores for SH using the stuff
+ * include/asm-sh/rwsem.h: R/W semaphores for SH using the stuff
* in lib/rwsem.c.
*/
#ifndef _ASM_SH_RWSEM_H
#define _ASM_SH_RWSEM_H
+#ifndef _LINUX_RWSEM_H
+#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
+#endif
+
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/spinlock.h>
diff --git a/include/asm-sh/saturn/io.h b/include/asm-sh/saturn/io.h
deleted file mode 100644
index f1b9b5d633f4..000000000000
--- a/include/asm-sh/saturn/io.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-sh/saturn/io.h
- *
- * I/O functions for use on the Sega Saturn.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#ifndef __ASM_SH_SATURN_IO_H
-#define __ASM_SH_SATURN_IO_H
-
-/* arch/sh/boards/saturn/io.c */
-extern unsigned long saturn_isa_port2addr(unsigned long offset);
-extern void *saturn_ioremap(unsigned long offset, unsigned long size);
-extern void saturn_iounmap(void *addr);
-
-#endif /* __ASM_SH_SATURN_IO_H */
-
diff --git a/include/asm-sh/saturn/smpc.h b/include/asm-sh/saturn/smpc.h
deleted file mode 100644
index 5de5c12d6347..000000000000
--- a/include/asm-sh/saturn/smpc.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * include/asm-sh/saturn/smpc.h
- *
- * System Manager / Peripheral Control definitions.
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * Released under the terms of the GNU GPL v2.0.
- */
-#ifndef __ASM_SH_SATURN_SMPC_H
-#define __ASM_SH_SATURN_SMPC_H
-
-#include <asm/io.h>
-
-#define SMPC_COMMAND 0x2010001f /* SMPC command register */
-#define SMPC_RESULT 0x2010005f /* SMPC result register */
-#define SMPC_STATUS 0x20100063 /* SMPC status register */
-
-#define SMPC_CMD_MSHON 0x0001 /* Master SH On */
-#define SMPC_CMD_SSHON 0x0002 /* Slave SH On */
-#define SMPC_CMD_SSHOFF 0x0003 /* Slave SH Off */
-#define SMPC_CMD_SNDON 0x0004 /* Sound On */
-#define SMPC_CMD_SNDOFF 0x0005 /* Sound Off */
-#define SMPC_CMD_CDON 0x0006 /* CD On */
-#define SMPC_CMD_CDOFF 0x0007 /* CD Off */
-
-static inline void smpc_barrier(void)
-{
- while ((ctrl_inb(SMPC_STATUS) & 0x0001) == 0x0001)
- ;
-}
-
-#endif /* __ASM_SH_SATURN_SMPC_H */
-
diff --git a/include/asm-sh/sections.h b/include/asm-sh/sections.h
index 57abd708b236..2a696b8ee4f5 100644
--- a/include/asm-sh/sections.h
+++ b/include/asm-sh/sections.h
@@ -3,7 +3,7 @@
#include <asm-generic/sections.h>
-extern char _end[];
+extern long __machvec_start, __machvec_end;
#endif /* __ASM_SH_SECTIONS_H */
diff --git a/include/asm-sh/setup.h b/include/asm-sh/setup.h
index 1583c6b7bdaa..586a9711a75d 100644
--- a/include/asm-sh/setup.h
+++ b/include/asm-sh/setup.h
@@ -6,6 +6,7 @@
#ifdef __KERNEL__
int setup_early_printk(char *);
+void sh_mv_setup(void);
#endif /* __KERNEL__ */
diff --git a/include/asm-sh/sh03/io.h b/include/asm-sh/sh03/io.h
index df3b187ef883..4ff1eb900301 100644
--- a/include/asm-sh/sh03/io.h
+++ b/include/asm-sh/sh03/io.h
@@ -14,22 +14,18 @@
#define INTC_IPRD 0xffd00010UL
#define IRL0_IRQ 2
-#define IRL0_IPR_ADDR INTC_IPRD
#define IRL0_IPR_POS 3
#define IRL0_PRIORITY 13
#define IRL1_IRQ 5
-#define IRL1_IPR_ADDR INTC_IPRD
#define IRL1_IPR_POS 2
#define IRL1_PRIORITY 10
#define IRL2_IRQ 8
-#define IRL2_IPR_ADDR INTC_IPRD
#define IRL2_IPR_POS 1
#define IRL2_PRIORITY 7
#define IRL3_IRQ 11
-#define IRL3_IPR_ADDR INTC_IPRD
#define IRL3_IPR_POS 0
#define IRL3_PRIORITY 4
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index caa7b93f1bce..b99ca786c0c1 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -39,4 +39,6 @@ extern struct smp_fn_call_struct smp_fn_call;
#endif /* CONFIG_SMP */
+#define hard_smp_processor_id() (0)
+
#endif /* __ASM_SH_SMP_H */
diff --git a/include/asm-sh/snapgear.h b/include/asm-sh/snapgear.h
index 2d712e72c9e5..3554e3a74e99 100644
--- a/include/asm-sh/snapgear.h
+++ b/include/asm-sh/snapgear.h
@@ -20,22 +20,18 @@
*/
#define IRL0_IRQ 2
-#define IRL0_IPR_ADDR INTC_IPRD
#define IRL0_IPR_POS 3
#define IRL0_PRIORITY 13
#define IRL1_IRQ 5
-#define IRL1_IPR_ADDR INTC_IPRD
#define IRL1_IPR_POS 2
#define IRL1_PRIORITY 10
#define IRL2_IRQ 8
-#define IRL2_IPR_ADDR INTC_IPRD
#define IRL2_IPR_POS 1
#define IRL2_PRIORITY 7
#define IRL3_IRQ 11
-#define IRL3_IPR_ADDR INTC_IPRD
#define IRL3_IPR_POS 0
#define IRL3_PRIORITY 4
#endif
diff --git a/include/asm-sh/sparsemem.h b/include/asm-sh/sparsemem.h
new file mode 100644
index 000000000000..547a540b6667
--- /dev/null
+++ b/include/asm-sh/sparsemem.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_SH_SPARSEMEM_H
+#define __ASM_SH_SPARSEMEM_H
+
+#ifdef __KERNEL__
+/*
+ * SECTION_SIZE_BITS 2^N: how big each section will be
+ * MAX_PHYSADDR_BITS 2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS 26
+#define MAX_PHYSADDR_BITS 32
+#define MAX_PHYSMEM_BITS 32
+
+#endif
+
+#endif /* __ASM_SH_SPARSEMEM_H */
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 82f3e229e621..7c75045ae22b 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -8,9 +8,13 @@
#include <linux/irqflags.h>
#include <linux/compiler.h>
+#include <linux/linkage.h>
#include <asm/types.h>
#include <asm/ptrace.h>
+struct task_struct *__switch_to(struct task_struct *prev,
+ struct task_struct *next);
+
/*
* switch_to() should switch tasks to task nr n, first
*/
@@ -122,7 +126,7 @@ static inline void sched_cacheflush(void)
#define smp_read_barrier_depends() do { } while(0)
#endif
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
/*
* Jump to P2 area.
@@ -271,6 +275,16 @@ extern unsigned int instruction_size(unsigned int insn);
void disable_hlt(void);
void enable_hlt(void);
+void default_idle(void);
+
+asmlinkage void break_point_trap(void);
+asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs);
+asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs);
+
#define arch_align_stack(x) (x)
#endif
diff --git a/include/asm-sh/topology.h b/include/asm-sh/topology.h
index cff001c316fe..f402a3b1cfa4 100644
--- a/include/asm-sh/topology.h
+++ b/include/asm-sh/topology.h
@@ -1,6 +1,36 @@
#ifndef _ASM_SH_TOPOLOGY_H
#define _ASM_SH_TOPOLOGY_H
+#ifdef CONFIG_NUMA
+
+/* sched_domains SD_NODE_INIT for sh machines */
+#define SD_NODE_INIT (struct sched_domain) { \
+ .span = CPU_MASK_NONE, \
+ .parent = NULL, \
+ .child = NULL, \
+ .groups = NULL, \
+ .min_interval = 8, \
+ .max_interval = 32, \
+ .busy_factor = 32, \
+ .imbalance_pct = 125, \
+ .cache_nice_tries = 2, \
+ .busy_idx = 3, \
+ .idle_idx = 2, \
+ .newidle_idx = 0, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
+ .flags = SD_LOAD_BALANCE \
+ | SD_BALANCE_FORK \
+ | SD_BALANCE_EXEC \
+ | SD_SERIALIZE \
+ | SD_WAKE_BALANCE, \
+ .last_balance = jiffies, \
+ .balance_interval = 1, \
+ .nr_balance_failed = 0, \
+}
+
+#endif
+
#include <asm-generic/topology.h>
#endif /* _ASM_SH_TOPOLOGY_H */
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index 5c49ed6715f2..f18a1a5c95c0 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -61,8 +61,6 @@ static inline void set_fs(mm_segment_t s)
*/
static inline int __access_ok(unsigned long addr, unsigned long size)
{
- extern unsigned long memory_start, memory_end;
-
return ((addr >= memory_start) && ((addr + size) < memory_end));
}
#else /* CONFIG_MMU */
@@ -76,7 +74,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
* __access_ok: Check if address with size is OK or not.
*
* We do three checks:
- * (1) is it user space?
+ * (1) is it user space?
* (2) addr + size --> carry?
* (3) addr + size >= 0x80000000 (PAGE_OFFSET)
*
@@ -142,11 +140,12 @@ static inline int access_ok(int type, const void __user *p, unsigned long size)
__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+#define __m(x) (*(struct __large_struct __user *)(x))
#define __get_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
+ __chk_user_ptr(ptr); \
switch (size) { \
case 1: \
__get_user_asm(x, ptr, retval, "b"); \
@@ -175,6 +174,7 @@ do { \
#define __get_user_check(x,ptr,size) \
({ \
long __gu_err, __gu_val; \
+ __chk_user_ptr(ptr); \
switch (size) { \
case 1: \
__get_user_1(__gu_val, (ptr), __gu_err); \
@@ -300,6 +300,7 @@ extern void __get_user_unknown(void);
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
+ __chk_user_ptr(ptr); \
switch (size) { \
case 1: \
__put_user_asm(x, ptr, retval, "b"); \
@@ -328,7 +329,7 @@ do { \
#define __put_user_check(x,ptr,size) \
({ \
long __pu_err = -EFAULT; \
- __typeof__(*(ptr)) *__pu_addr = (ptr); \
+ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
\
if (__access_ok((unsigned long)__pu_addr,size)) \
__put_user_size((x),__pu_addr,(size),__pu_err); \
@@ -406,10 +407,10 @@ __asm__ __volatile__( \
#endif
extern void __put_user_unknown(void);
-
+
/* Generic arbitrary sized copy. */
/* Return the number of bytes NOT copied */
-extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
#define copy_to_user(to,from,n) ({ \
void *__copy_to = (void *) (to); \
@@ -420,14 +421,6 @@ __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \
} else __copy_res = __copy_size; \
__copy_res; })
-#define __copy_to_user(to,from,n) \
- __copy_user((void *)(to), \
- (void *)(from), n)
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-
#define copy_from_user(to,from,n) ({ \
void *__copy_to = (void *) (to); \
void *__copy_from = (void *) (from); \
@@ -438,9 +431,20 @@ __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
} else __copy_res = __copy_size; \
__copy_res; })
-#define __copy_from_user(to,from,n) \
- __copy_user((void *)(to), \
- (void *)(from), n)
+static __always_inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+ return __copy_user(to, (__force void *)from, n);
+}
+
+static __always_inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+ return __copy_user((__force void *)to, from, n);
+}
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
/*
* Clear the area and return remaining number of bytes
diff --git a/include/asm-sh/ubc.h b/include/asm-sh/ubc.h
index ae9bbdeefbe1..38d46e01b846 100644
--- a/include/asm-sh/ubc.h
+++ b/include/asm-sh/ubc.h
@@ -51,9 +51,14 @@
#define BRCR_UBDE (1 << 0)
#ifndef __ASSEMBLY__
-/* arch/sh/kernel/ubc.S */
-extern void ubc_wakeup(void);
+/* arch/sh/kernel/cpu/ubc.S */
extern void ubc_sleep(void);
+
+#ifdef CONFIG_UBC_WAKEUP
+extern void ubc_wakeup(void);
+#else
+#define ubc_wakeup() do { } while (0)
+#endif
#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-sh64/fb.h b/include/asm-sh64/fb.h
new file mode 100644
index 000000000000..d92e99cd8c8a
--- /dev/null
+++ b/include/asm-sh64/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index b875482eb592..3488fe32e436 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -415,22 +415,15 @@ extern void __handle_bad_pmd_kernel(pmd_t * pmd);
/*
* The following have defined behavior only work if pte_present() is true.
*/
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXECUTE; }
static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
-static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
-
-static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
-static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
diff --git a/include/asm-sparc/fb.h b/include/asm-sparc/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-sparc/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 59229aeba27b..a55f4c3488b0 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -151,7 +151,6 @@ BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page_vaddr, pgd_t)
BTFIXUPDEF_SETHI(none_mask)
BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
-BTFIXUPDEF_CALL(int, pte_read, pte_t)
static inline int pte_none(pte_t pte)
{
@@ -160,7 +159,6 @@ static inline int pte_none(pte_t pte)
#define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
-#define pte_read(pte) BTFIXUP_CALL(pte_read)(pte)
BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index bf39d86c0c9e..11ade6841971 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -4,12 +4,7 @@
*/
#include <asm/sstate.h>
-extern unsigned long loops_per_jiffy;
-
static void __init check_bugs(void)
{
-#ifndef CONFIG_SMP
- cpu_data(0).udelay_val = loops_per_jiffy;
-#endif
sstate_running();
}
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index 36511ca51416..01fe6682b405 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -31,8 +31,10 @@ typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index 445026fbec35..98a6e609163e 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -19,7 +19,7 @@ typedef struct {
unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
unsigned int __pad0;
unsigned long clock_tick; /* %tick's per second */
- unsigned long udelay_val;
+ unsigned long __pad;
unsigned int __pad1;
unsigned int __pad2;
@@ -80,7 +80,8 @@ struct trap_per_cpu {
unsigned int dev_mondo_qmask;
unsigned int resum_qmask;
unsigned int nonresum_qmask;
- unsigned int __pad2[3];
+ unsigned int __pad2[1];
+ void *hdesc;
} __attribute__((aligned(64)));
extern struct trap_per_cpu trap_block[NR_CPUS];
extern void init_cur_cpu_trap(struct thread_info *);
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
index a4aae6f80627..a77aa622d762 100644
--- a/include/asm-sparc64/delay.h
+++ b/include/asm-sparc64/delay.h
@@ -1,37 +1,17 @@
/* delay.h: Linux delay routines on sparc64.
*
- * Copyright (C) 1996, 2004 David S. Miller (davem@davemloft.net).
- *
- * Based heavily upon x86 variant which is:
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/sparc64/lib/delay.c
+ * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
*/
-#ifndef __SPARC64_DELAY_H
-#define __SPARC64_DELAY_H
-
-#include <linux/param.h>
-#include <asm/cpudata.h>
+#ifndef _SPARC64_DELAY_H
+#define _SPARC64_DELAY_H
#ifndef __ASSEMBLY__
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
- __udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
- __ndelay(n))
+extern void udelay(unsigned long usecs);
+#define mdelay(n) udelay((n) * 1000)
#endif /* !__ASSEMBLY__ */
-#endif /* defined(__SPARC64_DELAY_H) */
+#endif /* _SPARC64_DELAY_H */
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h
new file mode 100644
index 000000000000..d6cd3a175fc3
--- /dev/null
+++ b/include/asm-sparc64/fb.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-sparc64/hvtramp.h b/include/asm-sparc64/hvtramp.h
new file mode 100644
index 000000000000..c7dd6ad056df
--- /dev/null
+++ b/include/asm-sparc64/hvtramp.h
@@ -0,0 +1,37 @@
+#ifndef _SPARC64_HVTRAP_H
+#define _SPARC64_HVTRAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct hvtramp_mapping {
+ __u64 vaddr;
+ __u64 tte;
+};
+
+struct hvtramp_descr {
+ __u32 cpu;
+ __u32 num_mappings;
+ __u64 fault_info_va;
+ __u64 fault_info_pa;
+ __u64 thread_reg;
+ struct hvtramp_mapping maps[2];
+};
+
+extern void hv_cpu_startup(unsigned long hvdescr_pa);
+
+#endif
+
+#define HVTRAMP_DESCR_CPU 0x00
+#define HVTRAMP_DESCR_NUM_MAPPINGS 0x04
+#define HVTRAMP_DESCR_FAULT_INFO_VA 0x08
+#define HVTRAMP_DESCR_FAULT_INFO_PA 0x10
+#define HVTRAMP_DESCR_THREAD_REG 0x18
+#define HVTRAMP_DESCR_MAPS 0x20
+
+#define HVTRAMP_MAPPING_VADDR 0x00
+#define HVTRAMP_MAPPING_TTE 0x08
+#define HVTRAMP_MAPPING_SIZE 0x10
+
+#endif /* _SPARC64_HVTRAP_H */
diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h
index db2130a95d68..524d49835dfd 100644
--- a/include/asm-sparc64/hypervisor.h
+++ b/include/asm-sparc64/hypervisor.h
@@ -98,7 +98,7 @@
#define HV_FAST_MACH_EXIT 0x00
#ifndef __ASSEMBLY__
-extern void sun4v_mach_exit(unsigned long exit_core);
+extern void sun4v_mach_exit(unsigned long exit_code);
#endif
/* Domain services. */
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 90781e34a95c..e6c436ef9356 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -53,6 +53,8 @@ extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
extern void sun4v_destroy_msi(unsigned int virt_irq);
extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
+extern void fixup_irqs(void);
+
static __inline__ void set_softint(unsigned long bits)
{
__asm__ __volatile__("wr %0, 0x0, %%set_softint"
diff --git a/include/asm-sparc64/ldc.h b/include/asm-sparc64/ldc.h
new file mode 100644
index 000000000000..bdb524a7b814
--- /dev/null
+++ b/include/asm-sparc64/ldc.h
@@ -0,0 +1,138 @@
+#ifndef _SPARC64_LDC_H
+#define _SPARC64_LDC_H
+
+#include <asm/hypervisor.h>
+
+extern int ldom_domaining_enabled;
+extern void ldom_set_var(const char *var, const char *value);
+extern void ldom_reboot(const char *boot_command);
+extern void ldom_power_off(void);
+
+/* The event handler will be evoked when link state changes
+ * or data becomes available on the receive side.
+ *
+ * For non-RAW links, if the LDC_EVENT_RESET event arrives the
+ * driver should reset all of it's internal state and reinvoke
+ * ldc_connect() to try and bring the link up again.
+ *
+ * For RAW links, ldc_connect() is not used. Instead the driver
+ * just waits for the LDC_EVENT_UP event.
+ */
+struct ldc_channel_config {
+ void (*event)(void *arg, int event);
+
+ u32 mtu;
+ unsigned int rx_irq;
+ unsigned int tx_irq;
+ u8 mode;
+#define LDC_MODE_RAW 0x00
+#define LDC_MODE_UNRELIABLE 0x01
+#define LDC_MODE_RESERVED 0x02
+#define LDC_MODE_STREAM 0x03
+
+ u8 debug;
+#define LDC_DEBUG_HS 0x01
+#define LDC_DEBUG_STATE 0x02
+#define LDC_DEBUG_RX 0x04
+#define LDC_DEBUG_TX 0x08
+#define LDC_DEBUG_DATA 0x10
+};
+
+#define LDC_EVENT_RESET 0x01
+#define LDC_EVENT_UP 0x02
+#define LDC_EVENT_DATA_READY 0x04
+
+#define LDC_STATE_INVALID 0x00
+#define LDC_STATE_INIT 0x01
+#define LDC_STATE_BOUND 0x02
+#define LDC_STATE_READY 0x03
+#define LDC_STATE_CONNECTED 0x04
+
+struct ldc_channel;
+
+/* Allocate state for a channel. */
+extern struct ldc_channel *ldc_alloc(unsigned long id,
+ const struct ldc_channel_config *cfgp,
+ void *event_arg);
+
+/* Shut down and free state for a channel. */
+extern void ldc_free(struct ldc_channel *lp);
+
+/* Register TX and RX queues of the link with the hypervisor. */
+extern int ldc_bind(struct ldc_channel *lp, const char *name);
+
+/* For non-RAW protocols we need to complete a handshake before
+ * communication can proceed. ldc_connect() does that, if the
+ * handshake completes successfully, an LDC_EVENT_UP event will
+ * be sent up to the driver.
+ */
+extern int ldc_connect(struct ldc_channel *lp);
+extern int ldc_disconnect(struct ldc_channel *lp);
+
+extern int ldc_state(struct ldc_channel *lp);
+
+/* Read and write operations. Only valid when the link is up. */
+extern int ldc_write(struct ldc_channel *lp, const void *buf,
+ unsigned int size);
+extern int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
+
+#define LDC_MAP_SHADOW 0x01
+#define LDC_MAP_DIRECT 0x02
+#define LDC_MAP_IO 0x04
+#define LDC_MAP_R 0x08
+#define LDC_MAP_W 0x10
+#define LDC_MAP_X 0x20
+#define LDC_MAP_RW (LDC_MAP_R | LDC_MAP_W)
+#define LDC_MAP_RWX (LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
+#define LDC_MAP_ALL 0x03f
+
+struct ldc_trans_cookie {
+ u64 cookie_addr;
+ u64 cookie_size;
+};
+
+struct scatterlist;
+extern int ldc_map_sg(struct ldc_channel *lp,
+ struct scatterlist *sg, int num_sg,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm);
+
+extern int ldc_map_single(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm);
+
+extern void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+ int ncookies);
+
+extern int ldc_copy(struct ldc_channel *lp, int copy_dir,
+ void *buf, unsigned int len, unsigned long offset,
+ struct ldc_trans_cookie *cookies, int ncookies);
+
+static inline int ldc_get_dring_entry(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ unsigned long offset,
+ struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
+}
+
+static inline int ldc_put_dring_entry(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ unsigned long offset,
+ struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
+}
+
+extern void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+ struct ldc_trans_cookie *cookies,
+ int *ncookies, unsigned int map_perm);
+
+extern void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
+ unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies);
+
+#endif /* _SPARC64_LDC_H */
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
index c6383982b53d..e97c43133752 100644
--- a/include/asm-sparc64/mdesc.h
+++ b/include/asm-sparc64/mdesc.h
@@ -2,38 +2,66 @@
#define _SPARC64_MDESC_H
#include <linux/types.h>
+#include <linux/cpumask.h>
#include <asm/prom.h>
-struct mdesc_node;
-struct mdesc_arc {
- const char *name;
- struct mdesc_node *arc;
-};
-
-struct mdesc_node {
- const char *name;
- u64 node;
- unsigned int unique_id;
- unsigned int num_arcs;
- unsigned int irqs[2];
- struct property *properties;
- struct mdesc_node *hash_next;
- struct mdesc_node *allnodes_next;
- struct mdesc_arc arcs[0];
-};
-
-extern struct mdesc_node *md_find_node_by_name(struct mdesc_node *from,
- const char *name);
-#define md_for_each_node_by_name(__mn, __name) \
- for (__mn = md_find_node_by_name(NULL, __name); __mn; \
- __mn = md_find_node_by_name(__mn, __name))
-
-extern struct property *md_find_property(const struct mdesc_node *mp,
- const char *name,
- int *lenp);
-extern const void *md_get_property(const struct mdesc_node *mp,
- const char *name,
- int *lenp);
+struct mdesc_handle;
+
+/* Machine description operations are to be surrounded by grab and
+ * release calls. The mdesc_handle returned from the grab is
+ * the first argument to all of the operational calls that work
+ * on mdescs.
+ */
+extern struct mdesc_handle *mdesc_grab(void);
+extern void mdesc_release(struct mdesc_handle *);
+
+#define MDESC_NODE_NULL (~(u64)0)
+
+extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
+ u64 from_node, const char *name);
+#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
+ for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
+ (__node) != MDESC_NODE_NULL; \
+ __node = mdesc_node_by_name(__hdl, __node, __name))
+
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
+extern const void *mdesc_get_property(struct mdesc_handle *handle,
+ u64 node, const char *name, int *lenp);
+extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ * unsigned long arc;
+ * mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ * unsigned long target = mdesc_arc_target(handle, arc);
+ * ...
+ * }
+ */
+
+#define MDESC_ARC_TYPE_FWD "fwd"
+#define MDESC_ARC_TYPE_BACK "back"
+
+extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
+ const char *arc_type);
+#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
+ for (__arc = mdesc_next_arc(__hdl, __node, __type); \
+ (__arc) != MDESC_NODE_NULL; \
+ __arc = mdesc_next_arc(__hdl, __arc, __type))
+
+extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
+
+extern void mdesc_update(void);
+
+extern void mdesc_fill_in_cpu_data(cpumask_t mask);
extern void sun4v_mdesc_init(void);
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index 8d129032013e..9fc225ed5500 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -76,6 +76,9 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
unsigned long ctx_valid, flags;
int cpu;
+ if (unlikely(mm == &init_mm))
+ return;
+
spin_lock_irqsave(&mm->context.lock, flags);
ctx_valid = CTX_VALID(mm->context);
if (!ctx_valid)
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 9e80ad43b29c..0393380d754a 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -573,24 +573,6 @@ static inline unsigned long pte_exec(pte_t pte)
return (pte_val(pte) & mask);
}
-static inline unsigned long pte_read(pte_t pte)
-{
- unsigned long mask;
-
- __asm__ __volatile__(
- "\n661: mov %1, %0\n"
- " nop\n"
- " .section .sun4v_2insn_patch, \"ax\"\n"
- " .word 661b\n"
- " sethi %%uhi(%2), %0\n"
- " sllx %0, 32, %0\n"
- " .previous\n"
- : "=r" (mask)
- : "i" (_PAGE_READ_4U), "i" (_PAGE_READ_4V));
-
- return (pte_val(pte) & mask);
-}
-
static inline unsigned long pte_file(pte_t pte)
{
unsigned long val = pte_val(pte);
diff --git a/include/asm-sparc64/power.h b/include/asm-sparc64/power.h
new file mode 100644
index 000000000000..94495c1ac4f6
--- /dev/null
+++ b/include/asm-sparc64/power.h
@@ -0,0 +1,7 @@
+#ifndef _SPARC64_POWER_H
+#define _SPARC64_POWER_H
+
+extern void wake_up_powerd(void);
+extern int start_powerd(void);
+
+#endif /* !(_SPARC64_POWER_H) */
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 4fb8c4bfb848..e8a96a31761b 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -29,9 +29,6 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-extern cpumask_t phys_cpu_present_map;
-#define cpu_possible_map phys_cpu_present_map
-
extern cpumask_t cpu_sibling_map[NR_CPUS];
extern cpumask_t cpu_core_map[NR_CPUS];
extern int sparc64_multi_core;
@@ -44,7 +41,12 @@ extern int hard_smp_processor_id(void);
#define raw_smp_processor_id() (current_thread_info()->cpu)
extern void smp_fill_in_sib_core_maps(void);
-extern unsigned char boot_cpu_id;
+extern void cpu_play_dead(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+#endif
#endif /* !(__ASSEMBLY__) */
@@ -52,7 +54,6 @@ extern unsigned char boot_cpu_id;
#define hard_smp_processor_id() 0
#define smp_fill_in_sib_core_maps() do { } while (0)
-#define boot_cpu_id (0)
#endif /* !(CONFIG_SMP) */
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
new file mode 100644
index 000000000000..83c96422e9d6
--- /dev/null
+++ b/include/asm-sparc64/vio.h
@@ -0,0 +1,404 @@
+#ifndef _SPARC64_VIO_H
+#define _SPARC64_VIO_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+struct vio_msg_tag {
+ u8 type;
+#define VIO_TYPE_CTRL 0x01
+#define VIO_TYPE_DATA 0x02
+#define VIO_TYPE_ERR 0x04
+
+ u8 stype;
+#define VIO_SUBTYPE_INFO 0x01
+#define VIO_SUBTYPE_ACK 0x02
+#define VIO_SUBTYPE_NACK 0x04
+
+ u16 stype_env;
+#define VIO_VER_INFO 0x0001
+#define VIO_ATTR_INFO 0x0002
+#define VIO_DRING_REG 0x0003
+#define VIO_DRING_UNREG 0x0004
+#define VIO_RDX 0x0005
+#define VIO_PKT_DATA 0x0040
+#define VIO_DESC_DATA 0x0041
+#define VIO_DRING_DATA 0x0042
+#define VNET_MCAST_INFO 0x0101
+
+ u32 sid;
+};
+
+struct vio_rdx {
+ struct vio_msg_tag tag;
+ u64 resv[6];
+};
+
+struct vio_ver_info {
+ struct vio_msg_tag tag;
+ u16 major;
+ u16 minor;
+ u8 dev_class;
+#define VDEV_NETWORK 0x01
+#define VDEV_NETWORK_SWITCH 0x02
+#define VDEV_DISK 0x03
+#define VDEV_DISK_SERVER 0x04
+
+ u8 resv1[3];
+ u64 resv2[5];
+};
+
+struct vio_dring_register {
+ struct vio_msg_tag tag;
+ u64 dring_ident;
+ u32 num_descr;
+ u32 descr_size;
+ u16 options;
+#define VIO_TX_DRING 0x0001
+#define VIO_RX_DRING 0x0002
+ u16 resv;
+ u32 num_cookies;
+ struct ldc_trans_cookie cookies[0];
+};
+
+struct vio_dring_unregister {
+ struct vio_msg_tag tag;
+ u64 dring_ident;
+ u64 resv[5];
+};
+
+/* Data transfer modes */
+#define VIO_PKT_MODE 0x01 /* Packet based transfer */
+#define VIO_DESC_MODE 0x02 /* In-band descriptors */
+#define VIO_DRING_MODE 0x03 /* Descriptor rings */
+
+struct vio_dring_data {
+ struct vio_msg_tag tag;
+ u64 seq;
+ u64 dring_ident;
+ u32 start_idx;
+ u32 end_idx;
+ u8 state;
+#define VIO_DRING_ACTIVE 0x01
+#define VIO_DRING_STOPPED 0x02
+
+ u8 __pad1;
+ u16 __pad2;
+ u32 __pad3;
+ u64 __par4[2];
+};
+
+struct vio_dring_hdr {
+ u8 state;
+#define VIO_DESC_FREE 0x01
+#define VIO_DESC_READY 0x02
+#define VIO_DESC_ACCEPTED 0x03
+#define VIO_DESC_DONE 0x04
+ u8 ack;
+#define VIO_ACK_ENABLE 0x01
+#define VIO_ACK_DISABLE 0x00
+
+ u16 __pad1;
+ u32 __pad2;
+};
+
+/* VIO disk specific structures and defines */
+struct vio_disk_attr_info {
+ struct vio_msg_tag tag;
+ u8 xfer_mode;
+ u8 vdisk_type;
+#define VD_DISK_TYPE_SLICE 0x01 /* Slice in block device */
+#define VD_DISK_TYPE_DISK 0x02 /* Entire block device */
+ u16 resv1;
+ u32 vdisk_block_size;
+ u64 operations;
+ u64 vdisk_size;
+ u64 max_xfer_size;
+ u64 resv2[2];
+};
+
+struct vio_disk_desc {
+ struct vio_dring_hdr hdr;
+ u64 req_id;
+ u8 operation;
+#define VD_OP_BREAD 0x01 /* Block read */
+#define VD_OP_BWRITE 0x02 /* Block write */
+#define VD_OP_FLUSH 0x03 /* Flush disk contents */
+#define VD_OP_GET_WCE 0x04 /* Get write-cache status */
+#define VD_OP_SET_WCE 0x05 /* Enable/disable write-cache */
+#define VD_OP_GET_VTOC 0x06 /* Get VTOC */
+#define VD_OP_SET_VTOC 0x07 /* Set VTOC */
+#define VD_OP_GET_DISKGEOM 0x08 /* Get disk geometry */
+#define VD_OP_SET_DISKGEOM 0x09 /* Set disk geometry */
+#define VD_OP_SCSICMD 0x0a /* SCSI control command */
+#define VD_OP_GET_DEVID 0x0b /* Get device ID */
+#define VD_OP_GET_EFI 0x0c /* Get EFI */
+#define VD_OP_SET_EFI 0x0d /* Set EFI */
+ u8 slice;
+ u16 resv1;
+ u32 status;
+ u64 offset;
+ u64 size;
+ u32 ncookies;
+ u32 resv2;
+ struct ldc_trans_cookie cookies[0];
+};
+
+#define VIO_DISK_VNAME_LEN 8
+#define VIO_DISK_ALABEL_LEN 128
+#define VIO_DISK_NUM_PART 8
+
+struct vio_disk_vtoc {
+ u8 volume_name[VIO_DISK_VNAME_LEN];
+ u16 sector_size;
+ u16 num_partitions;
+ u8 ascii_label[VIO_DISK_ALABEL_LEN];
+ struct {
+ u16 id;
+ u16 perm_flags;
+ u32 resv;
+ u64 start_block;
+ u64 num_blocks;
+ } partitions[VIO_DISK_NUM_PART];
+};
+
+struct vio_disk_geom {
+ u16 num_cyl; /* Num data cylinders */
+ u16 alt_cyl; /* Num alternate cylinders */
+ u16 beg_cyl; /* Cyl off of fixed head area */
+ u16 num_hd; /* Num heads */
+ u16 num_sec; /* Num sectors */
+ u16 ifact; /* Interleave factor */
+ u16 apc; /* Alts per cylinder (SCSI) */
+ u16 rpm; /* Revolutions per minute */
+ u16 phy_cyl; /* Num physical cylinders */
+ u16 wr_skip; /* Num sects to skip, writes */
+ u16 rd_skip; /* Num sects to skip, writes */
+};
+
+struct vio_disk_devid {
+ u16 resv;
+ u16 type;
+ u32 len;
+ char id[0];
+};
+
+struct vio_disk_efi {
+ u64 lba;
+ u64 len;
+ char data[0];
+};
+
+/* VIO net specific structures and defines */
+struct vio_net_attr_info {
+ struct vio_msg_tag tag;
+ u8 xfer_mode;
+ u8 addr_type;
+#define VNET_ADDR_ETHERMAC 0x01
+ u16 ack_freq;
+ u32 resv1;
+ u64 addr;
+ u64 mtu;
+ u64 resv2[3];
+};
+
+#define VNET_NUM_MCAST 7
+
+struct vio_net_mcast_info {
+ struct vio_msg_tag tag;
+ u8 set;
+ u8 count;
+ u8 mcast_addr[VNET_NUM_MCAST * 6];
+ u32 resv;
+};
+
+struct vio_net_desc {
+ struct vio_dring_hdr hdr;
+ u32 size;
+ u32 ncookies;
+ struct ldc_trans_cookie cookies[0];
+};
+
+#define VIO_MAX_RING_COOKIES 24
+
+struct vio_dring_state {
+ u64 ident;
+ void *base;
+ u64 snd_nxt;
+ u64 rcv_nxt;
+ u32 entry_size;
+ u32 num_entries;
+ u32 prod;
+ u32 cons;
+ u32 pending;
+ int ncookies;
+ struct ldc_trans_cookie cookies[VIO_MAX_RING_COOKIES];
+};
+
+static inline void *vio_dring_cur(struct vio_dring_state *dr)
+{
+ return dr->base + (dr->entry_size * dr->prod);
+}
+
+static inline void *vio_dring_entry(struct vio_dring_state *dr,
+ unsigned int index)
+{
+ return dr->base + (dr->entry_size * index);
+}
+
+static inline u32 vio_dring_avail(struct vio_dring_state *dr,
+ unsigned int ring_size)
+{
+ /* Ensure build-time power-of-2. */
+ BUILD_BUG_ON(ring_size & (ring_size - 1));
+
+ return (dr->pending -
+ ((dr->prod - dr->cons) & (ring_size - 1)));
+}
+
+#define VIO_MAX_TYPE_LEN 64
+#define VIO_MAX_COMPAT_LEN 64
+
+struct vio_dev {
+ u64 mp;
+ struct device_node *dp;
+
+ char type[VIO_MAX_TYPE_LEN];
+ char compat[VIO_MAX_COMPAT_LEN];
+ int compat_len;
+
+ unsigned long channel_id;
+
+ unsigned int tx_irq;
+ unsigned int rx_irq;
+
+ struct device dev;
+};
+
+struct vio_driver {
+ struct list_head node;
+ const struct vio_device_id *id_table;
+ int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
+ int (*remove)(struct vio_dev *dev);
+ void (*shutdown)(struct vio_dev *dev);
+ unsigned long driver_data;
+ struct device_driver driver;
+};
+
+struct vio_version {
+ u16 major;
+ u16 minor;
+};
+
+struct vio_driver_state;
+struct vio_driver_ops {
+ int (*send_attr)(struct vio_driver_state *vio);
+ int (*handle_attr)(struct vio_driver_state *vio, void *pkt);
+ void (*handshake_complete)(struct vio_driver_state *vio);
+};
+
+struct vio_completion {
+ struct completion com;
+ int err;
+ int waiting_for;
+};
+
+struct vio_driver_state {
+ /* Protects VIO handshake and, optionally, driver private state. */
+ spinlock_t lock;
+
+ struct ldc_channel *lp;
+
+ u32 _peer_sid;
+ u32 _local_sid;
+ struct vio_dring_state drings[2];
+#define VIO_DRIVER_TX_RING 0
+#define VIO_DRIVER_RX_RING 1
+
+ u8 hs_state;
+#define VIO_HS_INVALID 0x00
+#define VIO_HS_GOTVERS 0x01
+#define VIO_HS_GOT_ATTR 0x04
+#define VIO_HS_SENT_DREG 0x08
+#define VIO_HS_SENT_RDX 0x10
+#define VIO_HS_GOT_RDX_ACK 0x20
+#define VIO_HS_GOT_RDX 0x40
+#define VIO_HS_SENT_RDX_ACK 0x80
+#define VIO_HS_COMPLETE (VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
+
+ u8 dev_class;
+
+ u8 dr_state;
+#define VIO_DR_STATE_TXREG 0x01
+#define VIO_DR_STATE_RXREG 0x02
+#define VIO_DR_STATE_TXREQ 0x10
+#define VIO_DR_STATE_RXREQ 0x20
+
+ u8 debug;
+#define VIO_DEBUG_HS 0x01
+#define VIO_DEBUG_DATA 0x02
+
+ void *desc_buf;
+ unsigned int desc_buf_len;
+
+ struct vio_completion *cmp;
+
+ struct vio_dev *vdev;
+
+ struct timer_list timer;
+
+ struct vio_version ver;
+
+ struct vio_version *ver_table;
+ int ver_table_entries;
+
+ char *name;
+
+ struct vio_driver_ops *ops;
+};
+
+#define viodbg(TYPE, f, a...) \
+do { if (vio->debug & VIO_DEBUG_##TYPE) \
+ printk(KERN_INFO "vio: ID[%lu] " f, \
+ vio->vdev->channel_id, ## a); \
+} while (0)
+
+extern int vio_register_driver(struct vio_driver *drv);
+extern void vio_unregister_driver(struct vio_driver *drv);
+
+static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
+{
+ return container_of(drv, struct vio_driver, driver);
+}
+
+static inline struct vio_dev *to_vio_dev(struct device *dev)
+{
+ return container_of(dev, struct vio_dev, dev);
+}
+
+extern int vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
+extern void vio_link_state_change(struct vio_driver_state *vio, int event);
+extern void vio_conn_reset(struct vio_driver_state *vio);
+extern int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
+extern int vio_validate_sid(struct vio_driver_state *vio,
+ struct vio_msg_tag *tp);
+extern u32 vio_send_sid(struct vio_driver_state *vio);
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+ struct ldc_channel_config *base_cfg, void *event_arg);
+extern void vio_ldc_free(struct vio_driver_state *vio);
+extern int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+ u8 dev_class, struct vio_version *ver_table,
+ int ver_table_size, struct vio_driver_ops *ops,
+ char *name);
+
+extern void vio_port_up(struct vio_driver_state *vio);
+
+#endif /* _SPARC64_VIO_H */
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 1b1090a91a58..830fc6e5d49d 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -175,12 +175,6 @@ static inline int pte_none(pte_t pte)
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-static inline int pte_user(pte_t pte)
-{
- return((pte_get_bits(pte, _PAGE_USER)) &&
- !(pte_get_bits(pte, _PAGE_PROTNONE)));
-}
-
static inline int pte_read(pte_t pte)
{
return((pte_get_bits(pte, _PAGE_USER)) &&
@@ -238,18 +232,6 @@ static inline pte_t pte_mknewprot(pte_t pte)
return(pte);
}
-static inline pte_t pte_rdprotect(pte_t pte)
-{
- pte_clear_bits(pte, _PAGE_USER);
- return(pte_mknewprot(pte));
-}
-
-static inline pte_t pte_exprotect(pte_t pte)
-{
- pte_clear_bits(pte, _PAGE_USER);
- return(pte_mknewprot(pte));
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte_clear_bits(pte, _PAGE_DIRTY);
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 18a13ba74605..6e5fd5c892d0 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -52,10 +52,21 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
+#ifdef CONFIG_DEBUG_STACK_USAGE
+
+#define alloc_thread_info(tsk) \
+ ((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
+ CONFIG_KERNEL_STACK_ORDER))
+#else
+
/* thread information allocation */
#define alloc_thread_info(tsk) \
- ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
-#define free_thread_info(ti) kfree(ti)
+ ((struct thread_info *) __get_free_pages(GFP_KERNEL, \
+ CONFIG_KERNEL_STACK_ORDER))
+#endif
+
+#define free_thread_info(ti) \
+ free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
#endif
diff --git a/include/asm-v850/fb.h b/include/asm-v850/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-v850/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-v850/ioctls.h b/include/asm-v850/ioctls.h
index 05c0dc9ce1ea..5313abd5f388 100644
--- a/include/asm-v850/ioctls.h
+++ b/include/asm-v850/ioctls.h
@@ -46,6 +46,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
index 35412f7f3eea..295d7bf69451 100644
--- a/include/asm-v850/termbits.h
+++ b/include/asm-v850/termbits.h
@@ -141,6 +141,7 @@ struct ktermios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
@@ -156,10 +157,12 @@ struct ktermios {
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
+#define IBSHIFT 16 /* Shifr from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
diff --git a/include/asm-v850/termios.h b/include/asm-v850/termios.h
index c2c2b1d58776..fcd171838d9c 100644
--- a/include/asm-v850/termios.h
+++ b/include/asm-v850/termios.h
@@ -80,8 +80,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
index b37ab8218ef0..53cb96b68a62 100644
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -33,8 +33,10 @@ typedef s32 compat_key_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
+typedef s64 __attribute__((aligned(4))) compat_s64;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
+typedef u64 __attribute__((aligned(4))) compat_u64;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-x86_64/fb.h b/include/asm-x86_64/fb.h
new file mode 100644
index 000000000000..60548e651d12
--- /dev/null
+++ b/include/asm-x86_64/fb.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{
+ if (boot_cpu_data.x86 > 3)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e1677531b..2acb9b7f6418 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@ enum fixed_addresses {
VSYSCALL_LAST_PAGE,
VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
VSYSCALL_HPET,
+ FIX_DBGP_BASE,
+ FIX_EARLYCON_MEM_BASE,
FIX_HPET_BASE,
FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
if (idx >= __end_of_fixed_addresses)
__this_fixmap_does_not_exist();
- return __fix_to_virt(idx);
+ return __fix_to_virt(idx);
}
#endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a2303a..7475095c5061 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -144,6 +144,7 @@ extern void early_iounmap(void *addr, unsigned long size);
*/
extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
extern void iounmap(volatile void __iomem *addr);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index e327c830da0c..88adf1afb0a2 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -48,7 +48,8 @@ void copy_page(void *, void *);
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#define alloc_zeroed_user_highpage(vma, vaddr) alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr)
+#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
+ alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/*
* These are used to make use of C type-checking..
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 0a71e0b9a619..3ba53099297d 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -266,21 +266,15 @@ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
* Undefined behaviour if not..
*/
#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
-static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-static inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_NX); }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; }
-static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
-static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
-static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX)); return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
@@ -290,13 +284,6 @@ static inline pte_t pte_clrhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) &
struct vm_area_struct;
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
- if (!pte_dirty(*ptep))
- return 0;
- return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte);
-}
-
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
if (!pte_young(*ptep))
@@ -433,7 +420,6 @@ extern int kern_addr_valid(unsigned long addr);
(((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
diff --git a/include/asm-xtensa/fb.h b/include/asm-xtensa/fb.h
new file mode 100644
index 000000000000..c7df38030992
--- /dev/null
+++ b/include/asm-xtensa/fb.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_FB_H_
+#define _ASM_FB_H_
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+ return 0;
+}
+
+#endif /* _ASM_FB_H_ */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 2d4b5db6ea63..06850f3b26a7 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -197,16 +197,13 @@ extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
/* Note: We use the _PAGE_USER bit to indicate write-protect kernel memory */
-static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
-static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
@@ -270,17 +267,6 @@ ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
return 1;
}
-static inline int
-ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
- pte_t *ptep)
-{
- pte_t pte = *ptep;
- if (!pte_dirty(pte))
- return 0;
- update_pte(ptep, pte_mkclean(pte));
- return 1;
-}
-
static inline pte_t
ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
@@ -421,7 +407,6 @@ typedef pte_t *pte_addr_t;
#endif /* !defined (__ASSEMBLY__) */
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
#define __HAVE_ARCH_PTEP_MKDIRTY
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 127d2d192b5a..bcf875e844fe 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -247,7 +247,6 @@ unifdef-y += isdn.h
unifdef-y += isdnif.h
unifdef-y += isdn_divertif.h
unifdef-y += isdn_ppp.h
-unifdef-y += isicom.h
unifdef-y += jbd.h
unifdef-y += joystick.h
unifdef-y += kdev_t.h
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
index 93bfb0beb62a..8ff274933948 100644
--- a/include/linux/attribute_container.h
+++ b/include/linux/attribute_container.h
@@ -12,7 +12,6 @@
#include <linux/device.h>
#include <linux/list.h>
#include <linux/klist.h>
-#include <linux/spinlock.h>
struct attribute_container {
struct list_head node;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index fccc6e50298a..8ca7ca0b47f0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -63,9 +63,12 @@
#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */
#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */
#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */
+#define AUDIT_TTY_GET 1014 /* Get TTY auditing status */
+#define AUDIT_TTY_SET 1015 /* Set TTY auditing status */
#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */
+#define AUDIT_USER_TTY 1124 /* Non-ICANON TTY input meaning */
#define AUDIT_LAST_USER_MSG 1199
#define AUDIT_FIRST_USER_MSG2 2100 /* More user space messages */
#define AUDIT_LAST_USER_MSG2 2999
@@ -92,6 +95,7 @@
#define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */
#define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */
#define AUDIT_OBJ_PID 1318 /* ptrace target */
+#define AUDIT_TTY 1319 /* Input on an administrative TTY */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -289,6 +293,10 @@ struct audit_status {
__u32 backlog; /* messages waiting in queue */
};
+struct audit_tty_status {
+ __u32 enabled; /* 1 = enabled, 0 = disabled */
+};
+
/* audit_rule_data supports filter rules with both integer and string
* fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
* AUDIT_LIST_RULES requests.
@@ -515,11 +523,13 @@ extern void audit_log_d_path(struct audit_buffer *ab,
const char *prefix,
struct dentry *dentry,
struct vfsmount *vfsmnt);
+extern void audit_log_lost(const char *message);
/* Private API (for audit.c only) */
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int uid, int seq,
void *data, size_t datasz, uid_t loginuid, u32 sid);
+extern int audit_enabled;
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
#define audit_log_start(c,g,t) ({ NULL; })
@@ -530,6 +540,7 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq,
#define audit_log_untrustedstring(a,s) do { ; } while (0)
#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
+#define audit_enabled 0
#endif
#endif
#endif
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index f2542c24b328..7011d6255593 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -93,7 +93,6 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
void set_bdi_congested(struct backing_dev_info *bdi, int rw);
long congestion_wait(int rw, long timeout);
-long congestion_wait_interruptible(int rw, long timeout);
void congestion_end(int rw);
#define bdi_cap_writeback_dirty(bdi) \
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index fae138bd2207..f78965fc6426 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -14,6 +14,7 @@
#include <linux/bio.h>
#include <linux/module.h>
#include <linux/stringify.h>
+#include <linux/bsg.h>
#include <asm/scatterlist.h>
@@ -41,6 +42,8 @@ struct elevator_queue;
typedef struct elevator_queue elevator_t;
struct request_pm_state;
struct blk_trace;
+struct request;
+struct sg_io_hdr;
#define BLKDEV_MIN_RQ 4
#define BLKDEV_MAX_RQ 128 /* Default maximum */
@@ -314,6 +317,9 @@ struct request {
*/
rq_end_io_fn *end_io;
void *end_io_data;
+
+ /* for bidi */
+ struct request *next_rq;
};
/*
@@ -468,6 +474,10 @@ struct request_queue
unsigned int bi_size;
struct mutex sysfs_lock;
+
+#if defined(CONFIG_BLK_DEV_BSG)
+ struct bsg_class_device bsg_dev;
+#endif
};
#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
@@ -479,6 +489,7 @@ struct request_queue
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
enum {
/*
@@ -543,6 +554,7 @@ enum {
#define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED)
#define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER)
#define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA)
+#define blk_bidi_rq(rq) ((rq)->next_rq != NULL)
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
@@ -607,7 +619,12 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
#define BLK_BOUNCE_ANY ((u64)blk_max_pfn << PAGE_SHIFT)
#define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
-#ifdef CONFIG_MMU
+/*
+ * default timeout for SG_IO if none specified
+ */
+#define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
+
+#ifdef CONFIG_BOUNCE
extern int init_emergency_isa_pool(void);
extern void blk_queue_bounce(request_queue_t *q, struct bio **bio);
#else
@@ -637,7 +654,8 @@ extern void blk_requeue_request(request_queue_t *, struct request *);
extern void blk_plug_device(request_queue_t *);
extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
-extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
+extern int scsi_cmd_ioctl(struct file *, struct request_queue *,
+ struct gendisk *, unsigned int, void __user *);
extern int sg_scsi_ioctl(struct file *, struct request_queue *,
struct gendisk *, struct scsi_ioctl_command __user *);
@@ -680,6 +698,12 @@ extern int blk_execute_rq(request_queue_t *, struct gendisk *,
struct request *, int);
extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
struct request *, int, rq_end_io_fn *);
+extern int blk_fill_sghdr_rq(request_queue_t *, struct request *,
+ struct sg_io_hdr *, int);
+extern int blk_unmap_sghdr_rq(struct request *, struct sg_io_hdr *);
+extern int blk_complete_sghdr_rq(struct request *, struct sg_io_hdr *,
+ struct bio *);
+extern int blk_verify_command(unsigned char *, int);
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
{
diff --git a/include/linux/bsg.h b/include/linux/bsg.h
new file mode 100644
index 000000000000..8547b10c388b
--- /dev/null
+++ b/include/linux/bsg.h
@@ -0,0 +1,69 @@
+#ifndef BSG_H
+#define BSG_H
+
+#define BSG_PROTOCOL_SCSI 0
+
+#define BSG_SUB_PROTOCOL_SCSI_CMD 0
+#define BSG_SUB_PROTOCOL_SCSI_TMF 1
+#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2
+
+struct sg_io_v4 {
+ __s32 guard; /* [i] 'Q' to differentiate from v3 */
+ __u32 protocol; /* [i] 0 -> SCSI , .... */
+ __u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task
+ management function, .... */
+
+ __u32 request_len; /* [i] in bytes */
+ __u64 request; /* [i], [*i] {SCSI: cdb} */
+ __u32 request_attr; /* [i] {SCSI: task attribute} */
+ __u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */
+ __u32 request_priority; /* [i] {SCSI: task priority} */
+ __u32 max_response_len; /* [i] in bytes */
+ __u64 response; /* [i], [*o] {SCSI: (auto)sense data} */
+
+ /* "din_" for data in (from device); "dout_" for data out (to device) */
+ __u32 dout_xfer_len; /* [i] bytes to be transferred to device */
+ __u32 din_xfer_len; /* [i] bytes to be transferred from device */
+ __u64 dout_xferp; /* [i], [*i] */
+ __u64 din_xferp; /* [i], [*o] */
+
+ __u32 timeout; /* [i] units: millisecond */
+ __u32 flags; /* [i] bit mask */
+ __u64 usr_ptr; /* [i->o] unused internally */
+ __u32 spare_in; /* [i] */
+
+ __u32 driver_status; /* [o] 0 -> ok */
+ __u32 transport_status; /* [o] 0 -> ok */
+ __u32 device_status; /* [o] {SCSI: command completion status} */
+ __u32 retry_delay; /* [o] {SCSI: status auxiliary information} */
+ __u32 info; /* [o] additional information */
+ __u32 duration; /* [o] time to complete, in milliseconds */
+ __u32 response_len; /* [o] bytes of response actually written */
+ __s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */
+ __u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */
+ __u32 spare_out; /* [o] */
+
+ __u32 padding;
+};
+
+#ifdef __KERNEL__
+
+#if defined(CONFIG_BLK_DEV_BSG)
+struct bsg_class_device {
+ struct class_device *class_dev;
+ struct device *dev;
+ int minor;
+ struct list_head list;
+ struct request_queue *queue;
+};
+
+extern int bsg_register_queue(struct request_queue *, const char *);
+extern void bsg_unregister_queue(struct request_queue *);
+#else
+#define bsg_register_queue(disk, name) (0)
+#define bsg_unregister_queue(disk) do { } while (0)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 42aa0a54b6f4..54398d2c6d8d 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -10,6 +10,8 @@ enum bug_trap_type {
BUG_TRAP_TYPE_BUG = 2,
};
+struct pt_regs;
+
#ifdef CONFIG_GENERIC_BUG
#include <asm-generic/bug.h>
@@ -20,7 +22,7 @@ static inline int is_warning_bug(const struct bug_entry *bug)
const struct bug_entry *find_bug(unsigned long bugaddr);
-enum bug_trap_type report_bug(unsigned long bug_addr);
+enum bug_trap_type report_bug(unsigned long bug_addr, struct pt_regs *regs);
int module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
struct module *);
@@ -31,7 +33,8 @@ int is_valid_bugaddr(unsigned long addr);
#else /* !CONFIG_GENERIC_BUG */
-static inline enum bug_trap_type report_bug(unsigned long bug_addr)
+static inline enum bug_trap_type report_bug(unsigned long bug_addr,
+ struct pt_regs *regs)
{
return BUG_TRAP_TYPE_BUG;
}
diff --git a/include/linux/capability.h b/include/linux/capability.h
index bbf8df7de28f..2dfa58555934 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -44,7 +44,6 @@ typedef struct __user_cap_data_struct {
#ifdef __KERNEL__
-#include <linux/spinlock.h>
#include <asm/current.h>
/* #define STRICT_CAP_T_TYPECHECKS */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index f50f04bdbc16..2b641b176e7f 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -414,8 +414,8 @@ struct cdrom_generic_command
#define CDO_CHECK_TYPE 0x10 /* check type on open for data */
/* Special codes used when specifying changer slots. */
-#define CDSL_NONE ((int) (~0U>>1)-1)
-#define CDSL_CURRENT ((int) (~0U>>1))
+#define CDSL_NONE (INT_MAX-1)
+#define CDSL_CURRENT INT_MAX
/* For partition based multisession access. IDE can handle 64 partitions
* per drive - SCSI CD-ROM's use minors to differentiate between the
diff --git a/include/linux/cobalt-nvram.h b/include/linux/cobalt-nvram.h
deleted file mode 100644
index ea429562ff36..000000000000
--- a/include/linux/cobalt-nvram.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: cobalt-nvram.h,v 1.20 2001/10/17 23:16:55 thockin Exp $
- * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM
- *
- * Copyright 2001,2002 Sun Microsystems, Inc.
- */
-
-#ifndef COBALT_NVRAM_H
-#define COBALT_NVRAM_H
-
-#include <linux/nvram.h>
-
-#define COBT_CMOS_INFO_MAX 0x7f /* top address allowed */
-#define COBT_CMOS_BIOS_DRIVE_INFO 0x12 /* drive info would go here */
-
-#define COBT_CMOS_CKS_START NVRAM_OFFSET(0x0e)
-#define COBT_CMOS_CKS_END NVRAM_OFFSET(0x7f)
-
-/* flag bytes - 16 flags for now, leave room for more */
-#define COBT_CMOS_FLAG_BYTE_0 NVRAM_OFFSET(0x10)
-#define COBT_CMOS_FLAG_BYTE_1 NVRAM_OFFSET(0x11)
-
-/* flags in flag bytes - up to 16 */
-#define COBT_CMOS_FLAG_MIN 0x0001
-#define COBT_CMOS_CONSOLE_FLAG 0x0001 /* console on/off */
-#define COBT_CMOS_DEBUG_FLAG 0x0002 /* ROM debug messages */
-#define COBT_CMOS_AUTO_PROMPT_FLAG 0x0004 /* boot to ROM prompt? */
-#define COBT_CMOS_CLEAN_BOOT_FLAG 0x0008 /* set by a clean shutdown */
-#define COBT_CMOS_HW_NOPROBE_FLAG 0x0010 /* go easy on the probing */
-#define COBT_CMOS_SYSFAULT_FLAG 0x0020 /* system fault detected */
-#define COBT_CMOS_OOPSPANIC_FLAG 0x0040 /* panic on oops */
-#define COBT_CMOS_DELAY_CACHE_FLAG 0x0080 /* delay cache initialization */
-#define COBT_CMOS_NOLOGO_FLAG 0x0100 /* hide "C" logo @ boot */
-#define COBT_CMOS_VERSION_FLAG 0x0200 /* the version field is valid */
-#define COBT_CMOS_FLAG_MAX 0x0200
-
-/* leave byte 0x12 blank - Linux looks for drive info here */
-
-/* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */
-#define COBT_CMOS_VERSION NVRAM_OFFSET(0x13)
-#define COBT_CMOS_VER_BTOCODE 1 /* min. version needed for btocode */
-
-/* index of default boot method */
-#define COBT_CMOS_BOOT_METHOD NVRAM_OFFSET(0x20)
-#define COBT_CMOS_BOOT_METHOD_DISK 0
-#define COBT_CMOS_BOOT_METHOD_ROM 1
-#define COBT_CMOS_BOOT_METHOD_NET 2
-
-#define COBT_CMOS_BOOT_DEV_MIN NVRAM_OFFSET(0x21)
-/* major #, minor # of first through fourth boot device */
-#define COBT_CMOS_BOOT_DEV0_MAJ NVRAM_OFFSET(0x21)
-#define COBT_CMOS_BOOT_DEV0_MIN NVRAM_OFFSET(0x22)
-#define COBT_CMOS_BOOT_DEV1_MAJ NVRAM_OFFSET(0x23)
-#define COBT_CMOS_BOOT_DEV1_MIN NVRAM_OFFSET(0x24)
-#define COBT_CMOS_BOOT_DEV2_MAJ NVRAM_OFFSET(0x25)
-#define COBT_CMOS_BOOT_DEV2_MIN NVRAM_OFFSET(0x26)
-#define COBT_CMOS_BOOT_DEV3_MAJ NVRAM_OFFSET(0x27)
-#define COBT_CMOS_BOOT_DEV3_MIN NVRAM_OFFSET(0x28)
-#define COBT_CMOS_BOOT_DEV_MAX NVRAM_OFFSET(0x28)
-
-/* checksum of bytes 0xe-0x7f */
-#define COBT_CMOS_CHECKSUM NVRAM_OFFSET(0x2e)
-
-/* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */
-#define COBT_CMOS_UPTIME_0 NVRAM_OFFSET(0x30)
-#define COBT_CMOS_UPTIME_1 NVRAM_OFFSET(0x31)
-#define COBT_CMOS_UPTIME_2 NVRAM_OFFSET(0x32)
-#define COBT_CMOS_UPTIME_3 NVRAM_OFFSET(0x33)
-
-/* count of successful boots (32 bits) */
-#define COBT_CMOS_BOOTCOUNT_0 NVRAM_OFFSET(0x38)
-#define COBT_CMOS_BOOTCOUNT_1 NVRAM_OFFSET(0x39)
-#define COBT_CMOS_BOOTCOUNT_2 NVRAM_OFFSET(0x3a)
-#define COBT_CMOS_BOOTCOUNT_3 NVRAM_OFFSET(0x3b)
-
-/* 13 bytes: system serial number, same as on the back of the system */
-#define COBT_CMOS_SYS_SERNUM_LEN 13
-#define COBT_CMOS_SYS_SERNUM_0 NVRAM_OFFSET(0x40)
-#define COBT_CMOS_SYS_SERNUM_1 NVRAM_OFFSET(0x41)
-#define COBT_CMOS_SYS_SERNUM_2 NVRAM_OFFSET(0x42)
-#define COBT_CMOS_SYS_SERNUM_3 NVRAM_OFFSET(0x43)
-#define COBT_CMOS_SYS_SERNUM_4 NVRAM_OFFSET(0x44)
-#define COBT_CMOS_SYS_SERNUM_5 NVRAM_OFFSET(0x45)
-#define COBT_CMOS_SYS_SERNUM_6 NVRAM_OFFSET(0x46)
-#define COBT_CMOS_SYS_SERNUM_7 NVRAM_OFFSET(0x47)
-#define COBT_CMOS_SYS_SERNUM_8 NVRAM_OFFSET(0x48)
-#define COBT_CMOS_SYS_SERNUM_9 NVRAM_OFFSET(0x49)
-#define COBT_CMOS_SYS_SERNUM_10 NVRAM_OFFSET(0x4a)
-#define COBT_CMOS_SYS_SERNUM_11 NVRAM_OFFSET(0x4b)
-#define COBT_CMOS_SYS_SERNUM_12 NVRAM_OFFSET(0x4c)
-/* checksum for serial num - 1 byte */
-#define COBT_CMOS_SYS_SERNUM_CSUM NVRAM_OFFSET(0x4f)
-
-#define COBT_CMOS_ROM_REV_MAJ NVRAM_OFFSET(0x50)
-#define COBT_CMOS_ROM_REV_MIN NVRAM_OFFSET(0x51)
-#define COBT_CMOS_ROM_REV_REV NVRAM_OFFSET(0x52)
-
-#define COBT_CMOS_BTO_CODE_0 NVRAM_OFFSET(0x53)
-#define COBT_CMOS_BTO_CODE_1 NVRAM_OFFSET(0x54)
-#define COBT_CMOS_BTO_CODE_2 NVRAM_OFFSET(0x55)
-#define COBT_CMOS_BTO_CODE_3 NVRAM_OFFSET(0x56)
-
-#define COBT_CMOS_BTO_IP_CSUM NVRAM_OFFSET(0x57)
-#define COBT_CMOS_BTO_IP_0 NVRAM_OFFSET(0x58)
-#define COBT_CMOS_BTO_IP_1 NVRAM_OFFSET(0x59)
-#define COBT_CMOS_BTO_IP_2 NVRAM_OFFSET(0x5a)
-#define COBT_CMOS_BTO_IP_3 NVRAM_OFFSET(0x5b)
-
-#endif /* COBALT_NVRAM_H */
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index fef6f3d0a4a7..8c6967f3fb11 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -40,9 +40,9 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/kref.h>
+#include <linux/mutex.h>
#include <asm/atomic.h>
-#include <asm/semaphore.h>
#define CONFIGFS_ITEM_NAME_LEN 20
@@ -75,7 +75,6 @@ extern void config_item_init(struct config_item *);
extern void config_item_init_type_name(struct config_item *item,
const char *name,
struct config_item_type *type);
-extern void config_item_cleanup(struct config_item *);
extern struct config_item * config_item_get(struct config_item *);
extern void config_item_put(struct config_item *);
@@ -87,12 +86,10 @@ struct config_item_type {
struct configfs_attribute **ct_attrs;
};
-
/**
* group - a group of config_items of a specific type, belonging
* to a specific subsystem.
*/
-
struct config_group {
struct config_item cg_item;
struct list_head cg_children;
@@ -100,13 +97,11 @@ struct config_group {
struct config_group **default_groups;
};
-
extern void config_group_init(struct config_group *group);
extern void config_group_init_type_name(struct config_group *group,
const char *name,
struct config_item_type *type);
-
static inline struct config_group *to_config_group(struct config_item *item)
{
return item ? container_of(item,struct config_group,cg_item) : NULL;
@@ -122,7 +117,8 @@ static inline void config_group_put(struct config_group *group)
config_item_put(&group->cg_item);
}
-extern struct config_item *config_group_find_obj(struct config_group *, const char *);
+extern struct config_item *config_group_find_item(struct config_group *,
+ const char *);
struct configfs_attribute {
@@ -131,6 +127,22 @@ struct configfs_attribute {
mode_t ca_mode;
};
+/*
+ * Users often need to create attribute structures for their configurable
+ * attributes, containing a configfs_attribute member and function pointers
+ * for the show() and store() operations on that attribute. They can use
+ * this macro (similar to sysfs' __ATTR) to make defining attributes easier.
+ */
+#define __CONFIGFS_ATTR(_name, _mode, _show, _store) \
+{ \
+ .attr = { \
+ .ca_name = __stringify(_name), \
+ .ca_mode = _mode, \
+ .ca_owner = THIS_MODULE, \
+ }, \
+ .show = _show, \
+ .store = _store, \
+}
/*
* If allow_link() exists, the item can symlink(2) out to other
@@ -157,12 +169,13 @@ struct configfs_group_operations {
struct config_item *(*make_item)(struct config_group *group, const char *name);
struct config_group *(*make_group)(struct config_group *group, const char *name);
int (*commit_item)(struct config_item *item);
+ void (*disconnect_notify)(struct config_group *group, struct config_item *item);
void (*drop_item)(struct config_group *group, struct config_item *item);
};
struct configfs_subsystem {
struct config_group su_group;
- struct semaphore su_sem;
+ struct mutex su_mutex;
};
static inline struct configfs_subsystem *to_configfs_subsystem(struct config_group *group)
@@ -175,6 +188,11 @@ static inline struct configfs_subsystem *to_configfs_subsystem(struct config_gro
int configfs_register_subsystem(struct configfs_subsystem *subsys);
void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
+/* These functions can sleep and can alloc with GFP_KERNEL */
+/* WARNING: These cannot be called underneath configfs callbacks!! */
+int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
+void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
+
#endif /* __KERNEL__ */
#endif /* _CONFIGFS_H_ */
diff --git a/include/linux/console.h b/include/linux/console.h
index 62ef6e11d0d2..56a7bcda49cb 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -15,7 +15,6 @@
#define _LINUX_CONSOLE_H_ 1
#include <linux/types.h>
-#include <linux/spinlock.h>
struct vc_data;
struct console_font_op;
@@ -99,6 +98,7 @@ struct console {
struct tty_driver *(*device)(struct console *, int *);
void (*unblank)(void);
int (*setup)(struct console *, char *);
+ int (*early_setup)(void);
short flags;
short index;
int cflag;
@@ -107,6 +107,7 @@ struct console {
};
extern int add_preferred_console(char *name, int idx, char *options);
+extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
extern void register_console(struct console *);
extern int unregister_console(struct console *);
extern struct console *console_drivers;
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index 82c9a1f11020..06b2768c603f 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -8,9 +8,12 @@
#define IBMPC_MAP 2
#define USER_MAP 3
+#include <linux/types.h>
+
struct vc_data;
-extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
+extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
extern unsigned short *set_translate(int m, struct vc_data *vc);
extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
+extern u32 conv_8bit_to_uni(unsigned char c);
void console_map_init(void);
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 3b2df2523f1d..c2236bbff412 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -120,7 +120,6 @@ static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex)
#define lock_cpu_hotplug() do { } while (0)
#define unlock_cpu_hotplug() do { } while (0)
-#define lock_cpu_hotplug_interruptible() 0
#define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
#define register_hotcpu_notifier(nb) do { (void)(nb); } while (0)
#define unregister_hotcpu_notifier(nb) do { (void)(nb); } while (0)
diff --git a/include/linux/crc7.h b/include/linux/crc7.h
new file mode 100644
index 000000000000..1786e772d5c6
--- /dev/null
+++ b/include/linux/crc7.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_CRC7_H
+#define _LINUX_CRC7_H
+#include <linux/types.h>
+
+extern const u8 crc7_syndrome_table[256];
+
+static inline u8 crc7_byte(u8 crc, u8 data)
+{
+ return crc7_syndrome_table[(crc << 1) ^ data];
+}
+
+extern u8 crc7(u8 crc, const u8 *buffer, size_t len);
+
+#endif
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9a663c6db16a..2dc21cbeb304 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -31,7 +31,11 @@ static inline int valid_dma_direction(int dma_direction)
(dma_direction == DMA_FROM_DEVICE));
}
+#ifdef CONFIG_HAS_DMA
#include <asm/dma-mapping.h>
+#else
+#include <asm-generic/dma-mapping-broken.h>
+#endif
/* Backwards compat, remove in 2.7.x */
#define dma_sync_single dma_sync_single_for_cpu
diff --git a/include/linux/ds17287rtc.h b/include/linux/ds17287rtc.h
index c281ba42e28f..d85d3f497b96 100644
--- a/include/linux/ds17287rtc.h
+++ b/include/linux/ds17287rtc.h
@@ -11,7 +11,6 @@
#define __LINUX_DS17287RTC_H
#include <linux/rtc.h> /* get the user-level API */
-#include <linux/spinlock.h> /* spinlock_t */
#include <linux/mc146818rtc.h>
/* Register A */
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index dfed8009ebff..16cb25cbf7c5 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -45,6 +45,7 @@ extern efs_block_t efs_map_block(struct inode *, efs_block_t);
extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp);
extern struct dentry *efs_get_parent(struct dentry *);
extern int efs_bmap(struct inode *, int);
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
new file mode 100644
index 000000000000..8872fe8392d6
--- /dev/null
+++ b/include/linux/exportfs.h
@@ -0,0 +1,126 @@
+#ifndef LINUX_EXPORTFS_H
+#define LINUX_EXPORTFS_H 1
+
+#include <linux/types.h>
+
+struct dentry;
+struct super_block;
+struct vfsmount;
+
+
+/**
+ * struct export_operations - for nfsd to communicate with file systems
+ * @decode_fh: decode a file handle fragment and return a &struct dentry
+ * @encode_fh: encode a file handle fragment from a dentry
+ * @get_name: find the name for a given inode in a given directory
+ * @get_parent: find the parent of a given directory
+ * @get_dentry: find a dentry for the inode given a file handle sub-fragment
+ * @find_exported_dentry:
+ * set by the exporting module to a standard helper function.
+ *
+ * Description:
+ * The export_operations structure provides a means for nfsd to communicate
+ * with a particular exported file system - particularly enabling nfsd and
+ * the filesystem to co-operate when dealing with file handles.
+ *
+ * export_operations contains two basic operation for dealing with file
+ * handles, decode_fh() and encode_fh(), and allows for some other
+ * operations to be defined which standard helper routines use to get
+ * specific information from the filesystem.
+ *
+ * nfsd encodes information use to determine which filesystem a filehandle
+ * applies to in the initial part of the file handle. The remainder, termed
+ * a file handle fragment, is controlled completely by the filesystem. The
+ * standard helper routines assume that this fragment will contain one or
+ * two sub-fragments, one which identifies the file, and one which may be
+ * used to identify the (a) directory containing the file.
+ *
+ * In some situations, nfsd needs to get a dentry which is connected into a
+ * specific part of the file tree. To allow for this, it passes the
+ * function acceptable() together with a @context which can be used to see
+ * if the dentry is acceptable. As there can be multiple dentrys for a
+ * given file, the filesystem should check each one for acceptability before
+ * looking for the next. As soon as an acceptable one is found, it should
+ * be returned.
+ *
+ * decode_fh:
+ * @decode_fh is given a &struct super_block (@sb), a file handle fragment
+ * (@fh, @fh_len) and an acceptability testing function (@acceptable,
+ * @context). It should return a &struct dentry which refers to the same
+ * file that the file handle fragment refers to, and which passes the
+ * acceptability test. If it cannot, it should return a %NULL pointer if
+ * the file was found but no acceptable &dentries were available, or a
+ * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
+ * %ENOMEM).
+ *
+ * encode_fh:
+ * @encode_fh should store in the file handle fragment @fh (using at most
+ * @max_len bytes) information that can be used by @decode_fh to recover the
+ * file refered to by the &struct dentry @de. If the @connectable flag is
+ * set, the encode_fh() should store sufficient information so that a good
+ * attempt can be made to find not only the file but also it's place in the
+ * filesystem. This typically means storing a reference to de->d_parent in
+ * the filehandle fragment. encode_fh() should return the number of bytes
+ * stored or a negative error code such as %-ENOSPC
+ *
+ * get_name:
+ * @get_name should find a name for the given @child in the given @parent
+ * directory. The name should be stored in the @name (with the
+ * understanding that it is already pointing to a a %NAME_MAX+1 sized
+ * buffer. get_name() should return %0 on success, a negative error code
+ * or error. @get_name will be called without @parent->i_mutex held.
+ *
+ * get_parent:
+ * @get_parent should find the parent directory for the given @child which
+ * is also a directory. In the event that it cannot be found, or storage
+ * space cannot be allocated, a %ERR_PTR should be returned.
+ *
+ * get_dentry:
+ * Given a &super_block (@sb) and a pointer to a file-system specific inode
+ * identifier, possibly an inode number, (@inump) get_dentry() should find
+ * the identified inode and return a dentry for that inode. Any suitable
+ * dentry can be returned including, if necessary, a new dentry created with
+ * d_alloc_root. The caller can then find any other extant dentrys by
+ * following the d_alias links. If a new dentry was created using
+ * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
+ * should be d_rehash()ed.
+ *
+ * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
+ * can be returned. The @inump will be whatever was passed to
+ * nfsd_find_fh_dentry() in either the @obj or @parent parameters.
+ *
+ * Locking rules:
+ * get_parent is called with child->d_inode->i_mutex down
+ * get_name is not (which is possibly inconsistent)
+ */
+
+struct export_operations {
+ struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh,
+ int fh_len, int fh_type,
+ int (*acceptable)(void *context, struct dentry *de),
+ void *context);
+ int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
+ int connectable);
+ int (*get_name)(struct dentry *parent, char *name,
+ struct dentry *child);
+ struct dentry * (*get_parent)(struct dentry *child);
+ struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
+
+ /* This is set by the exporting module to a standard helper */
+ struct dentry * (*find_exported_dentry)(
+ struct super_block *sb, void *obj, void *parent,
+ int (*acceptable)(void *context, struct dentry *de),
+ void *context);
+};
+
+extern struct dentry *find_exported_dentry(struct super_block *sb, void *obj,
+ void *parent, int (*acceptable)(void *context, struct dentry *de),
+ void *context);
+
+extern int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+ int connectable);
+extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh,
+ int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *),
+ void *context);
+
+#endif /* LINUX_EXPORTFS_H */
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index 4eda0ed76a48..d149f2959e67 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -33,6 +33,8 @@ struct ext2_sb_info {
unsigned long s_gdb_count; /* Number of group descriptor blocks */
unsigned long s_desc_per_block; /* Number of group descriptors per block */
unsigned long s_groups_count; /* Number of groups in the fs */
+ unsigned long s_overhead_last; /* Last calculated overhead */
+ unsigned long s_blocks_last; /* Last seen block count */
struct buffer_head * s_sbh; /* Buffer containing the super block */
struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index f61309c81cc4..d3c08353edf6 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -38,6 +38,8 @@ struct ext3_sb_info {
unsigned long s_gdb_count; /* Number of group descriptor blocks */
unsigned long s_desc_per_block; /* Number of group descriptors per block */
unsigned long s_groups_count; /* Number of groups in the fs */
+ unsigned long s_overhead_last; /* Last calculated overhead */
+ unsigned long s_blocks_last; /* Last seen block count */
struct buffer_head * s_sbh; /* Buffer containing the super block */
struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index 691a713139ce..2347557a327a 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -39,6 +39,8 @@ struct ext4_sb_info {
unsigned long s_gdb_count; /* Number of group descriptor blocks */
unsigned long s_desc_per_block; /* Number of group descriptors per block */
unsigned long s_groups_count; /* Number of groups in the fs */
+ unsigned long s_overhead_last; /* Last calculated overhead */
+ unsigned long s_blocks_last; /* Last seen block count */
struct buffer_head * s_sbh; /* Buffer containing the super block */
struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 66226824ab68..cec54106aa87 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -119,6 +119,7 @@ struct dentry;
#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */
#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */
#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */
+#define FB_ACCEL_OMAP1610 49 /* TI OMAP16xx */
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
@@ -529,6 +530,8 @@ struct fb_cursor_user {
#define FB_EVENT_CONBLANK 0x0C
/* Get drawing requirements */
#define FB_EVENT_GET_REQ 0x0D
+/* Unbind from the console if possible */
+#define FB_EVENT_FB_UNBIND 0x0E
struct fb_event {
struct fb_info *info;
diff --git a/include/linux/file.h b/include/linux/file.h
index a59001e9ea58..0114fbc78061 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -73,6 +73,7 @@ extern struct file * FASTCALL(fget_light(unsigned int fd, int *fput_needed));
extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag));
extern void put_filp(struct file *);
extern int get_unused_fd(void);
+extern int get_unused_fd_flags(int flags);
extern void FASTCALL(put_unused_fd(unsigned int fd));
struct kmem_cache;
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 4631086f5060..2d38b1a74662 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -1,5 +1,8 @@
/* Freezer declarations */
+#ifndef FREEZER_H_INCLUDED
+#define FREEZER_H_INCLUDED
+
#include <linux/sched.h>
#ifdef CONFIG_PM
@@ -115,6 +118,14 @@ static inline int freezer_should_skip(struct task_struct *p)
return !!(p->flags & PF_FREEZER_SKIP);
}
+/*
+ * Tell the freezer that the current task should be frozen by it
+ */
+static inline void set_freezable(void)
+{
+ current->flags &= ~PF_NOFREEZE;
+}
+
#else
static inline int frozen(struct task_struct *p) { return 0; }
static inline int freezing(struct task_struct *p) { return 0; }
@@ -130,4 +141,7 @@ static inline int try_to_freeze(void) { return 0; }
static inline void freezer_do_not_count(void) {}
static inline void freezer_count(void) {}
static inline int freezer_should_skip(struct task_struct *p) { return 0; }
+static inline void set_freezable(void) {}
#endif
+
+#endif /* FREEZER_H_INCLUDED */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4f0b3bf5983c..98205f680476 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -44,7 +44,7 @@ extern int get_max_files(void);
struct inodes_stat_t {
int nr_inodes;
int nr_unused;
- int dummy[5];
+ int dummy[5]; /* padding for sysctl ABI compatibility */
};
extern struct inodes_stat_t inodes_stat;
@@ -283,11 +283,14 @@ extern int dir_notify_enable;
#include <linux/init.h>
#include <linux/pid.h>
#include <linux/mutex.h>
+#include <linux/sysctl.h>
+#include <linux/capability.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
+struct export_operations;
struct hd_geometry;
struct iovec;
struct nameidata;
@@ -820,6 +823,10 @@ struct file_lock {
union {
struct nfs_lock_info nfs_fl;
struct nfs4_lock_info nfs4_fl;
+ struct {
+ struct list_head link; /* link in AFS vnode's pending_locks list */
+ int state; /* state of grant or error if -ve */
+ } afs;
} fl_u;
};
@@ -984,6 +991,9 @@ enum {
#define put_fs_excl() atomic_dec(&current->fs_excl)
#define has_fs_excl() atomic_read(&current->fs_excl)
+#define is_owner_or_cap(inode) \
+ ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER))
+
/* not quite ready to be deprecated, but... */
extern void lock_super(struct super_block *);
extern void unlock_super(struct super_block *);
@@ -1273,119 +1283,6 @@ static inline void file_accessed(struct file *file)
int sync_inode(struct inode *inode, struct writeback_control *wbc);
-/**
- * struct export_operations - for nfsd to communicate with file systems
- * @decode_fh: decode a file handle fragment and return a &struct dentry
- * @encode_fh: encode a file handle fragment from a dentry
- * @get_name: find the name for a given inode in a given directory
- * @get_parent: find the parent of a given directory
- * @get_dentry: find a dentry for the inode given a file handle sub-fragment
- * @find_exported_dentry:
- * set by the exporting module to a standard helper function.
- *
- * Description:
- * The export_operations structure provides a means for nfsd to communicate
- * with a particular exported file system - particularly enabling nfsd and
- * the filesystem to co-operate when dealing with file handles.
- *
- * export_operations contains two basic operation for dealing with file
- * handles, decode_fh() and encode_fh(), and allows for some other
- * operations to be defined which standard helper routines use to get
- * specific information from the filesystem.
- *
- * nfsd encodes information use to determine which filesystem a filehandle
- * applies to in the initial part of the file handle. The remainder, termed
- * a file handle fragment, is controlled completely by the filesystem. The
- * standard helper routines assume that this fragment will contain one or
- * two sub-fragments, one which identifies the file, and one which may be
- * used to identify the (a) directory containing the file.
- *
- * In some situations, nfsd needs to get a dentry which is connected into a
- * specific part of the file tree. To allow for this, it passes the
- * function acceptable() together with a @context which can be used to see
- * if the dentry is acceptable. As there can be multiple dentrys for a
- * given file, the filesystem should check each one for acceptability before
- * looking for the next. As soon as an acceptable one is found, it should
- * be returned.
- *
- * decode_fh:
- * @decode_fh is given a &struct super_block (@sb), a file handle fragment
- * (@fh, @fh_len) and an acceptability testing function (@acceptable,
- * @context). It should return a &struct dentry which refers to the same
- * file that the file handle fragment refers to, and which passes the
- * acceptability test. If it cannot, it should return a %NULL pointer if
- * the file was found but no acceptable &dentries were available, or a
- * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
- * %ENOMEM).
- *
- * encode_fh:
- * @encode_fh should store in the file handle fragment @fh (using at most
- * @max_len bytes) information that can be used by @decode_fh to recover the
- * file refered to by the &struct dentry @de. If the @connectable flag is
- * set, the encode_fh() should store sufficient information so that a good
- * attempt can be made to find not only the file but also it's place in the
- * filesystem. This typically means storing a reference to de->d_parent in
- * the filehandle fragment. encode_fh() should return the number of bytes
- * stored or a negative error code such as %-ENOSPC
- *
- * get_name:
- * @get_name should find a name for the given @child in the given @parent
- * directory. The name should be stored in the @name (with the
- * understanding that it is already pointing to a a %NAME_MAX+1 sized
- * buffer. get_name() should return %0 on success, a negative error code
- * or error. @get_name will be called without @parent->i_mutex held.
- *
- * get_parent:
- * @get_parent should find the parent directory for the given @child which
- * is also a directory. In the event that it cannot be found, or storage
- * space cannot be allocated, a %ERR_PTR should be returned.
- *
- * get_dentry:
- * Given a &super_block (@sb) and a pointer to a file-system specific inode
- * identifier, possibly an inode number, (@inump) get_dentry() should find
- * the identified inode and return a dentry for that inode. Any suitable
- * dentry can be returned including, if necessary, a new dentry created with
- * d_alloc_root. The caller can then find any other extant dentrys by
- * following the d_alias links. If a new dentry was created using
- * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
- * should be d_rehash()ed.
- *
- * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
- * can be returned. The @inump will be whatever was passed to
- * nfsd_find_fh_dentry() in either the @obj or @parent parameters.
- *
- * Locking rules:
- * get_parent is called with child->d_inode->i_mutex down
- * get_name is not (which is possibly inconsistent)
- */
-
-struct export_operations {
- struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
- int (*acceptable)(void *context, struct dentry *de),
- void *context);
- int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
- int connectable);
-
- /* the following are only called from the filesystem itself */
- int (*get_name)(struct dentry *parent, char *name,
- struct dentry *child);
- struct dentry * (*get_parent)(struct dentry *child);
- struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
-
- /* This is set by the exporting module to a standard helper */
- struct dentry * (*find_exported_dentry)(
- struct super_block *sb, void *obj, void *parent,
- int (*acceptable)(void *context, struct dentry *de),
- void *context);
-
-
-};
-
-extern struct dentry *
-find_exported_dentry(struct super_block *sb, void *obj, void *parent,
- int (*acceptable)(void *context, struct dentry *de),
- void *context);
-
struct file_system_type {
const char *name;
int fs_flags;
@@ -1522,7 +1419,7 @@ extern void putname(const char *name);
#ifdef CONFIG_BLOCK
extern int register_blkdev(unsigned int, const char *);
-extern int unregister_blkdev(unsigned int, const char *);
+extern void unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t);
extern void bd_set_size(struct block_device *, loff_t size);
extern void bd_forget(struct inode *inode);
@@ -1610,6 +1507,9 @@ extern int __invalidate_device(struct block_device *);
extern int invalidate_partition(struct gendisk *, int);
#endif
extern int invalidate_inodes(struct super_block *);
+unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+ pgoff_t start, pgoff_t end,
+ bool be_atomic);
unsigned long invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end);
@@ -2043,5 +1943,9 @@ static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */
+int proc_nr_files(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+
+
#endif /* __KERNEL__ */
#endif /* _LINUX_FS_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 73710d617775..695741b0e420 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -112,7 +112,7 @@ struct fsl_usb2_platform_data {
struct fsl_spi_platform_data {
u32 initial_spmode; /* initial SPMODE value */
u16 bus_num;
-
+ bool qe_mode;
/* board specific information */
u16 max_chipselect;
void (*activate_cs)(u8 cs, u8 polarity);
@@ -120,5 +120,10 @@ struct fsl_spi_platform_data {
u32 sysclk;
};
+struct mpc8xx_pcmcia_ops {
+ void(*hw_ctrl)(int slot, int enable);
+ int(*voltage_set)(int slot, int vcc, int vpp);
+};
+
#endif /* _FSL_DEVICE_H_ */
#endif /* __KERNEL__ */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 534744efe30d..9fbe9d258e22 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -339,7 +339,7 @@ struct fuse_dirent {
char name[0];
};
-#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
+#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
#define FUSE_DIRENT_SIZE(d) \
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 0d2ef0b082a6..bc68dd9a6d41 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -30,6 +30,9 @@ struct vm_area_struct;
* cannot handle allocation failures.
*
* __GFP_NORETRY: The VM implementation must not retry indefinitely.
+ *
+ * __GFP_MOVABLE: Flag that this page will be movable by the page migration
+ * mechanism or reclaimed
*/
#define __GFP_WAIT ((__force gfp_t)0x10u) /* Can wait and reschedule? */
#define __GFP_HIGH ((__force gfp_t)0x20u) /* Should access emergency pools? */
@@ -45,6 +48,7 @@ struct vm_area_struct;
#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
#define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
#define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */
+#define __GFP_MOVABLE ((__force gfp_t)0x80000u) /* Page is movable */
#define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
@@ -53,7 +57,8 @@ struct vm_area_struct;
#define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
__GFP_NOFAIL|__GFP_NORETRY|__GFP_COMP| \
- __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE)
+ __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE| \
+ __GFP_MOVABLE)
/* This equals 0, but use constants in case they ever change */
#define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH)
@@ -65,6 +70,15 @@ struct vm_area_struct;
#define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
#define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
__GFP_HIGHMEM)
+#define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_HIGHMEM | \
+ __GFP_MOVABLE)
+#define GFP_NOFS_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
+#define GFP_USER_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_MOVABLE)
+#define GFP_HIGHUSER_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_HIGHMEM | \
+ __GFP_MOVABLE)
#ifdef CONFIG_NUMA
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
@@ -92,6 +106,9 @@ static inline enum zone_type gfp_zone(gfp_t flags)
if (flags & __GFP_DMA32)
return ZONE_DMA32;
#endif
+ if ((flags & (__GFP_HIGHMEM | __GFP_MOVABLE)) ==
+ (__GFP_HIGHMEM | __GFP_MOVABLE))
+ return ZONE_MOVABLE;
#ifdef CONFIG_HIGHMEM
if (flags & __GFP_HIGHMEM)
return ZONE_HIGHMEM;
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 98e2cce996a4..12c5e4e3135a 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -73,10 +73,27 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
}
#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+/**
+ * __alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA with caller-specified movable GFP flags
+ * @movableflags: The GFP flags related to the pages future ability to move like __GFP_MOVABLE
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA but the caller is expected
+ * to specify via movableflags whether the page will be movable in the
+ * future or not
+ *
+ * An architecture may override this function by defining
+ * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE and providing their own
+ * implementation.
+ */
static inline struct page *
-alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+__alloc_zeroed_user_highpage(gfp_t movableflags,
+ struct vm_area_struct *vma,
+ unsigned long vaddr)
{
- struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
+ struct page *page = alloc_page_vma(GFP_HIGHUSER | movableflags,
+ vma, vaddr);
if (page)
clear_user_highpage(page, vaddr);
@@ -85,6 +102,36 @@ alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
}
#endif
+/**
+ * alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA that the caller knows will
+ * not be able to move in the future using move_pages() or reclaim. If it
+ * is known that the page can move, use alloc_zeroed_user_highpage_movable
+ */
+static inline struct page *
+alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
+{
+ return __alloc_zeroed_user_highpage(0, vma, vaddr);
+}
+
+/**
+ * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move
+ * @vma: The VMA the page is to be allocated for
+ * @vaddr: The virtual address the page will be inserted into
+ *
+ * This function will allocate a page for a VMA that the caller knows will
+ * be able to migrate in the future using move_pages() or reclaimed
+ */
+static inline struct page *
+alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
+ unsigned long vaddr)
+{
+ return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
+}
+
static inline void clear_highpage(struct page *page)
{
void *kaddr = kmap_atomic(page, KM_USER0);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 17c29dca8354..540799bc85f8 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -329,12 +329,13 @@ extern void sysrq_timer_list_show(void);
#ifdef CONFIG_TIMER_STATS
extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
- void *timerf, char * comm);
+ void *timerf, char *comm,
+ unsigned int timer_flag);
static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
{
timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
- timer->function, timer->start_comm);
+ timer->function, timer->start_comm, 0);
}
extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 2c13715e9dde..49b7053043ad 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -15,6 +15,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
}
int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
+int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
@@ -29,6 +30,7 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to);
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
extern unsigned long max_huge_pages;
+extern unsigned long hugepages_treat_as_movable;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 52f53e2e70c3..333a370a3bdc 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h> /* work_struct */
#include <linux/mempool.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/semaphore.h> /* Needed for MUTEX init macros */
@@ -425,7 +426,7 @@ struct i2o_device {
struct device device;
- struct semaphore lock; /* device lock */
+ struct mutex lock; /* device lock */
};
/*
@@ -544,7 +545,7 @@ struct i2o_controller {
struct i2o_dma hrt; /* HW Resource Table */
i2o_lct *lct; /* Logical Config Table */
struct i2o_dma dlct; /* Temp LCT */
- struct semaphore lct_lock; /* Lock for LCT updates */
+ struct mutex lct_lock; /* Lock for LCT updates */
struct i2o_dma status_block; /* IOP status block */
struct i2o_io base; /* controller messaging unit */
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 915572fa030b..0edda411959c 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -78,8 +78,11 @@ void *idr_find(struct idr *idp, int id);
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
int idr_get_new(struct idr *idp, void *ptr, int *id);
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+int idr_for_each(struct idr *idp,
+ int (*fn)(int id, void *p, void *data), void *data);
void *idr_replace(struct idr *idp, void *ptr, int id);
void idr_remove(struct idr *idp, int id);
+void idr_remove_all(struct idr *idp);
void idr_destroy(struct idr *idp);
void idr_init(struct idr *idp);
diff --git a/include/linux/init.h b/include/linux/init.h
index 56ec4c62eee0..5b5285316339 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -171,9 +171,6 @@ struct obs_kernel_param {
#define __setup(str, fn) \
__setup_param(str, fn, fn, 0)
-#define __obsolete_setup(str) \
- __setup_null_param(str, __LINE__)
-
/* NOTE: fn is as per module_param, not __setup! Emits warning if fn
* returns non-zero. */
#define early_param(str, fn) \
@@ -239,7 +236,6 @@ void __init parse_early_param(void);
#define __setup_param(str, unique_id, fn) /* nothing */
#define __setup_null_param(str, unique_id) /* nothing */
#define __setup(str, func) /* nothing */
-#define __obsolete_setup(str) /* nothing */
#endif
/* Data marked not to be saved by software suspend */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 276ccaa2670c..cab741c2d603 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -8,6 +8,7 @@
#include <linux/lockdep.h>
#include <linux/ipc.h>
#include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
#define INIT_FDTABLE \
{ \
@@ -78,6 +79,7 @@ extern struct nsproxy init_nsproxy;
.uts_ns = &init_uts_ns, \
.mnt_ns = NULL, \
INIT_IPC_NS(ipc_ns) \
+ .user_ns = &init_user_ns, \
}
#define INIT_SIGHAND(sighand) { \
diff --git a/include/linux/io.h b/include/linux/io.h
index 8423dd376514..e3b2dda6c8eb 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -63,32 +63,7 @@ void __iomem * devm_ioremap(struct device *dev, unsigned long offset,
void __iomem * devm_ioremap_nocache(struct device *dev, unsigned long offset,
unsigned long size);
void devm_iounmap(struct device *dev, void __iomem *addr);
-
-/**
- * check_signature - find BIOS signatures
- * @io_addr: mmio address to check
- * @signature: signature block
- * @length: length of signature
- *
- * Perform a signature comparison with the mmio address io_addr. This
- * address should have been obtained by ioremap.
- * Returns 1 on a match.
- */
-
-static inline int check_signature(const volatile void __iomem *io_addr,
- const unsigned char *signature, int length)
-{
- int retval = 0;
- do {
- if (readb(io_addr) != *signature)
- goto out;
- io_addr++;
- signature++;
- length--;
- } while (length);
- retval = 1;
-out:
- return retval;
-}
+int check_signature(const volatile void __iomem *io_addr,
+ const unsigned char *signature, int length);
#endif /* _LINUX_IO_H */
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 1980867a64a4..3fd3ddd5f0d9 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -52,6 +52,7 @@ struct ipc_perm
#ifdef __KERNEL__
#include <linux/kref.h>
+#include <linux/spinlock.h>
#define IPCMNI 32768 /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
@@ -92,6 +93,7 @@ extern struct ipc_namespace init_ipc_ns;
#ifdef CONFIG_SYSVIPC
#define INIT_IPC_NS(ns) .ns = &init_ipc_ns,
+extern void free_ipc_ns(struct kref *kref);
extern struct ipc_namespace *copy_ipcs(unsigned long flags,
struct ipc_namespace *ns);
#else
@@ -103,13 +105,9 @@ static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
}
#endif
-#ifdef CONFIG_IPC_NS
-extern void free_ipc_ns(struct kref *kref);
-#endif
-
static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
{
-#ifdef CONFIG_IPC_NS
+#ifdef CONFIG_SYSVIPC
if (ns)
kref_get(&ns->kref);
#endif
@@ -118,7 +116,7 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
static inline void put_ipc_ns(struct ipc_namespace *ns)
{
-#ifdef CONFIG_IPC_NS
+#ifdef CONFIG_SYSVIPC
kref_put(&ns->kref, free_ipc_ns);
#endif
}
@@ -126,5 +124,3 @@ static inline void put_ipc_ns(struct ipc_namespace *ns)
#endif /* __KERNEL__ */
#endif /* _LINUX_IPC_H */
-
-
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1695054e8c63..44657197fcb0 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -161,6 +161,7 @@ struct irq_desc {
unsigned int wake_depth; /* nested wake enables */
unsigned int irq_count; /* For detecting broken IRQs */
unsigned int irqs_unhandled;
+ unsigned long last_unhandled; /* Aging timer for unhandled count */
spinlock_t lock;
#ifdef CONFIG_SMP
cpumask_t affinity;
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 5f06527dca21..f73de6fb5c68 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -7,9 +7,9 @@
#include <linux/errno.h>
-#define KSYM_NAME_LEN 127
-#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \
- 2*(BITS_PER_LONG*3/10) + MODULE_NAME_LEN + 1)
+#define KSYM_NAME_LEN 128
+#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
+ 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
#ifdef CONFIG_KALLSYMS
/* Lookup the address for a symbol. Returns 0 if not found. */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 7a4852505914..1eb9cde550c4 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -210,6 +210,7 @@ extern enum system_states {
#define TAINT_MACHINE_CHECK (1<<4)
#define TAINT_BAD_PAGE (1<<5)
#define TAINT_USER (1<<6)
+#define TAINT_DIE (1<<7)
extern void dump_stack(void);
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
index aea34e74c496..8c4350a9ed87 100644
--- a/include/linux/kernelcapi.h
+++ b/include/linux/kernelcapi.h
@@ -64,7 +64,7 @@ struct capi20_appl {
unsigned long nrecvdatapkt;
unsigned long nsentctlpkt;
unsigned long nsentdatapkt;
- struct semaphore recv_sem;
+ struct mutex recv_mtx;
struct sk_buff_head recv_queue;
struct work_struct recv_work;
int release_in_progress;
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 88afceffb7cb..494bed7c2fc1 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -13,7 +13,6 @@
#define __LINUX_LEDS_H_INCLUDED
#include <linux/list.h>
-#include <linux/spinlock.h>
struct device;
struct class_device;
diff --git a/include/linux/limits.h b/include/linux/limits.h
index eaf2e099f125..2d0f94162fb3 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -5,8 +5,6 @@
#define NGROUPS_MAX 65536 /* supplemental group IDs are available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
-#define CHILD_MAX 999 /* no limit :-) */
-#define OPEN_MAX 256 /* # open files a process may have */
#define LINK_MAX 127 /* # links a file may have */
#define MAX_CANON 255 /* size of the canonical input queue */
#define MAX_INPUT 255 /* size of the type-ahead buffer */
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
index 9c01bde5bf1b..08a92969c76e 100644
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -33,5 +33,13 @@ struct linux_logo {
};
extern const struct linux_logo *fb_find_logo(int depth);
+#ifdef CONFIG_FB_LOGO_EXTRA
+extern void fb_append_extra_logo(const struct linux_logo *logo,
+ unsigned int n);
+#else
+static inline void fb_append_extra_logo(const struct linux_logo *logo,
+ unsigned int n)
+{}
+#endif
#endif /* _LINUX_LINUX_LOGO_H */
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 246de1d84a26..6f1637c61e10 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -27,6 +27,7 @@ struct nlmsvc_binding {
struct nfs_fh *,
struct file **);
void (*fclose)(struct file *);
+ unsigned long (*get_grace_period)(void);
};
extern struct nlmsvc_binding * nlmsvc_ops;
@@ -38,4 +39,12 @@ extern int nlmclnt_proc(struct inode *, int, struct file_lock *);
extern int lockd_up(int proto);
extern void lockd_down(void);
+unsigned long get_nfs_grace_period(void);
+
+#ifdef CONFIG_NFSD_V4
+unsigned long get_nfs4_grace_period(void);
+#else
+static inline unsigned long get_nfs4_grace_period(void) {return 0;}
+#endif
+
#endif /* LINUX_LOCKD_BIND_H */
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
index 582d8b711a13..d793497ec1ca 100644
--- a/include/linux/lzo.h
+++ b/include/linux/lzo.h
@@ -17,7 +17,7 @@
#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
-#define lzo1x_worst_compress(x) (x + (x / 64) + 16 + 3)
+#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
int lzo1x_1_compress(const unsigned char *src, size_t src_len,
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index daabb3aa1ec6..e147cf50529f 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -159,7 +159,7 @@ extern void mpol_fix_fork_child_flag(struct task_struct *p);
extern struct mempolicy default_policy;
extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
- unsigned long addr);
+ unsigned long addr, gfp_t gfp_flags);
extern unsigned slab_node(struct mempolicy *policy);
extern enum zone_type policy_zone;
@@ -256,9 +256,9 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p)
#define set_cpuset_being_rebound(x) do {} while (0)
static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
- unsigned long addr)
+ unsigned long addr, gfp_t gfp_flags)
{
- return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+ return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags);
}
static inline int do_migrate_pages(struct mm_struct *mm,
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1c1207472bb4..a5c451816fdc 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,7 +2,6 @@
#define _LINUX_MM_H
#include <linux/errno.h>
-#include <linux/capability.h>
#ifdef __KERNEL__
@@ -27,7 +26,6 @@ extern unsigned long max_mapnr;
extern unsigned long num_physpages;
extern void * high_memory;
-extern unsigned long vmalloc_earlyreserve;
extern int page_cluster;
#ifdef CONFIG_SYSCTL
@@ -601,6 +599,7 @@ static inline struct address_space *page_mapping(struct page *page)
{
struct address_space *mapping = page->mapping;
+ VM_BUG_ON(PageSlab(page));
if (unlikely(PageSwapCache(page)))
mapping = &swapper_space;
#ifdef CONFIG_SLUB
@@ -812,27 +811,31 @@ extern unsigned long do_mremap(unsigned long addr,
unsigned long flags, unsigned long new_addr);
/*
- * Prototype to add a shrinker callback for ageable caches.
- *
- * These functions are passed a count `nr_to_scan' and a gfpmask. They should
- * scan `nr_to_scan' objects, attempting to free them.
+ * A callback you can register to apply pressure to ageable caches.
*
- * The callback must return the number of objects which remain in the cache.
+ * 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'. It should
+ * look through the least-recently-used 'nr_to_scan' entries and
+ * attempt to free them up. It should return the number of objects
+ * which remain in the cache. If it returns -1, it means it cannot do
+ * any scanning at this time (eg. there is a risk of deadlock).
*
- * The callback will be passed nr_to_scan == 0 when the VM is querying the
- * cache size, so a fastpath for that case is appropriate.
- */
-typedef int (*shrinker_t)(int nr_to_scan, gfp_t gfp_mask);
-
-/*
- * Add an aging callback. The int is the number of 'seeks' it takes
- * to recreate one of the objects that these functions age.
+ * The 'gfpmask' refers to the allocation we are currently trying to
+ * fulfil.
+ *
+ * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
+ * querying the cache size, so a fastpath for that case is appropriate.
*/
+struct shrinker {
+ int (*shrink)(int nr_to_scan, gfp_t gfp_mask);
+ int seeks; /* seeks to recreate an obj */
-#define DEFAULT_SEEKS 2
-struct shrinker;
-extern struct shrinker *set_shrinker(int, shrinker_t);
-extern void remove_shrinker(struct shrinker *shrinker);
+ /* These are for internal use */
+ struct list_head list;
+ long nr; /* objs pending delete */
+};
+#define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
+extern void register_shrinker(struct shrinker *);
+extern void unregister_shrinker(struct shrinker *);
/*
* Some shared mappigns will want the pages marked read-only
@@ -1072,6 +1075,10 @@ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned lo
extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long pgoff);
+extern unsigned long mmap_region(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long flags,
+ unsigned int vm_flags, unsigned long pgoff,
+ int accountable);
static inline unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index d09b1345a3a1..da8eb8ad9e9b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -24,6 +24,14 @@
#endif
#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
+/*
+ * PAGE_ALLOC_COSTLY_ORDER is the order at which allocations are deemed
+ * costly to service. That is between allocation orders which should
+ * coelesce naturally under reasonable reclaim pressure and those which
+ * will not.
+ */
+#define PAGE_ALLOC_COSTLY_ORDER 3
+
struct free_area {
struct list_head free_list;
unsigned long nr_free;
@@ -146,6 +154,7 @@ enum zone_type {
*/
ZONE_HIGHMEM,
#endif
+ ZONE_MOVABLE,
MAX_NR_ZONES
};
@@ -167,6 +176,7 @@ enum zone_type {
+ defined(CONFIG_ZONE_DMA32) \
+ 1 \
+ defined(CONFIG_HIGHMEM) \
+ + 1 \
)
#if __ZONE_COUNT < 2
#define ZONES_SHIFT 0
@@ -499,10 +509,22 @@ static inline int populated_zone(struct zone *zone)
return (!!zone->present_pages);
}
+extern int movable_zone;
+
+static inline int zone_movable_is_highmem(void)
+{
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_ARCH_POPULATES_NODE_MAP)
+ return movable_zone == ZONE_HIGHMEM;
+#else
+ return 0;
+#endif
+}
+
static inline int is_highmem_idx(enum zone_type idx)
{
#ifdef CONFIG_HIGHMEM
- return (idx == ZONE_HIGHMEM);
+ return (idx == ZONE_HIGHMEM ||
+ (idx == ZONE_MOVABLE && zone_movable_is_highmem()));
#else
return 0;
#endif
@@ -522,7 +544,9 @@ static inline int is_normal_idx(enum zone_type idx)
static inline int is_highmem(struct zone *zone)
{
#ifdef CONFIG_HIGHMEM
- return zone == zone->zone_pgdat->node_zones + ZONE_HIGHMEM;
+ int zone_idx = zone - zone->zone_pgdat->node_zones;
+ return zone_idx == ZONE_HIGHMEM ||
+ (zone_idx == ZONE_MOVABLE && zone_movable_is_highmem());
#else
return 0;
#endif
@@ -566,6 +590,11 @@ int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *, int,
int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int,
struct file *, void __user *, size_t *, loff_t *);
+extern int numa_zonelist_order_handler(struct ctl_table *, int,
+ struct file *, void __user *, size_t *, loff_t *);
+extern char numa_zonelist_order[];
+#define NUMA_ZONELIST_ORDER_LEN 16 /* string buffer size */
+
#include <linux/topology.h>
/* Returns the number of the current Node. */
#ifndef numa_node_id
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 1fa4d9813b31..8eed44f8ca73 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -14,7 +14,7 @@ struct mnt_namespace {
int event;
};
-extern struct mnt_namespace *copy_mnt_ns(int, struct mnt_namespace *,
+extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
struct fs_struct *);
extern void __put_mnt_ns(struct mnt_namespace *ns);
diff --git a/include/linux/module.h b/include/linux/module.h
index e6e0f86ef5fc..b6a646cea1cb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -6,7 +6,6 @@
* Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
* Rewritten again by Rusty Russell, 2002
*/
-#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/stat.h>
#include <linux/compiler.h>
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 0e09c005dda8..f950921523f5 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -146,7 +146,7 @@ struct fat_boot_fsinfo {
};
struct msdos_dir_entry {
- __u8 name[8],ext[3]; /* name and extension */
+ __u8 name[MSDOS_NAME];/* name and extension */
__u8 attr; /* attribute bits */
__u8 lcase; /* Case for base and extension */
__u8 ctime_cs; /* Creation time, centiseconds (0-199) */
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 83e39eb054d3..88766e43e121 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -148,8 +148,6 @@ struct ncp_nls_ioctl
#include <linux/ncp_fs_i.h>
#include <linux/ncp_fs_sb.h>
-/* undef because public define in umsdos_fs.h (ncp_fs.h isn't public) */
-#undef PRINTK
/* define because it is easy to change PRINTK to {*}PRINTK */
#define PRINTK(format, args...) printk(KERN_DEBUG format , ## args)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 322b5eae57dd..da7a13c97eb8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -262,8 +262,6 @@ enum netdev_state_t
__LINK_STATE_LINKWATCH_PENDING,
__LINK_STATE_DORMANT,
__LINK_STATE_QDISC_RUNNING,
- /* Set by the netpoll NAPI code */
- __LINK_STATE_POLL_LIST_FROZEN,
};
@@ -1022,14 +1020,6 @@ static inline void netif_rx_complete(struct net_device *dev)
{
unsigned long flags;
-#ifdef CONFIG_NETPOLL
- /* Prevent race with netpoll - yes, this is a kludge.
- * But at least it doesn't penalize the non-netpoll
- * code path. */
- if (test_bit(__LINK_STATE_POLL_LIST_FROZEN, &dev->state))
- return;
-#endif
-
local_irq_save(flags);
__netif_rx_complete(dev);
local_irq_restore(flags);
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 9f62d6182d32..78feb7beff75 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -42,6 +42,9 @@
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
#define NFSEXP_ALLFLAGS 0xFE3F
+/* The flags that may vary depending on security flavor: */
+#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+ | NFSEXP_ALLSQUASH)
#ifdef __KERNEL__
@@ -64,6 +67,19 @@ struct nfsd4_fs_locations {
int migrated;
};
+/*
+ * We keep an array of pseudoflavors with the export, in order from most
+ * to least preferred. For the forseeable future, we don't expect more
+ * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3,
+ * spkm3i, and spkm3p (and using all 8 at once should be rare).
+ */
+#define MAX_SECINFO_LIST 8
+
+struct exp_flavor_info {
+ u32 pseudoflavor;
+ u32 flags;
+};
+
struct svc_export {
struct cache_head h;
struct auth_domain * ex_client;
@@ -76,6 +92,8 @@ struct svc_export {
int ex_fsid;
unsigned char * ex_uuid; /* 16 byte fsid */
struct nfsd4_fs_locations ex_fslocs;
+ int ex_nflavors;
+ struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST];
};
/* an "export key" (expkey) maps a filehandlefragement to an
@@ -95,10 +113,22 @@ struct svc_expkey {
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
-#define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY)
#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
+static inline int EX_RDONLY(struct svc_export *exp, struct svc_rqst *rqstp)
+{
+ struct exp_flavor_info *f;
+ struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
+
+ for (f = exp->ex_flavors; f < end; f++) {
+ if (f->pseudoflavor == rqstp->rq_flavor)
+ return f->flags & NFSEXP_READONLY;
+ }
+ return exp->ex_flags & NFSEXP_READONLY;
+}
+
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
/*
* Function declarations
@@ -112,13 +142,19 @@ struct svc_export * exp_get_by_name(struct auth_domain *clp,
struct vfsmount *mnt,
struct dentry *dentry,
struct cache_req *reqp);
+struct svc_export * rqst_exp_get_by_name(struct svc_rqst *,
+ struct vfsmount *,
+ struct dentry *);
struct svc_export * exp_parent(struct auth_domain *clp,
struct vfsmount *mnt,
struct dentry *dentry,
struct cache_req *reqp);
+struct svc_export * rqst_exp_parent(struct svc_rqst *,
+ struct vfsmount *mnt,
+ struct dentry *dentry);
int exp_rootfh(struct auth_domain *,
char *path, struct knfsd_fh *, int maxsize);
-__be32 exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
+__be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
__be32 nfserrno(int errno);
extern struct cache_detail svc_export_cache;
@@ -135,6 +171,7 @@ static inline void exp_get(struct svc_export *exp)
extern struct svc_export *
exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
struct cache_req *reqp);
+struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
#endif /* __KERNEL__ */
diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h
deleted file mode 100644
index af0979704afb..000000000000
--- a/include/linux/nfsd/interface.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * include/linux/nfsd/interface.h
- *
- * defines interface between nfsd and other bits of
- * the kernel. Particularly filesystems (eventually).
- *
- * Copyright (C) 2000 Neil Brown <neilb@cse.unsw.edu.au>
- */
-
-#ifndef LINUX_NFSD_INTERFACE_H
-#define LINUX_NFSD_INTERFACE_H
-
-#endif /* LINUX_NFSD_INTERFACE_H */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 72feac581aa3..e452256d3f72 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -22,7 +22,6 @@
#include <linux/nfsd/export.h>
#include <linux/nfsd/auth.h>
#include <linux/nfsd/stats.h>
-#include <linux/nfsd/interface.h>
/*
* nfsd version
*/
@@ -72,6 +71,9 @@ int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
struct svc_export **expp);
__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
const char *, int, struct svc_fh *);
+__be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
+ const char *, int,
+ struct svc_export **, struct dentry **);
__be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
struct iattr *, int, time_t);
#ifdef CONFIG_NFSD_V4
@@ -120,7 +122,8 @@ __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct kstatfs *);
int nfsd_notify_change(struct inode *, struct iattr *);
-__be32 nfsd_permission(struct svc_export *, struct dentry *, int);
+__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
+ struct dentry *, int);
int nfsd_sync_dir(struct dentry *dp);
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -149,6 +152,7 @@ extern int nfsd_max_blksize;
* NFSv4 State
*/
#ifdef CONFIG_NFSD_V4
+extern unsigned int max_delegations;
void nfs4_state_init(void);
int nfs4_state_start(void);
void nfs4_state_shutdown(void);
@@ -236,6 +240,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_badname __constant_htonl(NFSERR_BADNAME)
#define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN)
#define nfserr_locked __constant_htonl(NFSERR_LOCKED)
+#define nfserr_wrongsec __constant_htonl(NFSERR_WRONGSEC)
#define nfserr_replay_me __constant_htonl(NFSERR_REPLAY_ME)
/* error codes for internal use */
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index ab5c236bd9a7..db348f749376 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -67,7 +67,7 @@ struct nfs4_cb_recall {
int cbr_trunc;
stateid_t cbr_stateid;
u32 cbr_fhlen;
- u32 cbr_fhval[NFS4_FHSIZE];
+ char cbr_fhval[NFS4_FHSIZE];
struct nfs4_delegation *cbr_dp;
};
@@ -224,6 +224,7 @@ struct nfs4_file {
struct inode *fi_inode;
u32 fi_id; /* used with stateowner->so_id
* for stateid_hashtbl hash */
+ bool fi_had_conflict;
};
/*
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 09799bcee0ac..1b653267133a 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -293,6 +293,12 @@ struct nfsd4_rename {
struct nfsd4_change_info rn_tinfo; /* response */
};
+struct nfsd4_secinfo {
+ u32 si_namelen; /* request */
+ char *si_name; /* request */
+ struct svc_export *si_exp; /* response */
+};
+
struct nfsd4_setattr {
stateid_t sa_stateid; /* request */
u32 sa_bmval[2]; /* request */
@@ -365,6 +371,7 @@ struct nfsd4_op {
struct nfsd4_remove remove;
struct nfsd4_rename rename;
clientid_t renew;
+ struct nfsd4_secinfo secinfo;
struct nfsd4_setattr setattr;
struct nfsd4_setclientid setclientid;
struct nfsd4_setclientid_confirm setclientid_confirm;
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 189e0dc993ab..ce06188b7a56 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -28,10 +28,11 @@ struct nsproxy {
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
+ struct user_namespace *user_ns;
};
extern struct nsproxy init_nsproxy;
-int copy_namespaces(int flags, struct task_struct *tsk);
+int copy_namespaces(unsigned long flags, struct task_struct *tsk);
void get_task_namespaces(struct task_struct *tsk);
void free_nsproxy(struct nsproxy *ns);
int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 37a71580ad8a..5e84f2e8d54c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -432,6 +432,8 @@ extern struct bus_type pci_bus_type;
* code, or pci core code. */
extern struct list_head pci_root_buses; /* list of all known PCI buses */
extern struct list_head pci_devices; /* list of all devices */
+/* Some device drivers need know if pci is initiated */
+extern int no_pci_devices(void);
void pcibios_fixup_bus(struct pci_bus *);
int __must_check pcibios_enable_device(struct pci_dev *, int mask);
@@ -724,6 +726,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *
{ return NULL; }
#define pci_dev_present(ids) (0)
+#define no_pci_devices() (1)
#define pci_find_present(ids) (NULL)
#define pci_dev_put(dev) do { } while (0)
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index b72be2f79e6a..926adaae0f96 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -1,7 +1,7 @@
#ifndef __LINUX_PERCPU_H
#define __LINUX_PERCPU_H
-#include <linux/spinlock.h> /* For preempt_disable() */
+#include <linux/preempt.h>
#include <linux/slab.h> /* For kmalloc() */
#include <linux/smp.h>
#include <linux/string.h> /* For memset() */
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index f5aa593ccf32..3d9f70972cdf 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -8,6 +8,7 @@
#include <linux/spinlock.h>
#include <linux/smp.h>
+#include <linux/list.h>
#include <linux/threads.h>
#include <linux/percpu.h>
#include <linux/types.h>
@@ -17,6 +18,9 @@
struct percpu_counter {
spinlock_t lock;
s64 count;
+#ifdef CONFIG_HOTPLUG_CPU
+ struct list_head list; /* All percpu_counters are on a list */
+#endif
s32 *counters;
};
@@ -26,18 +30,8 @@ struct percpu_counter {
#define FBC_BATCH (NR_CPUS*4)
#endif
-static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
-{
- spin_lock_init(&fbc->lock);
- fbc->count = amount;
- fbc->counters = alloc_percpu(s32);
-}
-
-static inline void percpu_counter_destroy(struct percpu_counter *fbc)
-{
- free_percpu(fbc->counters);
-}
-
+void percpu_counter_init(struct percpu_counter *fbc, s64 amount);
+void percpu_counter_destroy(struct percpu_counter *fbc);
void percpu_counter_mod(struct percpu_counter *fbc, s32 amount);
s64 percpu_counter_sum(struct percpu_counter *fbc);
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 169c6c24209b..b9a17e08ff0f 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -29,7 +29,7 @@ static inline void get_pid_ns(struct pid_namespace *ns)
kref_get(&ns->kref);
}
-extern struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *ns);
+extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
extern void free_pid_ns(struct kref *kref);
static inline void put_pid_ns(struct pid_namespace *ns)
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 52a9be41250d..e2eff9079fe9 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -59,4 +59,8 @@
# define PR_ENDIAN_LITTLE 1 /* True little endian mode */
# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */
+/* Get/set process seccomp mode */
+#define PR_GET_SECCOMP 21
+#define PR_SET_SECCOMP 22
+
#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/prefetch.h b/include/linux/prefetch.h
index fc86f274147f..1adfe668d031 100644
--- a/include/linux/prefetch.h
+++ b/include/linux/prefetch.h
@@ -27,7 +27,7 @@
prefetch(x) - prefetches the cacheline at "x" for read
prefetchw(x) - prefetches the cacheline at "x" for write
- spin_lock_prefetch(x) - prefectches the spinlock *x for taking
+ spin_lock_prefetch(x) - prefetches the spinlock *x for taking
there is also PREFETCH_STRIDE which is the architecure-prefered
"lookahead" size for prefetching streamed operations.
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 3469f96bc8b2..28e3664fdf1b 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -7,6 +7,8 @@
#include <linux/magic.h>
#include <asm/atomic.h>
+struct completion;
+
/*
* The proc filesystem constants/structures
*/
@@ -56,6 +58,14 @@ struct proc_dir_entry {
gid_t gid;
loff_t size;
const struct inode_operations *proc_iops;
+ /*
+ * NULL ->proc_fops means "PDE is going away RSN" or
+ * "PDE is just created". In either case, e.g. ->read_proc won't be
+ * called because it's too late or too early, respectively.
+ *
+ * If you're allocating ->proc_fops dynamically, save a pointer
+ * somewhere.
+ */
const struct file_operations *proc_fops;
get_info_t *get_info;
struct module *owner;
@@ -66,6 +76,9 @@ struct proc_dir_entry {
atomic_t count; /* use count */
int deleted; /* delete flag */
void *set;
+ int pde_users; /* number of callers into module in progress */
+ spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
+ struct completion *pde_unload_completion;
};
struct kcore_list {
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index eeb1976ef7bf..ae8146abd746 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -110,6 +110,8 @@ static inline void ptrace_unlink(struct task_struct *child)
__ptrace_unlink(child);
}
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data);
+int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data);
#ifndef force_successful_syscall_return
/*
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index dd5a05d03d4f..75e17a05540e 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -262,7 +262,7 @@ int bitmap_active(struct bitmap *bitmap);
char *file_path(struct file *file, char *buf, int count);
void bitmap_print_sb(struct bitmap *bitmap);
-int bitmap_update_sb(struct bitmap *bitmap);
+void bitmap_update_sb(struct bitmap *bitmap);
int bitmap_setallbits(struct bitmap *bitmap);
void bitmap_write_all(struct bitmap *bitmap);
@@ -278,8 +278,8 @@ int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int d
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
void bitmap_close_sync(struct bitmap *bitmap);
-int bitmap_unplug(struct bitmap *bitmap);
-int bitmap_daemon_work(struct bitmap *bitmap);
+void bitmap_unplug(struct bitmap *bitmap);
+void bitmap_daemon_work(struct bitmap *bitmap);
#endif
#endif
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index de72c49747c8..28ac632b42dd 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -51,7 +51,7 @@ struct mdk_rdev_s
sector_t size; /* Device size (in blocks) */
mddev_t *mddev; /* RAID array if running */
- unsigned long last_events; /* IO event timestamp */
+ long last_events; /* IO event timestamp */
struct block_device *bdev; /* block device handle */
diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h
new file mode 100644
index 000000000000..e8c7c21ceb1f
--- /dev/null
+++ b/include/linux/rtc/m48t59.h
@@ -0,0 +1,57 @@
+/*
+ * include/linux/rtc/m48t59.h
+ *
+ * Definitions for the platform data of m48t59 RTC chip driver.
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Mark Zhan <rongkai.zhan@windriver.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_RTC_M48T59_H_
+#define _LINUX_RTC_M48T59_H_
+
+/*
+ * M48T59 Register Offset
+ */
+#define M48T59_YEAR 0x1fff
+#define M48T59_MONTH 0x1ffe
+#define M48T59_MDAY 0x1ffd /* Day of Month */
+#define M48T59_WDAY 0x1ffc /* Day of Week */
+#define M48T59_WDAY_CB 0x20 /* Century Bit */
+#define M48T59_WDAY_CEB 0x10 /* Century Enable Bit */
+#define M48T59_HOUR 0x1ffb
+#define M48T59_MIN 0x1ffa
+#define M48T59_SEC 0x1ff9
+#define M48T59_CNTL 0x1ff8
+#define M48T59_CNTL_READ 0x40
+#define M48T59_CNTL_WRITE 0x80
+#define M48T59_WATCHDOG 0x1ff7
+#define M48T59_INTR 0x1ff6
+#define M48T59_INTR_AFE 0x80 /* Alarm Interrupt Enable */
+#define M48T59_INTR_ABE 0x20
+#define M48T59_ALARM_DATE 0x1ff5
+#define M48T59_ALARM_HOUR 0x1ff4
+#define M48T59_ALARM_MIN 0x1ff3
+#define M48T59_ALARM_SEC 0x1ff2
+#define M48T59_UNUSED 0x1ff1
+#define M48T59_FLAGS 0x1ff0
+#define M48T59_FLAGS_WDT 0x80 /* watchdog timer expired */
+#define M48T59_FLAGS_AF 0x40 /* alarm */
+#define M48T59_FLAGS_BF 0x10 /* low battery */
+
+#define M48T59_NVRAM_SIZE 0x1ff0
+
+struct m48t59_plat_data {
+ /* The method to access M48T59 registers,
+ * NOTE: The 'ofs' should be 0x00~0x1fff
+ */
+ void (*write_byte)(struct device *dev, u32 ofs, u8 val);
+ unsigned char (*read_byte)(struct device *dev, u32 ofs);
+};
+
+#endif /* _LINUX_RTC_M48T59_H_ */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index cfb680585ab8..731edaca8ffd 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -26,6 +26,7 @@
#define CLONE_STOPPED 0x02000000 /* Start in stopped state */
#define CLONE_NEWUTS 0x04000000 /* New utsname group? */
#define CLONE_NEWIPC 0x08000000 /* New ipcs */
+#define CLONE_NEWUSER 0x10000000 /* New user namespace */
/*
* Scheduling policies
@@ -287,6 +288,7 @@ extern signed long schedule_timeout_uninterruptible(signed long timeout);
asmlinkage void schedule(void);
struct nsproxy;
+struct user_namespace;
/* Maximum number of active map areas.. This is a random (large) number */
#define DEFAULT_MAX_MAP_COUNT 65536
@@ -529,6 +531,10 @@ struct signal_struct {
#ifdef CONFIG_TASKSTATS
struct taskstats *stats;
#endif
+#ifdef CONFIG_AUDIT
+ unsigned audit_tty;
+ struct tty_audit_buf *tty_audit_buf;
+#endif
};
/* Context switch must be unlocked if interrupts are to be enabled */
@@ -972,7 +978,8 @@ struct task_struct {
unsigned int rt_priority;
cputime_t utime, stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
- struct timespec start_time;
+ struct timespec start_time; /* monotonic time */
+ struct timespec real_start_time; /* boot based time */
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, maj_flt;
@@ -1403,7 +1410,7 @@ extern struct task_struct *find_task_by_pid_type(int type, int pid);
extern void __set_special_pids(pid_t session, pid_t pgrp);
/* per-UID process charging. */
-extern struct user_struct * alloc_uid(uid_t);
+extern struct user_struct * alloc_uid(struct user_namespace *, uid_t);
static inline struct user_struct *get_uid(struct user_struct *u)
{
atomic_inc(&u->__count);
diff --git a/include/linux/scx200_gpio.h b/include/linux/scx200_gpio.h
index 1a82d30c4b17..d2b058130eb1 100644
--- a/include/linux/scx200_gpio.h
+++ b/include/linux/scx200_gpio.h
@@ -1,5 +1,3 @@
-#include <linux/spinlock.h>
-
u32 scx200_gpio_configure(unsigned index, u32 set, u32 clear);
extern unsigned scx200_gpio_base;
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 3e8b1cf54303..262a8dccfa81 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -4,8 +4,6 @@
#ifdef CONFIG_SECCOMP
-#define NR_SECCOMP_MODES 1
-
#include <linux/thread_info.h>
#include <asm/seccomp.h>
@@ -18,20 +16,23 @@ static inline void secure_computing(int this_syscall)
__secure_computing(this_syscall);
}
-static inline int has_secure_computing(struct thread_info *ti)
-{
- return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
-}
+extern long prctl_get_seccomp(void);
+extern long prctl_set_seccomp(unsigned long);
#else /* CONFIG_SECCOMP */
typedef struct { } seccomp_t;
#define secure_computing(x) do { } while (0)
-/* static inline to preserve typechecking */
-static inline int has_secure_computing(struct thread_info *ti)
+
+static inline long prctl_get_seccomp(void)
+{
+ return -EINVAL;
+}
+
+static inline long prctl_set_seccomp(unsigned long arg2)
{
- return 0;
+ return -EINVAL;
}
#endif /* CONFIG_SECCOMP */
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 33fc8cb8ddfb..deb714314fb1 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -177,11 +177,5 @@ struct serial_icounter_struct {
#ifdef __KERNEL__
#include <linux/compiler.h>
-/* Allow architectures to override entries in serial8250_ports[] at run time: */
-struct uart_port; /* forward declaration */
-extern int early_serial_setup(struct uart_port *port);
-extern int early_serial_console_init(char *options);
-extern int serial8250_start_console(struct uart_port *port, char *options);
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 71310d80c09a..706ee9a4c80c 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,4 +60,8 @@ void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);
void serial8250_resume_port(int line);
+extern int serial8250_find_port(struct uart_port *p);
+extern int serial8250_find_port_for_earlycon(void);
+extern int setup_early_serial8250_console(char *cmdline);
+
#endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 7f2c99d66e9d..9c721cd2c9d6 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -142,6 +142,9 @@
/* Micrel KS8695 */
#define PORT_KS8695 76
+/* Broadcom SB1250, etc. SOC */
+#define PORT_SB1250_DUART 77
+
#ifdef __KERNEL__
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 9a5eac508e5e..ea91abe740da 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -6,7 +6,6 @@
#ifdef __KERNEL__
#include <linux/list.h>
-#include <linux/spinlock.h>
/*
* Real Time signals may be queued.
diff --git a/include/linux/slab.h b/include/linux/slab.h
index cebcd3833c76..0e1d0daef6a2 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -14,8 +14,6 @@
#include <linux/gfp.h>
#include <linux/types.h>
-typedef struct kmem_cache kmem_cache_t __deprecated;
-
/*
* Flags to pass to kmem_cache_create().
* The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
@@ -33,6 +31,19 @@ typedef struct kmem_cache kmem_cache_t __deprecated;
#define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */
/*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+#define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) < \
+ (unsigned long)ZERO_SIZE_PTR)
+
+/*
* struct kmem_cache related prototypes
*/
void __init kmem_cache_init(void);
@@ -44,8 +55,6 @@ struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
void (*)(void *, struct kmem_cache *, unsigned long));
void kmem_cache_destroy(struct kmem_cache *);
int kmem_cache_shrink(struct kmem_cache *);
-void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
-void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
void kmem_cache_free(struct kmem_cache *, void *);
unsigned int kmem_cache_size(struct kmem_cache *);
const char *kmem_cache_name(struct kmem_cache *);
@@ -63,16 +72,6 @@ int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
sizeof(struct __struct), __alignof__(struct __struct),\
(__flags), NULL, NULL)
-#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
-#else
-static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
- gfp_t flags, int node)
-{
- return kmem_cache_alloc(cachep, flags);
-}
-#endif
-
/*
* The largest kmalloc size supported by the slab allocators is
* 32 megabyte (2^25) or the maximum allocatable page order if that is
@@ -91,59 +90,50 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
/*
* Common kmalloc functions provided by all allocators
*/
-void *__kmalloc(size_t, gfp_t);
-void *__kzalloc(size_t, gfp_t);
void * __must_check krealloc(const void *, size_t, gfp_t);
void kfree(const void *);
size_t ksize(const void *);
-/**
- * kcalloc - allocate memory for an array. The memory is set to zero.
- * @n: number of elements.
- * @size: element size.
- * @flags: the type of memory to allocate.
- */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
- if (n != 0 && size > ULONG_MAX / n)
- return NULL;
- return __kzalloc(n * size, flags);
-}
-
/*
* Allocator specific definitions. These are mainly used to establish optimized
- * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by selecting
- * the appropriate general cache at compile time.
+ * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by
+ * selecting the appropriate general cache at compile time.
+ *
+ * Allocators must define at least:
+ *
+ * kmem_cache_alloc()
+ * __kmalloc()
+ * kmalloc()
+ *
+ * Those wishing to support NUMA must also define:
+ *
+ * kmem_cache_alloc_node()
+ * kmalloc_node()
+ *
+ * See each allocator definition file for additional comments and
+ * implementation notes.
*/
-
-#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
#ifdef CONFIG_SLUB
#include <linux/slub_def.h>
+#elif defined(CONFIG_SLOB)
+#include <linux/slob_def.h>
#else
#include <linux/slab_def.h>
-#endif /* !CONFIG_SLUB */
-#else
-
-/*
- * Fallback definitions for an allocator not wanting to provide
- * its own optimized kmalloc definitions (like SLOB).
- */
+#endif
/**
- * kmalloc - allocate memory
- * @size: how many bytes of memory are required.
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
* @flags: the type of memory to allocate.
*
- * kmalloc is the normal method of allocating memory
- * in the kernel.
- *
* The @flags argument may be one of:
*
* %GFP_USER - Allocate memory on behalf of user. May sleep.
*
* %GFP_KERNEL - Allocate normal kernel ram. May sleep.
*
- * %GFP_ATOMIC - Allocation will not sleep.
+ * %GFP_ATOMIC - Allocation will not sleep. May use emergency pools.
* For example, use this inside interrupt handlers.
*
* %GFP_HIGHUSER - Allocate pages from high memory.
@@ -152,18 +142,22 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
*
* %GFP_NOFS - Do not make any fs calls while trying to get memory.
*
+ * %GFP_NOWAIT - Allocation will not sleep.
+ *
+ * %GFP_THISNODE - Allocate node-local memory only.
+ *
+ * %GFP_DMA - Allocation suitable for DMA.
+ * Should only be used for kmalloc() caches. Otherwise, use a
+ * slab created with SLAB_DMA.
+ *
* Also it is possible to set different flags by OR'ing
* in one or more of the following additional @flags:
*
* %__GFP_COLD - Request cache-cold pages instead of
* trying to return cache-warm pages.
*
- * %__GFP_DMA - Request memory from the DMA-capable zone.
- *
* %__GFP_HIGH - This allocation has high priority and may use emergency pools.
*
- * %__GFP_HIGHMEM - Allocated memory may be from highmem.
- *
* %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail
* (think twice before using).
*
@@ -173,24 +167,29 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
* %__GFP_NOWARN - If allocation fails, don't issue any warnings.
*
* %__GFP_REPEAT - If allocation fails initially, try once more before failing.
+ *
+ * There are other flags available as well, but these are not intended
+ * for general use, and so are not documented here. For a full list of
+ * potential flags, always refer to linux/gfp.h.
*/
-static inline void *kmalloc(size_t size, gfp_t flags)
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
{
- return __kmalloc(size, flags);
+ if (n != 0 && size > ULONG_MAX / n)
+ return NULL;
+ return __kmalloc(n * size, flags | __GFP_ZERO);
}
+#if !defined(CONFIG_NUMA) && !defined(CONFIG_SLOB)
/**
- * kzalloc - allocate memory. The memory is set to zero.
+ * kmalloc_node - allocate memory from a specific node
* @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate (see kmalloc).
+ * @flags: the type of memory to allocate (see kcalloc).
+ * @node: node to allocate from.
+ *
+ * kmalloc() for non-local nodes, used to allocate from a specific node
+ * if available. Equivalent to kmalloc() in the non-NUMA single-node
+ * case.
*/
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
- return __kzalloc(size, flags);
-}
-#endif
-
-#ifndef CONFIG_NUMA
static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
return kmalloc(size, flags);
@@ -200,7 +199,15 @@ static inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
{
return __kmalloc(size, flags);
}
-#endif /* !CONFIG_NUMA */
+
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+ gfp_t flags, int node)
+{
+ return kmem_cache_alloc(cachep, flags);
+}
+#endif /* !CONFIG_NUMA && !CONFIG_SLOB */
/*
* kmalloc_track_caller is a special version of kmalloc that records the
@@ -245,6 +252,23 @@ extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
#endif /* DEBUG_SLAB */
+/*
+ * Shortcuts
+ */
+static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
+{
+ return kmem_cache_alloc(k, flags | __GFP_ZERO);
+}
+
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+ return kmalloc(size, flags | __GFP_ZERO);
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SLAB_H */
-
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 8d81a60518e4..32bdc2ffd715 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -25,10 +25,17 @@ struct cache_sizes {
};
extern struct cache_sizes malloc_sizes[];
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
+
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size)) {
int i = 0;
+
+ if (!size)
+ return ZERO_SIZE_PTR;
+
#define CACHE(x) \
if (size <= x) \
goto found; \
@@ -51,39 +58,18 @@ found:
return __kmalloc(size, flags);
}
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kzalloc_that_much(void);
- __you_cannot_kzalloc_that_much();
- }
-found:
-#ifdef CONFIG_ZONE_DMA
- if (flags & GFP_DMA)
- return kmem_cache_zalloc(malloc_sizes[i].cs_dmacachep,
- flags);
-#endif
- return kmem_cache_zalloc(malloc_sizes[i].cs_cachep, flags);
- }
- return __kzalloc(size, flags);
-}
-
#ifdef CONFIG_NUMA
extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
if (__builtin_constant_p(size)) {
int i = 0;
+
+ if (!size)
+ return ZERO_SIZE_PTR;
+
#define CACHE(x) \
if (size <= x) \
goto found; \
diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h
new file mode 100644
index 000000000000..59a3fa476ab9
--- /dev/null
+++ b/include/linux/slob_def.h
@@ -0,0 +1,36 @@
+#ifndef __LINUX_SLOB_DEF_H
+#define __LINUX_SLOB_DEF_H
+
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+
+static inline void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
+{
+ return kmem_cache_alloc_node(cachep, flags, -1);
+}
+
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+ return __kmalloc_node(size, flags, node);
+}
+
+/**
+ * kmalloc - allocate memory
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kcalloc).
+ *
+ * kmalloc is the normal method of allocating memory
+ * in the kernel.
+ */
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+ return __kmalloc_node(size, flags, -1);
+}
+
+static inline void *__kmalloc(size_t size, gfp_t flags)
+{
+ return kmalloc(size, flags);
+}
+
+#endif /* __LINUX_SLOB_DEF_H */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 6207a3d8da71..07f7e4cbcee3 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -16,7 +16,9 @@ struct kmem_cache_node {
unsigned long nr_partial;
atomic_long_t nr_slabs;
struct list_head partial;
+#ifdef CONFIG_SLUB_DEBUG
struct list_head full;
+#endif
};
/*
@@ -44,7 +46,9 @@ struct kmem_cache {
int align; /* Alignment */
const char *name; /* Name (only for display!) */
struct list_head list; /* List of slab caches */
+#ifdef CONFIG_SLUB_DEBUG
struct kobject kobj; /* For sysfs */
+#endif
#ifdef CONFIG_NUMA
int defrag_ratio;
@@ -159,17 +163,8 @@ static inline struct kmem_cache *kmalloc_slab(size_t size)
#define SLUB_DMA 0
#endif
-
-/*
- * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
- *
- * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
- *
- * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
- * Both make kfree a no-op.
- */
-#define ZERO_SIZE_PTR ((void *)16)
-
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *__kmalloc(size_t size, gfp_t flags);
static inline void *kmalloc(size_t size, gfp_t flags)
{
@@ -184,21 +179,9 @@ static inline void *kmalloc(size_t size, gfp_t flags)
return __kmalloc(size, flags);
}
-static inline void *kzalloc(size_t size, gfp_t flags)
-{
- if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
- struct kmem_cache *s = kmalloc_slab(size);
-
- if (!s)
- return ZERO_SIZE_PTR;
-
- return kmem_cache_zalloc(s, flags);
- } else
- return __kzalloc(size, flags);
-}
-
#ifdef CONFIG_NUMA
-extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+void *__kmalloc_node(size_t size, gfp_t flags, int node);
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 613edd2e0d25..259a13c3bd98 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -7,7 +7,6 @@
*/
#include <linux/errno.h>
-#include <asm/system.h>
extern void cpu_idle(void);
@@ -62,11 +61,6 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
* Call a function on all processors
*/
int on_each_cpu(void (*func) (void *info), void *info, int retry, int wait);
-/*
- * Call a function on one processor
- */
-int on_cpu(int cpu, void (*func)(void *info), void *info,
- int retry, int wait);
#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
#define MSG_ALL 0x8001
@@ -102,24 +96,17 @@ static inline int up_smp_call_function(void)
local_irq_enable(); \
0; \
})
-
-static inline int on_cpu(int cpu, void (*func)(void *info), void *info,
- int retry, int wait)
-{
- local_irq_disable();
- func(info);
- local_irq_enable();
- return 0;
-}
-
static inline void smp_send_reschedule(int cpu) { }
#define num_booting_cpus() 1
#define smp_prepare_boot_cpu() do {} while (0)
-static inline int smp_call_function_single(int cpuid, void (*func) (void *info),
- void *info, int retry, int wait)
-{
- return -EBUSY;
-}
+#define smp_call_function_single(cpuid, func, info, retry, wait) \
+({ \
+ WARN_ON(cpuid != 0); \
+ local_irq_disable(); \
+ (func)(info); \
+ local_irq_enable(); \
+ 0; \
+})
#endif /* !SMP */
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index cf715a40d833..58962c51dee1 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -3,7 +3,6 @@
#ifdef CONFIG_LOCK_KERNEL
#include <linux/sched.h>
-#include <linux/spinlock.h>
#define kernel_locked() (current->lock_depth >= 0)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index fe195c97a89d..f852e1afd65a 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -253,6 +253,9 @@ struct ucred {
#define MSG_EOF MSG_FIN
+#define MSG_CMSG_CLOEXEC 0x40000000 /* Set close_on_exit for file
+ descriptor received through
+ SCM_RIGHTS */
#if defined(CONFIG_COMPAT)
#define MSG_CMSG_COMPAT 0x80000000 /* This message needs 32 bit fixups */
#else
diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h
index 34d4b075f7b8..40c7b5d993b9 100644
--- a/include/linux/sonypi.h
+++ b/include/linux/sonypi.h
@@ -153,8 +153,6 @@
#define SONYPI_COMMAND_GETCAMERAROMVERSION 18 /* obsolete */
#define SONYPI_COMMAND_GETCAMERAREVISION 19 /* obsolete */
-int sonypi_camera_command(int command, u8 value);
-
#endif /* __KERNEL__ */
#endif /* _SONYPI_H_ */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 1be5ea059477..302b81d1d117 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -76,6 +76,7 @@ struct spi_device {
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
+#define SPI_3WIRE 0x10 /* SI/SO signals shared */
u8 bits_per_word;
int irq;
void *controller_state;
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index 9dbca629dcfb..b8db32cea1de 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -26,6 +26,7 @@ struct spi_bitbang {
struct list_head queue;
u8 busy;
u8 use_dma;
+ u8 flags; /* extra spi->mode support */
struct spi_master *master;
diff --git a/include/linux/spi/tle62x0.h b/include/linux/spi/tle62x0.h
new file mode 100644
index 000000000000..60b59187e590
--- /dev/null
+++ b/include/linux/spi/tle62x0.h
@@ -0,0 +1,24 @@
+/*
+ * tle62x0.h - platform glue to Infineon TLE62x0 driver chips
+ *
+ * Copyright 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 tle62x0_pdata {
+ unsigned int init_state;
+ unsigned int gpio_count;
+};
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index a946176db638..c376f3b36c89 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -282,6 +282,13 @@ do { \
1 : ({ local_irq_restore(flags); 0; }); \
})
+#define write_trylock_irqsave(lock, flags) \
+({ \
+ local_irq_save(flags); \
+ write_trylock(lock) ? \
+ 1 : ({ local_irq_restore(flags); 0; }); \
+})
+
/*
* Locks two spinlocks l1 and l2.
* l1_first indicates if spinlock l1 should be taken first.
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index bbac101ac372..459c5fc11d51 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -58,6 +58,7 @@ u32 gss_unwrap(
u32 gss_delete_sec_context(
struct gss_ctx **ctx_id);
+u32 gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 service);
u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 129d50f2225c..8531a70da73d 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -212,6 +212,7 @@ struct svc_rqst {
struct svc_pool * rq_pool; /* thread pool */
struct svc_procedure * rq_procinfo; /* procedure info */
struct auth_ops * rq_authop; /* authentication flavour */
+ u32 rq_flavor; /* pseudoflavor */
struct svc_cred rq_cred; /* auth info */
struct sk_buff * rq_skbuff; /* fast recv inet buffer */
struct svc_deferred_req*rq_deferred; /* deferred request we are replaying */
@@ -248,6 +249,7 @@ struct svc_rqst {
*/
/* Catering to nfsd */
struct auth_domain * rq_client; /* RPC peer info */
+ struct auth_domain * rq_gssclient; /* "gss/"-style peer info */
struct svc_cacherep * rq_cacherep; /* cache info */
struct knfsd_fh * rq_reffh; /* Referrence filehandle, used to
* determine what device number
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index de92619b0826..22e1ef8e200e 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -127,6 +127,7 @@ extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
extern int auth_unix_forget_old(struct auth_domain *dom);
extern void svcauth_unix_purge(void);
extern void svcauth_unix_info_release(void *);
+extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
static inline unsigned long hash_str(char *name, int bits)
{
diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
index 5a5db16ab660..417a1def56db 100644
--- a/include/linux/sunrpc/svcauth_gss.h
+++ b/include/linux/sunrpc/svcauth_gss.h
@@ -22,6 +22,7 @@
int gss_svc_init(void);
void gss_svc_shutdown(void);
int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
+u32 svcauth_gss_flavor(struct auth_domain *dom);
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 006868881346..665f85f2a3af 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -188,7 +188,8 @@ extern int rotate_reclaimable_page(struct page *page);
extern void swap_setup(void);
/* linux/mm/vmscan.c */
-extern unsigned long try_to_free_pages(struct zone **, gfp_t);
+extern unsigned long try_to_free_pages(struct zone **zones, int order,
+ gfp_t gfp_mask);
extern unsigned long shrink_all_memory(unsigned long nr_pages);
extern int vm_swappiness;
extern int remove_mapping(struct address_space *mapping, struct page *page);
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index a46104a28f66..dce1ed204972 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -31,7 +31,7 @@
*/
-#define TASKSTATS_VERSION 4
+#define TASKSTATS_VERSION 5
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */
@@ -149,6 +149,9 @@ struct taskstats {
__u64 read_bytes; /* bytes of read I/O */
__u64 write_bytes; /* bytes of write I/O */
__u64 cancelled_write_bytes; /* bytes of cancelled write I/O */
+
+ __u64 nvcsw; /* voluntary_ctxt_switches */
+ __u64 nivcsw; /* nonvoluntary_ctxt_switches */
};
diff --git a/include/linux/time.h b/include/linux/time.h
index dda9be685ab6..ec3b0ced0afe 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -36,7 +36,8 @@ struct timezone {
#define NSEC_PER_SEC 1000000000L
#define FSEC_PER_SEC 1000000000000000L
-static inline int timespec_equal(struct timespec *a, struct timespec *b)
+static inline int timespec_equal(const struct timespec *a,
+ const struct timespec *b)
{
return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
}
@@ -116,6 +117,8 @@ extern int do_setitimer(int which, struct itimerval *value,
extern unsigned int alarm_setitimer(unsigned int seconds);
extern int do_getitimer(int which, struct itimerval *value);
extern void getnstimeofday(struct timespec *tv);
+extern void getboottime(struct timespec *ts);
+extern void monotonic_to_bootbased(struct timespec *ts);
extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
extern int timekeeping_is_continuous(void);
diff --git a/include/linux/timer.h b/include/linux/timer.h
index c661710d3627..78cf899b4409 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -3,7 +3,6 @@
#include <linux/list.h>
#include <linux/ktime.h>
-#include <linux/spinlock.h>
#include <linux/stddef.h>
struct tvec_t_base_s;
@@ -91,16 +90,13 @@ extern unsigned long get_next_timer_interrupt(unsigned long now);
*/
#ifdef CONFIG_TIMER_STATS
+#define TIMER_STATS_FLAG_DEFERRABLE 0x1
+
extern void init_timer_stats(void);
extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
- void *timerf, char * comm);
-
-static inline void timer_stats_account_timer(struct timer_list *timer)
-{
- timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
- timer->function, timer->start_comm);
-}
+ void *timerf, char *comm,
+ unsigned int timer_flag);
extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
void *addr);
@@ -119,10 +115,6 @@ static inline void init_timer_stats(void)
{
}
-static inline void timer_stats_account_timer(struct timer_list *timer)
-{
-}
-
static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
{
}
diff --git a/include/linux/tty.h b/include/linux/tty.h
index bb4576085203..691a1748d9d2 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -178,6 +178,7 @@ struct tty_bufhead {
#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN)
struct device;
+struct signal_struct;
/*
* Where all of the state associated with a tty is kept while the tty
* is open. Since the termios state should be kept even if the tty
@@ -310,6 +311,7 @@ extern void tty_hangup(struct tty_struct * tty);
extern void tty_vhangup(struct tty_struct * tty);
extern void tty_unhangup(struct file *filp);
extern int tty_hung_up_p(struct file * filp);
+extern int is_tty(struct file *filp);
extern void do_SAK(struct tty_struct *tty);
extern void __do_SAK(struct tty_struct *tty);
extern void disassociate_ctty(int priv);
@@ -338,9 +340,46 @@ extern struct tty_struct *get_current_tty(void);
extern struct mutex tty_mutex;
+extern void tty_write_unlock(struct tty_struct *tty);
+extern int tty_write_lock(struct tty_struct *tty, int ndelay);
+#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
+
+
+
/* n_tty.c */
extern struct tty_ldisc tty_ldisc_N_TTY;
+/* tty_audit.c */
+#ifdef CONFIG_AUDIT
+extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+ size_t size);
+extern void tty_audit_exit(void);
+extern void tty_audit_fork(struct signal_struct *sig);
+extern void tty_audit_push(struct tty_struct *tty);
+extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
+extern void tty_audit_opening(void);
+#else
+static inline void tty_audit_add_data(struct tty_struct *tty,
+ unsigned char *data, size_t size)
+{
+}
+static inline void tty_audit_exit(void)
+{
+}
+static inline void tty_audit_fork(struct signal_struct *sig)
+{
+}
+static inline void tty_audit_push(struct tty_struct *tty)
+{
+}
+static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+}
+static inline void tty_audit_opening(void)
+{
+}
+#endif
+
/* tty_ioctl.c */
extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg);
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 9af8bbcd8963..b7fe13883bdb 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -13,10 +13,6 @@
* 2 of the License, or (at your option) any later version.
*/
-
-/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
- library one from sys/uio.h if you have a very old library set */
-
struct iovec
{
void __user *iov_base; /* BSD uses caddr_t (1003.1g requires void *) */
@@ -38,11 +34,6 @@ struct kvec {
#define UIO_FASTIOV 8
#define UIO_MAXIOV 1024
-#if 0
-#define UIO_MAXIOV 16 /* Maximum iovec's in one operation
- 16 matches BSD */
- /* Beg pardon: BSD has 1024 --ANK */
-#endif
/*
* Total number of bytes covered by an iovec.
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
new file mode 100644
index 000000000000..bb320573bb9e
--- /dev/null
+++ b/include/linux/user_namespace.h
@@ -0,0 +1,61 @@
+#ifndef _LINUX_USER_NAMESPACE_H
+#define _LINUX_USER_NAMESPACE_H
+
+#include <linux/kref.h>
+#include <linux/nsproxy.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+
+#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
+#define UIDHASH_SZ (1 << UIDHASH_BITS)
+
+struct user_namespace {
+ struct kref kref;
+ struct list_head uidhash_table[UIDHASH_SZ];
+ struct user_struct *root_user;
+};
+
+extern struct user_namespace init_user_ns;
+
+#ifdef CONFIG_USER_NS
+
+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+{
+ if (ns)
+ kref_get(&ns->kref);
+ return ns;
+}
+
+extern struct user_namespace *copy_user_ns(int flags,
+ struct user_namespace *old_ns);
+extern void free_user_ns(struct kref *kref);
+
+static inline void put_user_ns(struct user_namespace *ns)
+{
+ if (ns)
+ kref_put(&ns->kref, free_user_ns);
+}
+
+#else
+
+static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
+{
+ return &init_user_ns;
+}
+
+static inline struct user_namespace *copy_user_ns(int flags,
+ struct user_namespace *old_ns)
+{
+ if (flags & CLONE_NEWUSER)
+ return ERR_PTR(-EINVAL);
+
+ return NULL;
+}
+
+static inline void put_user_ns(struct user_namespace *ns)
+{
+}
+
+#endif
+
+#endif /* _LINUX_USER_H */
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index f8d3b326e93a..923db99175f2 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -48,26 +48,14 @@ static inline void get_uts_ns(struct uts_namespace *ns)
kref_get(&ns->kref);
}
-#ifdef CONFIG_UTS_NS
-extern struct uts_namespace *copy_utsname(int flags, struct uts_namespace *ns);
+extern struct uts_namespace *copy_utsname(unsigned long flags,
+ struct uts_namespace *ns);
extern void free_uts_ns(struct kref *kref);
static inline void put_uts_ns(struct uts_namespace *ns)
{
kref_put(&ns->kref, free_uts_ns);
}
-#else
-static inline struct uts_namespace *copy_utsname(int flags,
- struct uts_namespace *ns)
-{
- return ns;
-}
-
-static inline void put_uts_ns(struct uts_namespace *ns)
-{
-}
-#endif
-
static inline struct new_utsname *utsname(void)
{
return &current->nsproxy->uts_ns->name;
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 4b7ee83787c1..132b260aef1e 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -65,9 +65,10 @@ extern struct vm_struct *get_vm_area_node(unsigned long size,
unsigned long flags, int node,
gfp_t gfp_mask);
extern struct vm_struct *remove_vm_area(void *addr);
+
extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
struct page ***pages);
-extern void unmap_vm_area(struct vm_struct *area);
+extern void unmap_kernel_range(unsigned long addr, unsigned long size);
/*
* Internals. Dont't use..
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index d9325cf8a134..75370ec0923e 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -25,7 +25,7 @@
#define HIGHMEM_ZONE(xx)
#endif
-#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx)
+#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL HIGHMEM_ZONE(xx) , xx##_MOVABLE
enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
FOR_ALL_ZONES(PGALLOC),
@@ -170,7 +170,8 @@ static inline unsigned long node_page_state(int node,
#ifdef CONFIG_HIGHMEM
zone_page_state(&zones[ZONE_HIGHMEM], item) +
#endif
- zone_page_state(&zones[ZONE_NORMAL], item);
+ zone_page_state(&zones[ZONE_NORMAL], item) +
+ zone_page_state(&zones[ZONE_MOVABLE], item);
}
extern void zone_statistics(struct zonelist *, struct zone *);
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index d961635d0e61..699b7e9864fa 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -75,6 +75,8 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
int vt_waitactive(int vt);
void change_console(struct vc_data *new_vc);
void reset_vc(struct vc_data *vc);
+extern int unbind_con_driver(const struct consw *csw, int first, int last,
+ int deflt);
/*
* vc_screen.c shares this temporary buffer with the console write code so that
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ce0719a2cfeb..ce6badc98f6d 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -148,7 +148,7 @@ extern int keventd_up(void);
extern void init_workqueues(void);
int execute_in_process_context(work_func_t fn, struct execute_work *);
-extern void cancel_work_sync(struct work_struct *work);
+extern int cancel_work_sync(struct work_struct *work);
/*
* Kill off a pending schedule_delayed_work(). Note that the work callback
@@ -166,14 +166,21 @@ static inline int cancel_delayed_work(struct delayed_work *work)
return ret;
}
-extern void cancel_rearming_delayed_work(struct delayed_work *work);
+extern int cancel_delayed_work_sync(struct delayed_work *work);
-/* Obsolete. use cancel_rearming_delayed_work() */
+/* Obsolete. use cancel_delayed_work_sync() */
static inline
void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
struct delayed_work *work)
{
- cancel_rearming_delayed_work(work);
+ cancel_delayed_work_sync(work);
+}
+
+/* Obsolete. use cancel_delayed_work_sync() */
+static inline
+void cancel_rearming_delayed_work(struct delayed_work *work)
+{
+ cancel_delayed_work_sync(work);
}
#endif
diff --git a/include/net/scm.h b/include/net/scm.h
index 5637d5e22d5f..423cb1d5ac25 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -8,7 +8,7 @@
/* Well, we should have at least one descriptor open
* to accept passed FDs 8)
*/
-#define SCM_MAX_FD (OPEN_MAX-1)
+#define SCM_MAX_FD 255
struct scm_fp_list
{
diff --git a/include/video/tgafb.h b/include/video/tgafb.h
index 03d0dbe293a8..7bc5e2c14826 100644
--- a/include/video/tgafb.h
+++ b/include/video/tgafb.h
@@ -216,6 +216,7 @@ struct tga_par {
u32 pll_freq; /* pixclock in mhz */
u32 bits_per_pixel; /* bits per pixel */
u32 sync_on_green; /* set if sync is on green */
+ u32 palette[16];
};
diff --git a/init/Kconfig b/init/Kconfig
index d9d878a3bb46..e2056828dc64 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -120,15 +120,6 @@ config SYSVIPC
section 6.4 of the Linux Programmer's Guide, available from
<http://www.tldp.org/guides.html>.
-config IPC_NS
- bool "IPC Namespaces"
- depends on SYSVIPC
- default n
- help
- Support ipc namespaces. This allows containers, i.e. virtual
- environments, to use ipc namespaces to provide different ipc
- objects for different servers. If unsure, say N.
-
config SYSVIPC_SYSCTL
bool
depends on SYSVIPC
@@ -218,13 +209,14 @@ config TASK_IO_ACCOUNTING
Say N if unsure.
-config UTS_NS
- bool "UTS Namespaces"
+config USER_NS
+ bool "User Namespaces (EXPERIMENTAL)"
default n
+ depends on EXPERIMENTAL
help
- Support uts namespaces. This allows containers, i.e.
- vservers, to use uts namespaces to provide different
- uts info for different servers. If unsure, say N.
+ Support user namespaces. This allows containers, i.e.
+ vservers, to use user namespaces to provide different
+ user info for different servers. If unsure, say N.
config AUDIT
bool "Auditing support"
@@ -554,7 +546,7 @@ config SLUB_DEBUG
choice
prompt "Choose SLAB allocator"
- default SLAB
+ default SLUB
help
This option allows to select a slab allocator.
@@ -576,7 +568,7 @@ config SLUB
and has enhanced diagnostics.
config SLOB
- depends on EMBEDDED && !SPARSEMEM
+ depends on EMBEDDED
bool "SLOB (Simple Allocator)"
help
SLOB replaces the SLAB allocator with a drastically simpler
@@ -602,9 +594,7 @@ config BASE_SMALL
default 0 if BASE_FULL
default 1 if !BASE_FULL
-menu "Loadable module support"
-
-config MODULES
+menuconfig MODULES
bool "Enable loadable module support"
help
Kernel modules are small pieces of compiled code which can
@@ -684,6 +674,5 @@ config STOP_MACHINE
depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU
help
Need stop_machine() primitive.
-endmenu
source "block/Kconfig"
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 46fe407fb03e..4efa1e5385e3 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -25,6 +25,7 @@ int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */
int root_mountflags = MS_RDONLY | MS_SILENT;
char * __initdata root_device_name;
static char __initdata saved_root_name[64];
+static int __initdata root_wait;
dev_t ROOT_DEV;
@@ -216,6 +217,16 @@ static int __init root_dev_setup(char *line)
__setup("root=", root_dev_setup);
+static int __init rootwait_setup(char *str)
+{
+ if (*str)
+ return 0;
+ root_wait = 1;
+ return 1;
+}
+
+__setup("rootwait", rootwait_setup);
+
static char * __initdata root_mount_data;
static int __init root_data_setup(char *str)
{
@@ -438,11 +449,20 @@ void __init prepare_namespace(void)
root_device_name += 5;
}
- is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
-
if (initrd_load())
goto out;
+ /* wait for any asynchronous scanning to complete */
+ if ((ROOT_DEV == 0) && root_wait) {
+ printk(KERN_INFO "Waiting for root device %s...\n",
+ saved_root_name);
+ while (driver_probe_done() != 0 ||
+ (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
+ msleep(100);
+ }
+
+ is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+
if (is_floppy && rd_doload && rd_load_disk(0))
ROOT_DEV = Root_RAM0;
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index b222ce9e1c8b..a6b4c0c08e13 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -56,12 +56,9 @@ static void __init handle_initrd(void)
sys_chroot(".");
pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
- if (pid > 0) {
- while (pid != sys_wait4(-1, NULL, 0, NULL)) {
- try_to_freeze();
+ if (pid > 0)
+ while (pid != sys_wait4(-1, NULL, 0, NULL))
yield();
- }
- }
/* move initrd to rootfs' /old */
sys_fchdir(old_fd);
diff --git a/init/main.c b/init/main.c
index 0eb1c7463fe4..d3bcb3b11620 100644
--- a/init/main.c
+++ b/init/main.c
@@ -132,20 +132,9 @@ static char *static_command_line;
static char *execute_command;
static char *ramdisk_execute_command;
+#ifdef CONFIG_SMP
/* Setup configured maximum number of CPUs to activate */
-static unsigned int max_cpus = NR_CPUS;
-
-/*
- * If set, this is an indication to the drivers that reset the underlying
- * device before going ahead with the initialization otherwise driver might
- * rely on the BIOS and skip the reset operation.
- *
- * This is useful if kernel is booting in an unreliable environment.
- * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
- * skipped and devices will be in unknown state.
- */
-unsigned int reset_devices;
-EXPORT_SYMBOL(reset_devices);
+static unsigned int __initdata max_cpus = NR_CPUS;
/*
* Setup routine for controlling SMP activation
@@ -160,10 +149,10 @@ EXPORT_SYMBOL(reset_devices);
static int __init nosmp(char *str)
{
max_cpus = 0;
- return 1;
+ return 0;
}
-__setup("nosmp", nosmp);
+early_param("nosmp", nosmp);
static int __init maxcpus(char *str)
{
@@ -172,6 +161,21 @@ static int __init maxcpus(char *str)
}
__setup("maxcpus=", maxcpus);
+#else
+#define max_cpus NR_CPUS
+#endif
+
+/*
+ * If set, this is an indication to the drivers that reset the underlying
+ * device before going ahead with the initialization otherwise driver might
+ * rely on the BIOS and skip the reset operation.
+ *
+ * This is useful if kernel is booting in an unreliable environment.
+ * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
+ * skipped and devices will be in unknown state.
+ */
+unsigned int reset_devices;
+EXPORT_SYMBOL(reset_devices);
static int __init set_reset_devices(char *str)
{
@@ -385,6 +389,10 @@ static void __init smp_init(void)
{
unsigned int cpu;
+#ifndef CONFIG_HOTPLUG_CPU
+ cpu_possible_map = cpu_present_map;
+#endif
+
/* FIXME: This should be done in userspace --RR */
for_each_present_cpu(cpu) {
if (num_online_cpus() >= max_cpus)
@@ -453,7 +461,10 @@ static int __init do_early_param(char *param, char *val)
struct obs_kernel_param *p;
for (p = __setup_start; p < __setup_end; p++) {
- if (p->early && strcmp(param, p->str) == 0) {
+ if ((p->early && strcmp(param, p->str) == 0) ||
+ (strcmp(param, "console") == 0 &&
+ strcmp(p->str, "earlycon") == 0)
+ ) {
if (p->setup_func(val) != 0)
printk(KERN_WARNING
"Malformed early option '%s'\n", param);
@@ -526,6 +537,10 @@ asmlinkage void __init start_kernel(void)
setup_arch(&command_line);
setup_command_line(command_line);
unwind_setup();
+#ifndef CONFIG_HOTPLUG_CPU
+ if (max_cpus < 2)
+ cpu_possible_map = cpu_online_map;
+#endif
setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
@@ -725,6 +740,15 @@ static void __init do_basic_setup(void)
do_initcalls();
}
+static int __initdata nosoftlockup;
+
+static int __init nosoftlockup_setup(char *str)
+{
+ nosoftlockup = 1;
+ return 1;
+}
+__setup("nosoftlockup", nosoftlockup_setup);
+
static void __init do_pre_smp_initcalls(void)
{
extern int spawn_ksoftirqd(void);
@@ -734,7 +758,8 @@ static void __init do_pre_smp_initcalls(void)
migration_init();
#endif
spawn_ksoftirqd();
- spawn_softlockup_task();
+ if (!nosoftlockup)
+ spawn_softlockup_task();
}
static void run_init_process(char *init_filename)
diff --git a/ipc/msg.c b/ipc/msg.c
index a388824740e7..a03fcb522fff 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -87,7 +87,7 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
#endif
-static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
{
ns->ids[IPC_MSG_IDS] = ids;
ns->msg_ctlmax = MSGMAX;
@@ -96,7 +96,6 @@ static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *i
ipc_init_ids(ids, ns->msg_ctlmni);
}
-#ifdef CONFIG_IPC_NS
int msg_init_ns(struct ipc_namespace *ns)
{
struct ipc_ids *ids;
@@ -128,7 +127,6 @@ void msg_exit_ns(struct ipc_namespace *ns)
kfree(ns->ids[IPC_MSG_IDS]);
ns->ids[IPC_MSG_IDS] = NULL;
}
-#endif
void __init msg_init(void)
{
@@ -387,7 +385,7 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
{
struct kern_ipc_perm *ipcp;
- struct msq_setbuf setbuf;
+ struct msq_setbuf uninitialized_var(setbuf);
struct msg_queue *msq;
int err, version;
struct ipc_namespace *ns;
@@ -511,7 +509,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
err = audit_ipc_obj(ipcp);
if (err)
goto out_unlock_up;
- if (cmd==IPC_SET) {
+ if (cmd == IPC_SET) {
err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
setbuf.mode);
if (err)
diff --git a/ipc/sem.c b/ipc/sem.c
index 9964b2224c70..b676fef6d208 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -121,7 +121,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
#define sc_semopm sem_ctls[2]
#define sc_semmni sem_ctls[3]
-static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
{
ns->ids[IPC_SEM_IDS] = ids;
ns->sc_semmsl = SEMMSL;
@@ -132,7 +132,6 @@ static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *i
ipc_init_ids(ids, ns->sc_semmni);
}
-#ifdef CONFIG_IPC_NS
int sem_init_ns(struct ipc_namespace *ns)
{
struct ipc_ids *ids;
@@ -164,7 +163,6 @@ void sem_exit_ns(struct ipc_namespace *ns)
kfree(ns->ids[IPC_SEM_IDS]);
ns->ids[IPC_SEM_IDS] = NULL;
}
-#endif
void __init sem_init (void)
{
@@ -858,7 +856,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
{
struct sem_array *sma;
int err;
- struct sem_setbuf setbuf;
+ struct sem_setbuf uninitialized_var(setbuf);
struct kern_ipc_perm *ipcp;
if(cmd == IPC_SET) {
diff --git a/ipc/shm.c b/ipc/shm.c
index 0852f206d895..242c3f66493a 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -77,7 +77,7 @@ static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
#endif
-static void __ipc_init __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
{
ns->ids[IPC_SHM_IDS] = ids;
ns->shm_ctlmax = SHMMAX;
@@ -98,7 +98,6 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
shm_destroy(ns, shp);
}
-#ifdef CONFIG_IPC_NS
int shm_init_ns(struct ipc_namespace *ns)
{
struct ipc_ids *ids;
@@ -130,7 +129,6 @@ void shm_exit_ns(struct ipc_namespace *ns)
kfree(ns->ids[IPC_SHM_IDS]);
ns->ids[IPC_SHM_IDS] = NULL;
}
-#endif
void __init shm_init (void)
{
diff --git a/ipc/util.c b/ipc/util.c
index 7536a7292d48..44e5135aee47 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -50,7 +50,6 @@ struct ipc_namespace init_ipc_ns = {
},
};
-#ifdef CONFIG_IPC_NS
static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
{
int err;
@@ -110,14 +109,6 @@ void free_ipc_ns(struct kref *kref)
shm_exit_ns(ns);
kfree(ns);
}
-#else
-struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
-{
- if (flags & CLONE_NEWIPC)
- return ERR_PTR(-EINVAL);
- return ns;
-}
-#endif
/**
* ipc_init - initialise IPC subsystem
@@ -145,7 +136,7 @@ __initcall(ipc_init);
* array itself.
*/
-void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size)
+void ipc_init_ids(struct ipc_ids* ids, int size)
{
int i;
diff --git a/ipc/util.h b/ipc/util.h
index e3aa2c5c97dc..333e891bcaca 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -41,12 +41,8 @@ struct ipc_ids {
};
struct seq_file;
-#ifdef CONFIG_IPC_NS
-#define __ipc_init
-#else
-#define __ipc_init __init
-#endif
-void __ipc_init ipc_init_ids(struct ipc_ids *ids, int size);
+
+void ipc_init_ids(struct ipc_ids *ids, int size);
#ifdef CONFIG_PROC_FS
void __init ipc_init_proc_interface(const char *path, const char *header,
int ids, int (*show)(struct seq_file *, void *));
diff --git a/kernel/Makefile b/kernel/Makefile
index 642d4277c2ea..2a999836ca18 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,11 +4,12 @@
obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
exit.o itimer.o time.o softirq.o resource.o \
- sysctl.o capability.o ptrace.o timer.o user.o \
+ sysctl.o capability.o ptrace.o timer.o user.o user_namespace.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o extable.o params.o posix-timers.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
- hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o
+ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
+ utsname.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += time/
@@ -48,7 +49,6 @@ obj-$(CONFIG_SECCOMP) += seccomp.o
obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
obj-$(CONFIG_RELAY) += relay.o
obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
-obj-$(CONFIG_UTS_NS) += utsname.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
diff --git a/kernel/audit.c b/kernel/audit.c
index d13276d41410..eb0f9165b401 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -58,6 +58,7 @@
#include <linux/selinux.h>
#include <linux/inotify.h>
#include <linux/freezer.h>
+#include <linux/tty.h>
#include "audit.h"
@@ -391,6 +392,7 @@ static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
+ set_freezable();
while (!kthread_should_stop()) {
skb = skb_dequeue(&audit_skb_queue);
wake_up(&audit_backlog_wait);
@@ -423,6 +425,31 @@ static int kauditd_thread(void *dummy)
return 0;
}
+static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
+{
+ struct task_struct *tsk;
+ int err;
+
+ read_lock(&tasklist_lock);
+ tsk = find_task_by_pid(pid);
+ err = -ESRCH;
+ if (!tsk)
+ goto out;
+ err = 0;
+
+ spin_lock_irq(&tsk->sighand->siglock);
+ if (!tsk->signal->audit_tty)
+ err = -EPERM;
+ spin_unlock_irq(&tsk->sighand->siglock);
+ if (err)
+ goto out;
+
+ tty_audit_push_task(tsk, loginuid);
+out:
+ read_unlock(&tasklist_lock);
+ return err;
+}
+
int audit_send_list(void *_dest)
{
struct audit_netlink_list *dest = _dest;
@@ -511,6 +538,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
case AUDIT_DEL:
case AUDIT_DEL_RULE:
case AUDIT_SIGNAL_INFO:
+ case AUDIT_TTY_GET:
+ case AUDIT_TTY_SET:
if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
err = -EPERM;
break;
@@ -622,6 +651,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
err = audit_filter_user(&NETLINK_CB(skb), msg_type);
if (err == 1) {
err = 0;
+ if (msg_type == AUDIT_USER_TTY) {
+ err = audit_prepare_user_tty(pid, loginuid);
+ if (err)
+ break;
+ }
ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
if (ab) {
audit_log_format(ab,
@@ -638,8 +672,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
" subj=%s", ctx);
kfree(ctx);
}
- audit_log_format(ab, " msg='%.1024s'",
- (char *)data);
+ if (msg_type != AUDIT_USER_TTY)
+ audit_log_format(ab, " msg='%.1024s'",
+ (char *)data);
+ else {
+ int size;
+
+ audit_log_format(ab, " msg=");
+ size = nlmsg_len(nlh);
+ audit_log_n_untrustedstring(ab, size,
+ data);
+ }
audit_set_pid(ab, pid);
audit_log_end(ab);
}
@@ -730,6 +773,45 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
0, 0, sig_data, sizeof(*sig_data) + len);
kfree(sig_data);
break;
+ case AUDIT_TTY_GET: {
+ struct audit_tty_status s;
+ struct task_struct *tsk;
+
+ read_lock(&tasklist_lock);
+ tsk = find_task_by_pid(pid);
+ if (!tsk)
+ err = -ESRCH;
+ else {
+ spin_lock_irq(&tsk->sighand->siglock);
+ s.enabled = tsk->signal->audit_tty != 0;
+ spin_unlock_irq(&tsk->sighand->siglock);
+ }
+ read_unlock(&tasklist_lock);
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,
+ &s, sizeof(s));
+ break;
+ }
+ case AUDIT_TTY_SET: {
+ struct audit_tty_status *s;
+ struct task_struct *tsk;
+
+ if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
+ return -EINVAL;
+ s = data;
+ if (s->enabled != 0 && s->enabled != 1)
+ return -EINVAL;
+ read_lock(&tasklist_lock);
+ tsk = find_task_by_pid(pid);
+ if (!tsk)
+ err = -ESRCH;
+ else {
+ spin_lock_irq(&tsk->sighand->siglock);
+ tsk->signal->audit_tty = s->enabled != 0;
+ spin_unlock_irq(&tsk->sighand->siglock);
+ }
+ read_unlock(&tasklist_lock);
+ break;
+ }
default:
err = -EINVAL;
break;
@@ -1185,7 +1267,7 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
}
/**
- * audit_log_n_unstrustedstring - log a string that may contain random characters
+ * audit_log_n_untrustedstring - log a string that may contain random characters
* @ab: audit_buffer
* @len: lenth of string (not including trailing null)
* @string: string to be logged
@@ -1201,25 +1283,24 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
const char *string)
{
- const unsigned char *p = string;
+ const unsigned char *p;
- while (*p) {
+ for (p = string; p < (const unsigned char *)string + len && *p; p++) {
if (*p == '"' || *p < 0x21 || *p > 0x7f) {
audit_log_hex(ab, string, len);
return string + len + 1;
}
- p++;
}
audit_log_n_string(ab, len, string);
return p + 1;
}
/**
- * audit_log_unstrustedstring - log a string that may contain random characters
+ * audit_log_untrustedstring - log a string that may contain random characters
* @ab: audit_buffer
* @string: string to be logged
*
- * Same as audit_log_n_unstrustedstring(), except that strlen is used to
+ * Same as audit_log_n_untrustedstring(), except that strlen is used to
* determine string length.
*/
const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
diff --git a/kernel/audit.h b/kernel/audit.h
index 815d6f5c04ee..95877435c347 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -115,7 +115,6 @@ extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
extern void audit_send_reply(int pid, int seq, int type,
int done, int multi,
void *payload, int size);
-extern void audit_log_lost(const char *message);
extern void audit_panic(const char *message);
struct audit_netlink_list {
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index ce61f423542c..1bf093dcffe0 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1210,8 +1210,8 @@ static inline int audit_add_rule(struct audit_entry *entry,
struct audit_entry *e;
struct audit_field *inode_f = entry->rule.inode_f;
struct audit_watch *watch = entry->rule.watch;
- struct nameidata *ndp, *ndw;
- int h, err, putnd_needed = 0;
+ struct nameidata *ndp = NULL, *ndw = NULL;
+ int h, err;
#ifdef CONFIG_AUDITSYSCALL
int dont_count = 0;
@@ -1239,7 +1239,6 @@ static inline int audit_add_rule(struct audit_entry *entry,
err = audit_get_nd(watch->path, &ndp, &ndw);
if (err)
goto error;
- putnd_needed = 1;
}
mutex_lock(&audit_filter_mutex);
@@ -1269,14 +1268,11 @@ static inline int audit_add_rule(struct audit_entry *entry,
#endif
mutex_unlock(&audit_filter_mutex);
- if (putnd_needed)
- audit_put_nd(ndp, ndw);
-
+ audit_put_nd(ndp, ndw); /* NULL args OK */
return 0;
error:
- if (putnd_needed)
- audit_put_nd(ndp, ndw);
+ audit_put_nd(ndp, ndw); /* NULL args OK */
if (watch)
audit_put_watch(watch); /* tmp watch, matches initial get */
return err;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e36481ed61b4..b7640a5f382a 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -71,9 +71,6 @@
extern struct list_head audit_filter_list[];
-/* No syscall auditing will take place unless audit_enabled != 0. */
-extern int audit_enabled;
-
/* AUDIT_NAMES is the number of slots we reserve in the audit_context
* for saving names from getname(). */
#define AUDIT_NAMES 20
@@ -2040,7 +2037,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
/**
* audit_core_dumps - record information about processes that end abnormally
- * @sig: signal value
+ * @signr: signal value
*
* If a process ends with a core dump, something fishy is going on and we
* should record the event for investigation.
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index c4d123f74bd3..b4796d850140 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -981,10 +981,10 @@ static int update_nodemask(struct cpuset *cs, char *buf)
mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
if (!mmarray)
goto done;
- write_lock_irq(&tasklist_lock); /* block fork */
+ read_lock(&tasklist_lock); /* block fork */
if (atomic_read(&cs->count) <= ntasks)
break; /* got enough */
- write_unlock_irq(&tasklist_lock); /* try again */
+ read_unlock(&tasklist_lock); /* try again */
kfree(mmarray);
}
@@ -1006,7 +1006,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
continue;
mmarray[n++] = mm;
} while_each_thread(g, p);
- write_unlock_irq(&tasklist_lock);
+ read_unlock(&tasklist_lock);
/*
* Now that we've dropped the tasklist spinlock, we can
diff --git a/kernel/exit.c b/kernel/exit.c
index ca6a11b73023..e8af8d0c2483 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -31,6 +31,7 @@
#include <linux/mempolicy.h>
#include <linux/taskstats_kern.h>
#include <linux/delayacct.h>
+#include <linux/freezer.h>
#include <linux/cpuset.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
@@ -387,6 +388,11 @@ void daemonize(const char *name, ...)
* they would be locked into memory.
*/
exit_mm(current);
+ /*
+ * We don't want to have TIF_FREEZE set if the system-wide hibernation
+ * or suspend transition begins right now.
+ */
+ current->flags |= PF_NOFREEZE;
set_special_pids(1, 1);
proc_clear_tty(current);
@@ -858,6 +864,34 @@ static void exit_notify(struct task_struct *tsk)
release_task(tsk);
}
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static void check_stack_usage(void)
+{
+ static DEFINE_SPINLOCK(low_water_lock);
+ static int lowest_to_date = THREAD_SIZE;
+ unsigned long *n = end_of_stack(current);
+ unsigned long free;
+
+ while (*n == 0)
+ n++;
+ free = (unsigned long)n - (unsigned long)end_of_stack(current);
+
+ if (free >= lowest_to_date)
+ return;
+
+ spin_lock(&low_water_lock);
+ if (free < lowest_to_date) {
+ printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
+ "left\n",
+ current->comm, free);
+ lowest_to_date = free;
+ }
+ spin_unlock(&low_water_lock);
+}
+#else
+static inline void check_stack_usage(void) {}
+#endif
+
fastcall NORET_TYPE void do_exit(long code)
{
struct task_struct *tsk = current;
@@ -937,6 +971,8 @@ fastcall NORET_TYPE void do_exit(long code)
if (unlikely(tsk->compat_robust_list))
compat_exit_robust_list(tsk);
#endif
+ if (group_dead)
+ tty_audit_exit();
if (unlikely(tsk->audit_context))
audit_free(tsk);
@@ -949,6 +985,7 @@ fastcall NORET_TYPE void do_exit(long code)
exit_sem(tsk);
__exit_files(tsk);
__exit_fs(tsk);
+ check_stack_usage();
exit_thread();
cpuset_exit(tsk);
exit_keys(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index da3a155bba0d..ba39bdb2a7b8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -49,6 +49,7 @@
#include <linux/delayacct.h>
#include <linux/taskstats_kern.h>
#include <linux/random.h>
+#include <linux/tty.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -897,6 +898,8 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
}
acct_init_pacct(&sig->pacct);
+ tty_audit_fork(sig);
+
return 0;
}
@@ -920,7 +923,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
{
unsigned long new_flags = p->flags;
- new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE);
+ new_flags &= ~PF_SUPERPRIV;
new_flags |= PF_FORKNOEXEC;
if (!(clone_flags & CLONE_PTRACE))
p->ptrace = 0;
@@ -999,7 +1002,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (atomic_read(&p->user->processes) >=
p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
- p->user != &root_user)
+ p->user != current->nsproxy->user_ns->root_user)
goto bad_fork_free;
}
@@ -1059,6 +1062,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->lock_depth = -1; /* -1 = no lock */
do_posix_clock_monotonic_gettime(&p->start_time);
+ p->real_start_time = p->start_time;
+ monotonic_to_bootbased(&p->real_start_time);
p->security = NULL;
p->io_context = NULL;
p->io_wait = NULL;
@@ -1601,7 +1606,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
err = -EINVAL;
if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
- CLONE_NEWUTS|CLONE_NEWIPC))
+ CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER))
goto bad_unshare_out;
if ((err = unshare_thread(unshare_flags)))
diff --git a/kernel/futex.c b/kernel/futex.c
index 45490bec5831..5c3f45d07c53 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -121,6 +121,24 @@ static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS];
static struct vfsmount *futex_mnt;
/*
+ * Take mm->mmap_sem, when futex is shared
+ */
+static inline void futex_lock_mm(struct rw_semaphore *fshared)
+{
+ if (fshared)
+ down_read(fshared);
+}
+
+/*
+ * Release mm->mmap_sem, when the futex is shared
+ */
+static inline void futex_unlock_mm(struct rw_semaphore *fshared)
+{
+ if (fshared)
+ up_read(fshared);
+}
+
+/*
* We hash on the keys returned from get_futex_key (see below).
*/
static struct futex_hash_bucket *hash_futex(union futex_key *key)
@@ -287,7 +305,18 @@ void drop_futex_key_refs(union futex_key *key)
}
EXPORT_SYMBOL_GPL(drop_futex_key_refs);
-static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
+static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+{
+ u32 curval;
+
+ pagefault_disable();
+ curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+ pagefault_enable();
+
+ return curval;
+}
+
+static int get_futex_value_locked(u32 *dest, u32 __user *from)
{
int ret;
@@ -620,9 +649,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
newval = FUTEX_WAITERS | new_owner->pid;
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
- pagefault_enable();
+ curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
if (curval == -EFAULT)
ret = -EFAULT;
@@ -659,9 +686,7 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
* There is no waiter, so we unlock the futex. The owner died
* bit has not to be preserved here. We are the owner:
*/
- pagefault_disable();
- oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0);
- pagefault_enable();
+ oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
if (oldval == -EFAULT)
return oldval;
@@ -700,8 +725,7 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
union futex_key key;
int ret;
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
ret = get_futex_key(uaddr, fshared, &key);
if (unlikely(ret != 0))
@@ -725,8 +749,7 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
spin_unlock(&hb->lock);
out:
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
return ret;
}
@@ -746,8 +769,7 @@ futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared,
int ret, op_ret, attempt = 0;
retryfull:
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
@@ -793,7 +815,7 @@ retry:
*/
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr2,
- fshared, attempt);
+ fshared, attempt);
if (ret)
goto out;
goto retry;
@@ -803,8 +825,7 @@ retry:
* If we would have faulted, release mmap_sem,
* fault it in and start all over again.
*/
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
ret = get_user(dummy, uaddr2);
if (ret)
@@ -841,8 +862,8 @@ retry:
if (hb1 != hb2)
spin_unlock(&hb2->lock);
out:
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
+
return ret;
}
@@ -861,8 +882,7 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
int ret, drop_count = 0;
retry:
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
@@ -890,8 +910,7 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
* If we would have faulted, release mmap_sem, fault
* it in and start all over again.
*/
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
ret = get_user(curval, uaddr1);
@@ -944,8 +963,7 @@ out_unlock:
drop_futex_key_refs(&key1);
out:
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
return ret;
}
@@ -1113,10 +1131,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
while (!ret) {
newval = (uval & FUTEX_OWNER_DIED) | newtid;
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr,
- uval, newval);
- pagefault_enable();
+ curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
if (curval == -EFAULT)
ret = -EFAULT;
@@ -1134,6 +1149,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
#define ARG3_SHARED 1
static long futex_wait_restart(struct restart_block *restart);
+
static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
u32 val, ktime_t *abs_time)
{
@@ -1148,8 +1164,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
q.pi_state = NULL;
retry:
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
@@ -1186,8 +1201,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
* If we would have faulted, release mmap_sem, fault it in and
* start all over again.
*/
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
ret = get_user(uval, uaddr);
@@ -1206,8 +1220,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
* Now the futex is queued and we have checked the data, we
* don't want to hold mmap_sem while we sleep.
*/
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
/*
* There might have been scheduling since the queue_me(), as we
@@ -1285,8 +1298,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
queue_unlock(&q, hb);
out_release_sem:
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
return ret;
}
@@ -1333,8 +1345,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
q.pi_state = NULL;
retry:
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
@@ -1353,9 +1364,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
*/
newval = current->pid;
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval);
- pagefault_enable();
+ curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
if (unlikely(curval == -EFAULT))
goto uaddr_faulted;
@@ -1398,9 +1407,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
lock_taken = 1;
}
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
- pagefault_enable();
+ curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
if (unlikely(curval == -EFAULT))
goto uaddr_faulted;
@@ -1428,8 +1435,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* exit to complete.
*/
queue_unlock(&q, hb);
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
cond_resched();
goto retry;
@@ -1465,8 +1471,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* Now the futex is queued and we have checked the data, we
* don't want to hold mmap_sem while we sleep.
*/
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
WARN_ON(!q.pi_state);
/*
@@ -1480,8 +1485,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
ret = ret ? 0 : -EWOULDBLOCK;
}
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
spin_lock(q.lock_ptr);
if (!ret) {
@@ -1518,8 +1522,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
/* Unqueue and drop the lock */
unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
return ret != -EINTR ? ret : -ERESTARTNOINTR;
@@ -1527,8 +1530,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
queue_unlock(&q, hb);
out_release_sem:
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
return ret;
uaddr_faulted:
@@ -1550,8 +1552,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
goto retry_unlocked;
}
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
ret = get_user(uval, uaddr);
if (!ret && (uval != -EFAULT))
@@ -1585,8 +1586,7 @@ retry:
/*
* First take all the futex related locks:
*/
- if (fshared)
- down_read(fshared);
+ futex_lock_mm(fshared);
ret = get_futex_key(uaddr, fshared, &key);
if (unlikely(ret != 0))
@@ -1601,11 +1601,9 @@ retry_unlocked:
* again. If it succeeds then we can return without waking
* anyone else up:
*/
- if (!(uval & FUTEX_OWNER_DIED)) {
- pagefault_disable();
- uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
- pagefault_enable();
- }
+ if (!(uval & FUTEX_OWNER_DIED))
+ uval = cmpxchg_futex_value_locked(uaddr, current->pid, 0);
+
if (unlikely(uval == -EFAULT))
goto pi_faulted;
@@ -1647,8 +1645,7 @@ retry_unlocked:
out_unlock:
spin_unlock(&hb->lock);
out:
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
return ret;
@@ -1671,8 +1668,7 @@ pi_faulted:
goto retry_unlocked;
}
- if (fshared)
- up_read(fshared);
+ futex_unlock_mm(fshared);
ret = get_user(uval, uaddr);
if (!ret && (uval != -EFAULT))
@@ -1729,8 +1725,8 @@ static int futex_fd(u32 __user *uaddr, int signal)
if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) {
printk(KERN_WARNING "Process `%s' used FUTEX_FD, which "
- "will be removed from the kernel in June 2007\n",
- current->comm);
+ "will be removed from the kernel in June 2007\n",
+ current->comm);
}
ret = -EINVAL;
@@ -1908,10 +1904,8 @@ retry:
* Wake robust non-PI futexes here. The wakeup of
* PI futexes happens in exit_pi_state():
*/
- if (!pi) {
- if (uval & FUTEX_WAITERS)
+ if (!pi && (uval & FUTEX_WAITERS))
futex_wake(uaddr, &curr->mm->mmap_sem, 1);
- }
}
return 0;
}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 23c03f43e196..72d034258ba1 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1406,7 +1406,7 @@ static void migrate_hrtimers(int cpu)
static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
- long cpu = (long)hcpu;
+ unsigned int cpu = (long)hcpu;
switch (action) {
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index bd9e272d55e9..32b161972fad 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -172,7 +172,17 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
irqreturn_t action_ret)
{
if (unlikely(action_ret != IRQ_HANDLED)) {
- desc->irqs_unhandled++;
+ /*
+ * If we are seeing only the odd spurious IRQ caused by
+ * bus asynchronicity then don't eventually trigger an error,
+ * otherwise the couter becomes a doomsday timer for otherwise
+ * working systems
+ */
+ if (jiffies - desc->last_unhandled > HZ/10)
+ desc->irqs_unhandled = 1;
+ else
+ desc->irqs_unhandled++;
+ desc->last_unhandled = jiffies;
if (unlikely(action_ret != IRQ_NONE))
report_bad_irq(irq, desc, action_ret);
}
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index fed54418626c..474219a41929 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -152,7 +152,7 @@ static unsigned int get_symbol_offset(unsigned long pos)
/* Lookup the address for this symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name)
{
- char namebuf[KSYM_NAME_LEN+1];
+ char namebuf[KSYM_NAME_LEN];
unsigned long i;
unsigned int off;
@@ -248,7 +248,7 @@ const char *kallsyms_lookup(unsigned long addr,
{
const char *msym;
- namebuf[KSYM_NAME_LEN] = 0;
+ namebuf[KSYM_NAME_LEN - 1] = 0;
namebuf[0] = 0;
if (is_ksym_addr(addr)) {
@@ -265,7 +265,7 @@ const char *kallsyms_lookup(unsigned long addr,
/* see if it's in a module */
msym = module_address_lookup(addr, symbolsize, offset, modname);
if (msym)
- return strncpy(namebuf, msym, KSYM_NAME_LEN);
+ return strncpy(namebuf, msym, KSYM_NAME_LEN - 1);
return NULL;
}
@@ -273,7 +273,7 @@ const char *kallsyms_lookup(unsigned long addr,
int lookup_symbol_name(unsigned long addr, char *symname)
{
symname[0] = '\0';
- symname[KSYM_NAME_LEN] = '\0';
+ symname[KSYM_NAME_LEN - 1] = '\0';
if (is_ksym_addr(addr)) {
unsigned long pos;
@@ -291,7 +291,7 @@ int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
unsigned long *offset, char *modname, char *name)
{
name[0] = '\0';
- name[KSYM_NAME_LEN] = '\0';
+ name[KSYM_NAME_LEN - 1] = '\0';
if (is_ksym_addr(addr)) {
unsigned long pos;
@@ -312,18 +312,17 @@ int sprint_symbol(char *buffer, unsigned long address)
char *modname;
const char *name;
unsigned long offset, size;
- char namebuf[KSYM_NAME_LEN+1];
+ char namebuf[KSYM_NAME_LEN];
name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
if (!name)
return sprintf(buffer, "0x%lx", address);
- else {
- if (modname)
- return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
+
+ if (modname)
+ return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
size, modname);
- else
- return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
- }
+ else
+ return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
}
/* Look up a kernel symbol and print it to the kernel messages. */
@@ -343,8 +342,8 @@ struct kallsym_iter
unsigned long value;
unsigned int nameoff; /* If iterating in core kernel symbols */
char type;
- char name[KSYM_NAME_LEN+1];
- char module_name[MODULE_NAME_LEN + 1];
+ char name[KSYM_NAME_LEN];
+ char module_name[MODULE_NAME_LEN];
int exported;
};
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index cee419143fd4..bc41ad0f24f8 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/kfifo.h>
+#include <linux/log2.h>
/**
* kfifo_init - allocates a new FIFO using a preallocated buffer
@@ -41,7 +42,7 @@ struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
struct kfifo *fifo;
/* size must be a power of 2 */
- BUG_ON(size & (size - 1));
+ BUG_ON(!is_power_of_2(size));
fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
if (!fifo)
diff --git a/kernel/kthread.c b/kernel/kthread.c
index bbd51b81a3e8..a404f7ee7395 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -215,7 +215,7 @@ int kthread_stop(struct task_struct *k)
EXPORT_SYMBOL(kthread_stop);
-static __init void kthreadd_setup(void)
+static noinline __init_refok void kthreadd_setup(void)
{
struct task_struct *tsk = current;
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 1a5ff2211d88..edba2ffb43de 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -379,7 +379,7 @@ get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4
static void print_lock_name(struct lock_class *class)
{
- char str[KSYM_NAME_LEN + 1], c1, c2, c3, c4;
+ char str[KSYM_NAME_LEN], c1, c2, c3, c4;
const char *name;
get_usage_chars(class, &c1, &c2, &c3, &c4);
@@ -401,7 +401,7 @@ static void print_lock_name(struct lock_class *class)
static void print_lockdep_cache(struct lockdep_map *lock)
{
const char *name;
- char str[KSYM_NAME_LEN + 1];
+ char str[KSYM_NAME_LEN];
name = lock->name;
if (!name)
diff --git a/kernel/module.c b/kernel/module.c
index 015d60cfd90e..33c04ad51175 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -61,10 +61,8 @@ extern int module_sysfs_initialized;
/* If this is set, the section belongs in the init part of the module */
#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
-/* Protects module list */
-static DEFINE_SPINLOCK(modlist_lock);
-
-/* List of modules, protected by module_mutex AND modlist_lock */
+/* List of modules, protected by module_mutex or preempt_disable
+ * (add/delete uses stop_machine). */
static DEFINE_MUTEX(module_mutex);
static LIST_HEAD(modules);
@@ -760,14 +758,13 @@ static void print_unload_info(struct seq_file *m, struct module *mod)
void __symbol_put(const char *symbol)
{
struct module *owner;
- unsigned long flags;
const unsigned long *crc;
- spin_lock_irqsave(&modlist_lock, flags);
+ preempt_disable();
if (!__find_symbol(symbol, &owner, &crc, 1))
BUG();
module_put(owner);
- spin_unlock_irqrestore(&modlist_lock, flags);
+ preempt_enable();
}
EXPORT_SYMBOL(__symbol_put);
@@ -1228,14 +1225,14 @@ static void free_module(struct module *mod)
void *__symbol_get(const char *symbol)
{
struct module *owner;
- unsigned long value, flags;
+ unsigned long value;
const unsigned long *crc;
- spin_lock_irqsave(&modlist_lock, flags);
+ preempt_disable();
value = __find_symbol(symbol, &owner, &crc, 1);
if (value && !strong_try_module_get(owner))
value = 0;
- spin_unlock_irqrestore(&modlist_lock, flags);
+ preempt_enable();
return (void *)value;
}
@@ -2136,7 +2133,7 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
sym = get_ksymbol(mod, addr, NULL, NULL);
if (!sym)
goto out;
- strlcpy(symname, sym, KSYM_NAME_LEN + 1);
+ strlcpy(symname, sym, KSYM_NAME_LEN);
mutex_unlock(&module_mutex);
return 0;
}
@@ -2161,9 +2158,9 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
if (!sym)
goto out;
if (modname)
- strlcpy(modname, mod->name, MODULE_NAME_LEN + 1);
+ strlcpy(modname, mod->name, MODULE_NAME_LEN);
if (name)
- strlcpy(name, sym, KSYM_NAME_LEN + 1);
+ strlcpy(name, sym, KSYM_NAME_LEN);
mutex_unlock(&module_mutex);
return 0;
}
@@ -2184,8 +2181,8 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
*value = mod->symtab[symnum].st_value;
*type = mod->symtab[symnum].st_info;
strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
- KSYM_NAME_LEN + 1);
- strlcpy(module_name, mod->name, MODULE_NAME_LEN + 1);
+ KSYM_NAME_LEN);
+ strlcpy(module_name, mod->name, MODULE_NAME_LEN);
*exported = is_exported(name, mod);
mutex_unlock(&module_mutex);
return 0;
@@ -2232,26 +2229,13 @@ unsigned long module_kallsyms_lookup_name(const char *name)
/* Called by the /proc file system to return a list of modules. */
static void *m_start(struct seq_file *m, loff_t *pos)
{
- struct list_head *i;
- loff_t n = 0;
-
mutex_lock(&module_mutex);
- list_for_each(i, &modules) {
- if (n++ == *pos)
- break;
- }
- if (i == &modules)
- return NULL;
- return i;
+ return seq_list_start(&modules, *pos);
}
static void *m_next(struct seq_file *m, void *p, loff_t *pos)
{
- struct list_head *i = p;
- (*pos)++;
- if (i->next == &modules)
- return NULL;
- return i->next;
+ return seq_list_next(p, &modules, pos);
}
static void m_stop(struct seq_file *m, void *p)
@@ -2321,11 +2305,10 @@ const struct seq_operations modules_op = {
/* Given an address, look for it in the module exception tables. */
const struct exception_table_entry *search_module_extables(unsigned long addr)
{
- unsigned long flags;
const struct exception_table_entry *e = NULL;
struct module *mod;
- spin_lock_irqsave(&modlist_lock, flags);
+ preempt_disable();
list_for_each_entry(mod, &modules, list) {
if (mod->num_exentries == 0)
continue;
@@ -2336,7 +2319,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
if (e)
break;
}
- spin_unlock_irqrestore(&modlist_lock, flags);
+ preempt_enable();
/* Now, if we found one, we are running inside it now, hence
we cannot unload the module, hence no refcnt needed. */
@@ -2348,25 +2331,24 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
*/
int is_module_address(unsigned long addr)
{
- unsigned long flags;
struct module *mod;
- spin_lock_irqsave(&modlist_lock, flags);
+ preempt_disable();
list_for_each_entry(mod, &modules, list) {
if (within(addr, mod->module_core, mod->core_size)) {
- spin_unlock_irqrestore(&modlist_lock, flags);
+ preempt_enable();
return 1;
}
}
- spin_unlock_irqrestore(&modlist_lock, flags);
+ preempt_enable();
return 0;
}
-/* Is this a valid kernel address? We don't grab the lock: we are oopsing. */
+/* Is this a valid kernel address? */
struct module *__module_text_address(unsigned long addr)
{
struct module *mod;
@@ -2381,11 +2363,10 @@ struct module *__module_text_address(unsigned long addr)
struct module *module_text_address(unsigned long addr)
{
struct module *mod;
- unsigned long flags;
- spin_lock_irqsave(&modlist_lock, flags);
+ preempt_disable();
mod = __module_text_address(addr);
- spin_unlock_irqrestore(&modlist_lock, flags);
+ preempt_enable();
return mod;
}
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 9e83b589f754..10f0bbba382b 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -21,6 +21,8 @@
#include <linux/utsname.h>
#include <linux/pid_namespace.h>
+static struct kmem_cache *nsproxy_cachep;
+
struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
static inline void get_nsproxy(struct nsproxy *ns)
@@ -43,9 +45,11 @@ static inline struct nsproxy *clone_nsproxy(struct nsproxy *orig)
{
struct nsproxy *ns;
- ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
- if (ns)
+ ns = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
+ if (ns) {
+ memcpy(ns, orig, sizeof(struct nsproxy));
atomic_set(&ns->count, 1);
+ }
return ns;
}
@@ -54,33 +58,51 @@ static inline struct nsproxy *clone_nsproxy(struct nsproxy *orig)
* Return the newly created nsproxy. Do not attach this to the task,
* leave it to the caller to do proper locking and attach it to task.
*/
-static struct nsproxy *create_new_namespaces(int flags, struct task_struct *tsk,
- struct fs_struct *new_fs)
+static struct nsproxy *create_new_namespaces(unsigned long flags,
+ struct task_struct *tsk, struct fs_struct *new_fs)
{
struct nsproxy *new_nsp;
+ int err;
new_nsp = clone_nsproxy(tsk->nsproxy);
if (!new_nsp)
return ERR_PTR(-ENOMEM);
new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
- if (IS_ERR(new_nsp->mnt_ns))
+ if (IS_ERR(new_nsp->mnt_ns)) {
+ err = PTR_ERR(new_nsp->mnt_ns);
goto out_ns;
+ }
new_nsp->uts_ns = copy_utsname(flags, tsk->nsproxy->uts_ns);
- if (IS_ERR(new_nsp->uts_ns))
+ if (IS_ERR(new_nsp->uts_ns)) {
+ err = PTR_ERR(new_nsp->uts_ns);
goto out_uts;
+ }
new_nsp->ipc_ns = copy_ipcs(flags, tsk->nsproxy->ipc_ns);
- if (IS_ERR(new_nsp->ipc_ns))
+ if (IS_ERR(new_nsp->ipc_ns)) {
+ err = PTR_ERR(new_nsp->ipc_ns);
goto out_ipc;
+ }
new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
- if (IS_ERR(new_nsp->pid_ns))
+ if (IS_ERR(new_nsp->pid_ns)) {
+ err = PTR_ERR(new_nsp->pid_ns);
goto out_pid;
+ }
+
+ new_nsp->user_ns = copy_user_ns(flags, tsk->nsproxy->user_ns);
+ if (IS_ERR(new_nsp->user_ns)) {
+ err = PTR_ERR(new_nsp->user_ns);
+ goto out_user;
+ }
return new_nsp;
+out_user:
+ if (new_nsp->pid_ns)
+ put_pid_ns(new_nsp->pid_ns);
out_pid:
if (new_nsp->ipc_ns)
put_ipc_ns(new_nsp->ipc_ns);
@@ -91,15 +113,15 @@ out_uts:
if (new_nsp->mnt_ns)
put_mnt_ns(new_nsp->mnt_ns);
out_ns:
- kfree(new_nsp);
- return ERR_PTR(-ENOMEM);
+ kmem_cache_free(nsproxy_cachep, new_nsp);
+ return ERR_PTR(err);
}
/*
* called from clone. This now handles copy for nsproxy and all
* namespaces therein.
*/
-int copy_namespaces(int flags, struct task_struct *tsk)
+int copy_namespaces(unsigned long flags, struct task_struct *tsk)
{
struct nsproxy *old_ns = tsk->nsproxy;
struct nsproxy *new_ns;
@@ -110,7 +132,7 @@ int copy_namespaces(int flags, struct task_struct *tsk)
get_nsproxy(old_ns);
- if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+ if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)))
return 0;
if (!capable(CAP_SYS_ADMIN)) {
@@ -140,7 +162,9 @@ void free_nsproxy(struct nsproxy *ns)
put_ipc_ns(ns->ipc_ns);
if (ns->pid_ns)
put_pid_ns(ns->pid_ns);
- kfree(ns);
+ if (ns->user_ns)
+ put_user_ns(ns->user_ns);
+ kmem_cache_free(nsproxy_cachep, ns);
}
/*
@@ -152,19 +176,10 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
{
int err = 0;
- if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
+ if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+ CLONE_NEWUSER)))
return 0;
-#ifndef CONFIG_IPC_NS
- if (unshare_flags & CLONE_NEWIPC)
- return -EINVAL;
-#endif
-
-#ifndef CONFIG_UTS_NS
- if (unshare_flags & CLONE_NEWUTS)
- return -EINVAL;
-#endif
-
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -174,3 +189,12 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
err = PTR_ERR(*new_nsp);
return err;
}
+
+static int __init nsproxy_cache_init(void)
+{
+ nsproxy_cachep = kmem_cache_create("nsproxy", sizeof(struct nsproxy),
+ 0, SLAB_PANIC, NULL, NULL);
+ return 0;
+}
+
+module_init(nsproxy_cache_init);
diff --git a/kernel/panic.c b/kernel/panic.c
index 623d1828259a..f64f4c1ac11f 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -159,14 +159,15 @@ const char *print_tainted(void)
{
static char buf[20];
if (tainted) {
- snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c",
+ snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c",
tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
tainted & TAINT_BAD_PAGE ? 'B' : ' ',
- tainted & TAINT_USER ? 'U' : ' ');
+ tainted & TAINT_USER ? 'U' : ' ',
+ tainted & TAINT_DIE ? 'D' : ' ');
}
else
snprintf(buf, sizeof(buf), "Not tainted");
diff --git a/kernel/pid.c b/kernel/pid.c
index eb66bd2953ab..c6e3f9ffff87 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -365,7 +365,7 @@ struct pid *find_ge_pid(int nr)
}
EXPORT_SYMBOL_GPL(find_get_pid);
-struct pid_namespace *copy_pid_ns(int flags, struct pid_namespace *old_ns)
+struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
{
BUG_ON(!old_ns);
get_pid_ns(old_ns);
diff --git a/kernel/printk.c b/kernel/printk.c
index 0bbdeac2810c..051d27e36a6c 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -449,13 +449,16 @@ static int printk_time = 1;
#else
static int printk_time = 0;
#endif
-module_param(printk_time, int, S_IRUGO | S_IWUSR);
+module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
static int __init printk_time_setup(char *str)
{
if (*str)
return 0;
printk_time = 1;
+ printk(KERN_NOTICE "The 'time' option is deprecated and "
+ "is scheduled for removal in early 2008\n");
+ printk(KERN_NOTICE "Use 'printk.time=<value>' instead\n");
return 1;
}
@@ -483,6 +486,9 @@ static int have_callable_console(void)
* @fmt: format string
*
* This is printk(). It can be called from any context. We want it to work.
+ * Be aware of the fact that if oops_in_progress is not set, we might try to
+ * wake klogd up which could deadlock on runqueue lock if printk() is called
+ * from scheduler code.
*
* We try to grab the console_sem. If we succeed, it's easy - we log the output and
* call the console drivers. If we fail to get the semaphore we place the output
@@ -654,7 +660,7 @@ static void call_console_drivers(unsigned long start, unsigned long end)
*/
static int __init console_setup(char *str)
{
- char name[sizeof(console_cmdline[0].name)];
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
char *s, *options;
int idx;
@@ -662,27 +668,27 @@ static int __init console_setup(char *str)
* Decode str into name, index, options.
*/
if (str[0] >= '0' && str[0] <= '9') {
- strcpy(name, "ttyS");
- strncpy(name + 4, str, sizeof(name) - 5);
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
} else {
- strncpy(name, str, sizeof(name) - 1);
+ strncpy(buf, str, sizeof(buf) - 1);
}
- name[sizeof(name) - 1] = 0;
+ buf[sizeof(buf) - 1] = 0;
if ((options = strchr(str, ',')) != NULL)
*(options++) = 0;
#ifdef __sparc__
if (!strcmp(str, "ttya"))
- strcpy(name, "ttyS0");
+ strcpy(buf, "ttyS0");
if (!strcmp(str, "ttyb"))
- strcpy(name, "ttyS1");
+ strcpy(buf, "ttyS1");
#endif
- for (s = name; *s; s++)
+ for (s = buf; *s; s++)
if ((*s >= '0' && *s <= '9') || *s == ',')
break;
idx = simple_strtoul(s, NULL, 10);
*s = 0;
- add_preferred_console(name, idx, options);
+ add_preferred_console(buf, idx, options);
return 1;
}
__setup("console=", console_setup);
@@ -709,7 +715,7 @@ int __init add_preferred_console(char *name, int idx, char *options)
* See if this tty is not yet registered, and
* if we have a slot free.
*/
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+ for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
if (strcmp(console_cmdline[i].name, name) == 0 &&
console_cmdline[i].index == idx) {
selected_console = i;
@@ -726,6 +732,25 @@ int __init add_preferred_console(char *name, int idx, char *options)
return 0;
}
+int __init update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+ if (strcmp(console_cmdline[i].name, name) == 0 &&
+ console_cmdline[i].index == idx) {
+ c = &console_cmdline[i];
+ memcpy(c->name, name_new, sizeof(c->name));
+ c->name[sizeof(c->name) - 1] = 0;
+ c->options = options;
+ c->index = idx_new;
+ return i;
+ }
+ /* not found */
+ return -1;
+}
+
#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
/**
* suspend_console - suspend the console subsystem
@@ -942,6 +967,9 @@ void register_console(struct console *console)
if (preferred_console < 0 || bootconsole || !console_drivers)
preferred_console = selected_console;
+ if (console->early_setup)
+ console->early_setup();
+
/*
* See if we want to use this console driver. If we
* didn't select a console we take the first one
@@ -985,12 +1013,15 @@ void register_console(struct console *console)
if (!(console->flags & CON_ENABLED))
return;
- if (bootconsole) {
+ if (bootconsole && (console->flags & CON_CONSDEV)) {
printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n",
bootconsole->name, bootconsole->index,
console->name, console->index);
unregister_console(bootconsole);
console->flags &= ~CON_PRINTBUFFER;
+ } else {
+ printk(KERN_INFO "console [%s%d] enabled\n",
+ console->name, console->index);
}
/*
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index ad7949a589dd..4a1745f1dadf 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -161,6 +161,7 @@ int ptrace_may_attach(struct task_struct *task)
int ptrace_attach(struct task_struct *task)
{
int retval;
+ unsigned long flags;
audit_ptrace(task);
@@ -181,9 +182,7 @@ repeat:
* cpu's that may have task_lock).
*/
task_lock(task);
- local_irq_disable();
- if (!write_trylock(&tasklist_lock)) {
- local_irq_enable();
+ if (!write_trylock_irqsave(&tasklist_lock, flags)) {
task_unlock(task);
do {
cpu_relax();
@@ -211,7 +210,7 @@ repeat:
force_sig_specific(SIGSTOP, task);
bad:
- write_unlock_irq(&tasklist_lock);
+ write_unlock_irqrestore(&tasklist_lock, flags);
task_unlock(task);
out:
return retval;
@@ -491,3 +490,22 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
return ret;
}
#endif /* __ARCH_SYS_PTRACE */
+
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
+{
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
+ if (copied != sizeof(tmp))
+ return -EIO;
+ return put_user(tmp, (unsigned long __user *)data);
+}
+
+int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
+{
+ int copied;
+
+ copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+ return (copied == sizeof(data)) ? 0 : -EIO;
+}
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 55ba82a85a66..ddff33247785 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -40,6 +40,7 @@
#include <linux/moduleparam.h>
#include <linux/percpu.h>
#include <linux/notifier.h>
+#include <linux/freezer.h>
#include <linux/cpu.h>
#include <linux/random.h>
#include <linux/delay.h>
@@ -518,7 +519,6 @@ rcu_torture_writer(void *arg)
VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
set_user_nice(current, 19);
- current->flags |= PF_NOFREEZE;
do {
schedule_timeout_uninterruptible(1);
@@ -558,7 +558,6 @@ rcu_torture_fakewriter(void *arg)
VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
set_user_nice(current, 19);
- current->flags |= PF_NOFREEZE;
do {
schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
@@ -589,7 +588,6 @@ rcu_torture_reader(void *arg)
VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
set_user_nice(current, 19);
- current->flags |= PF_NOFREEZE;
do {
idx = cur_ops->readlock();
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
index da8d6bf46457..5aedbee014df 100644
--- a/kernel/rtmutex-debug.c
+++ b/kernel/rtmutex-debug.c
@@ -29,12 +29,6 @@
#include "rtmutex_common.h"
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
# define TRACE_WARN_ON(x) WARN_ON(x)
# define TRACE_BUG_ON(x) BUG_ON(x)
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 015fc633c96c..e3055ba69159 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -260,6 +260,7 @@ static int test_func(void *data)
int ret;
current->flags |= PF_MUTEX_TESTER;
+ set_freezable();
allow_signal(SIGHUP);
for(;;) {
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 17d28ce20300..8cd9bd2cdb34 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -17,12 +17,6 @@
#include "rtmutex_common.h"
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
/*
* lock->owner state tracking:
*
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index 9c75856e791e..2d3b83593ca3 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -103,7 +103,7 @@ static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock)
{
- return (struct task_struct *)
+ return (struct task_struct *)
((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
}
@@ -120,4 +120,11 @@ extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
struct task_struct *proxy_owner);
extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
struct task_struct *proxy_owner);
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
#endif
diff --git a/kernel/sched.c b/kernel/sched.c
index 3332bbb5d5cf..cb31fb4a1379 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -736,7 +736,9 @@ static void update_curr_load(struct rq *rq, u64 now)
*
* The "10% effect" is relative and cumulative: from _any_ nice level,
* if you go up 1 level, it's -10% CPU usage, if you go down 1 level
- * it's +10% CPU usage.
+ * it's +10% CPU usage. (to achieve that we use a multiplier of 1.25.
+ * If a task goes up by ~10% and another task goes down by ~10% then
+ * the relative distance between them is ~25%.)
*/
static const int prio_to_weight[40] = {
/* -20 */ 88818, 71054, 56843, 45475, 36380, 29104, 23283, 18626, 14901, 11921,
@@ -746,15 +748,22 @@ static const int prio_to_weight[40] = {
/* 10 */ 110, 87, 70, 56, 45, 36, 29, 23, 18, 15,
};
+/*
+ * Inverse (2^32/x) values of the prio_to_weight[] array, precalculated.
+ *
+ * In cases where the weight does not change often, we can use the
+ * precalculated inverse to speed up arithmetics by turning divisions
+ * into multiplications:
+ */
static const u32 prio_to_wmult[40] = {
- 48356, 60446, 75558, 94446, 118058, 147573,
- 184467, 230589, 288233, 360285, 450347,
- 562979, 703746, 879575, 1099582, 1374389,
- 1717986, 2147483, 2684354, 3355443, 4194304,
- 5244160, 6557201, 8196502, 10250518, 12782640,
- 16025997, 19976592, 24970740, 31350126, 39045157,
- 49367440, 61356675, 76695844, 95443717, 119304647,
- 148102320, 186737708, 238609294, 286331153,
+/* -20 */ 48356, 60446, 75558, 94446, 118058,
+/* -15 */ 147573, 184467, 230589, 288233, 360285,
+/* -10 */ 450347, 562979, 703746, 879575, 1099582,
+/* -5 */ 1374389, 1717986, 2147483, 2684354, 3355443,
+/* 0 */ 4194304, 5244160, 6557201, 8196502, 10250518,
+/* 5 */ 12782640, 16025997, 19976592, 24970740, 31350126,
+/* 10 */ 39045157, 49367440, 61356675, 76695844, 95443717,
+/* 15 */ 119304647, 148102320, 186737708, 238609294, 286331153,
};
static inline void
@@ -4903,8 +4912,6 @@ static int migration_thread(void *data)
struct migration_req *req;
struct list_head *head;
- try_to_freeze();
-
spin_lock_irq(&rq->lock);
if (cpu_is_offline(cpu)) {
@@ -5138,7 +5145,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
if (IS_ERR(p))
return NOTIFY_BAD;
- p->flags |= PF_NOFREEZE;
kthread_bind(p, cpu);
/* Must be high prio: stop_machine expects to yield to it. */
rq = task_rq_lock(p, &flags);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index c3391b6020e8..ad64fcb731f2 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
/* #define SECCOMP_DEBUG 1 */
+#define NR_SECCOMP_MODES 1
/*
* Secure computing mode 1 allows only read/write/exit/sigreturn.
@@ -54,3 +55,31 @@ void __secure_computing(int this_syscall)
#endif
do_exit(SIGKILL);
}
+
+long prctl_get_seccomp(void)
+{
+ return current->seccomp.mode;
+}
+
+long prctl_set_seccomp(unsigned long seccomp_mode)
+{
+ long ret;
+
+ /* can set it only once to be even more secure */
+ ret = -EPERM;
+ if (unlikely(current->seccomp.mode))
+ goto out;
+
+ ret = -EINVAL;
+ if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+ current->seccomp.mode = seccomp_mode;
+ set_thread_flag(TIF_SECCOMP);
+#ifdef TIF_NOTSC
+ disable_TSC();
+#endif
+ ret = 0;
+ }
+
+ out:
+ return ret;
+}
diff --git a/kernel/signal.c b/kernel/signal.c
index f9405609774e..39d122753bac 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -718,6 +718,37 @@ out_set:
#define LEGACY_QUEUE(sigptr, sig) \
(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
+int print_fatal_signals;
+
+static void print_fatal_signal(struct pt_regs *regs, int signr)
+{
+ printk("%s/%d: potentially unexpected fatal signal %d.\n",
+ current->comm, current->pid, signr);
+
+#ifdef __i386__
+ printk("code at %08lx: ", regs->eip);
+ {
+ int i;
+ for (i = 0; i < 16; i++) {
+ unsigned char insn;
+
+ __get_user(insn, (unsigned char *)(regs->eip + i));
+ printk("%02x ", insn);
+ }
+ }
+#endif
+ printk("\n");
+ show_regs(regs);
+}
+
+static int __init setup_print_fatal_signals(char *str)
+{
+ get_option (&str, &print_fatal_signals);
+
+ return 1;
+}
+
+__setup("print-fatal-signals=", setup_print_fatal_signals);
static int
specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
@@ -1855,6 +1886,8 @@ relock:
* Anything else is fatal, maybe with a core dump.
*/
current->flags |= PF_SIGNALED;
+ if ((signr != SIGKILL) && print_fatal_signals)
+ print_fatal_signal(regs, signr);
if (sig_kernel_coredump(signr)) {
/*
* If it was able to dump core, this kills all
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 53c5f4a60f2f..0f546ddea43d 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -14,6 +14,7 @@
#include <linux/notifier.h>
#include <linux/percpu.h>
#include <linux/cpu.h>
+#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/rcupdate.h>
#include <linux/smp.h>
@@ -488,8 +489,6 @@ void __init softirq_init(void)
static int ksoftirqd(void * __bind_cpu)
{
- current->flags |= PF_NOFREEZE;
-
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
@@ -614,12 +613,16 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
kthread_bind(per_cpu(ksoftirqd, hotcpu),
any_online_cpu(cpu_online_map));
case CPU_DEAD:
- case CPU_DEAD_FROZEN:
+ case CPU_DEAD_FROZEN: {
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
p = per_cpu(ksoftirqd, hotcpu);
per_cpu(ksoftirqd, hotcpu) = NULL;
+ sched_setscheduler(p, SCHED_FIFO, &param);
kthread_stop(p);
takeover_tasklets(hotcpu);
break;
+ }
#endif /* CONFIG_HOTPLUG_CPU */
}
return NOTIFY_OK;
@@ -657,28 +660,4 @@ int on_each_cpu(void (*func) (void *info), void *info, int retry, int wait)
return ret;
}
EXPORT_SYMBOL(on_each_cpu);
-
-/*
- * Call a function on one processor, which might be the currently executing
- * processor.
- */
-int on_cpu(int cpu, void (*func) (void *info), void *info,
- int retry, int wait)
-{
- int ret;
- int this_cpu;
-
- this_cpu = get_cpu();
- if (this_cpu == cpu) {
- local_irq_disable();
- func(info);
- local_irq_enable();
- ret = 0;
- } else
- ret = smp_call_function_single(cpu, func, info, retry, wait);
- put_cpu();
- return ret;
-}
-EXPORT_SYMBOL(on_cpu);
-
#endif
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 0131e296ffb4..708d4882c0c3 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -10,6 +10,7 @@
#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <linux/module.h>
@@ -116,7 +117,6 @@ static int watchdog(void * __bind_cpu)
struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
sched_setscheduler(current, SCHED_FIFO, &param);
- current->flags |= PF_NOFREEZE;
/* initialize timestamp */
touch_softlockup_watchdog();
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index fcee2a8e6da3..319821ef78af 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -93,10 +93,6 @@ static void stopmachine_set_state(enum stopmachine_state state)
static int stop_machine(void)
{
int i, ret = 0;
- struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
-
- /* One high-prio thread per cpu. We'll do this one. */
- sched_setscheduler(current, SCHED_FIFO, &param);
atomic_set(&stopmachine_thread_ack, 0);
stopmachine_num_threads = 0;
@@ -189,6 +185,10 @@ struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
p = kthread_create(do_stop, &smdata, "kstopmachine");
if (!IS_ERR(p)) {
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
+ /* One high-prio thread per cpu. We'll do this one. */
+ sched_setscheduler(p, SCHED_FIFO, &param);
kthread_bind(p, cpu);
wake_up_process(p);
wait_for_completion(&smdata.done);
diff --git a/kernel/sys.c b/kernel/sys.c
index 872271ccc384..4d141ae3e802 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -31,10 +31,12 @@
#include <linux/cn_proc.h>
#include <linux/getcpu.h>
#include <linux/task_io_accounting_ops.h>
+#include <linux/seccomp.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
#include <linux/kprobes.h>
+#include <linux/user_namespace.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -1078,13 +1080,13 @@ static int set_user(uid_t new_ruid, int dumpclear)
{
struct user_struct *new_user;
- new_user = alloc_uid(new_ruid);
+ new_user = alloc_uid(current->nsproxy->user_ns, new_ruid);
if (!new_user)
return -EAGAIN;
if (atomic_read(&new_user->processes) >=
current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
- new_user != &root_user) {
+ new_user != current->nsproxy->user_ns->root_user) {
free_uid(new_user);
return -EAGAIN;
}
@@ -2241,6 +2243,13 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
error = SET_ENDIAN(current, arg2);
break;
+ case PR_GET_SECCOMP:
+ error = prctl_get_seccomp();
+ break;
+ case PR_SET_SECCOMP:
+ error = prctl_set_seccomp(arg2);
+ break;
+
default:
error = -EINVAL;
break;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 7e11e2c98bf9..b0ec498a18d9 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -14,6 +14,7 @@ asmlinkage long sys_ni_syscall(void)
cond_syscall(sys_nfsservctl);
cond_syscall(sys_quotactl);
+cond_syscall(sys32_quotactl);
cond_syscall(sys_acct);
cond_syscall(sys_lookup_dcookie);
cond_syscall(sys_swapon);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d93e13d93f24..7063ebc6db05 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -29,6 +29,7 @@
#include <linux/utsname.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
+#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
@@ -49,9 +50,6 @@
#include <asm/uaccess.h>
#include <asm/processor.h>
-extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos);
-
#ifdef CONFIG_X86
#include <asm/nmi.h>
#include <asm/stacktrace.h>
@@ -61,6 +59,7 @@ extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
/* External variables not in a header file. */
extern int C_A_D;
+extern int print_fatal_signals;
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern int sysctl_panic_on_oom;
@@ -202,7 +201,10 @@ static ctl_table root_table[] = {
.mode = 0555,
.child = dev_table,
},
-
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
{ .ctl_name = 0 }
};
@@ -340,6 +342,14 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "print-fatal-signals",
+ .data = &print_fatal_signals,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
#ifdef __sparc__
{
.ctl_name = KERN_SPARC_REBOOT,
@@ -814,6 +824,14 @@ static ctl_table vm_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "hugepages_treat_as_movable",
+ .data = &hugepages_treat_as_movable,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &hugetlb_treat_movable_handler,
+ },
#endif
{
.ctl_name = VM_LOWMEM_RESERVE_RATIO,
@@ -958,6 +976,17 @@ static ctl_table vm_table[] = {
.mode = 0644,
.proc_handler = &proc_doulongvec_minmax,
},
+#ifdef CONFIG_NUMA
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "numa_zonelist_order",
+ .data = &numa_zonelist_order,
+ .maxlen = NUMA_ZONELIST_ORDER_LEN,
+ .mode = 0644,
+ .proc_handler = &numa_zonelist_order_handler,
+ .strategy = &sysctl_string,
+ },
+#endif
#endif
#if defined(CONFIG_X86_32) || \
(defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
@@ -972,6 +1001,10 @@ static ctl_table vm_table[] = {
.extra1 = &zero,
},
#endif
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
{ .ctl_name = 0 }
};
@@ -1112,6 +1145,10 @@ static ctl_table fs_table[] = {
.child = binfmt_misc_table,
},
#endif
+/*
+ * NOTE: do not add new entries to this table unless you have read
+ * Documentation/sysctl/ctl_unnumbered.txt
+ */
{ .ctl_name = 0 }
};
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 906cae771585..059431ed67db 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -196,6 +196,8 @@ static int fill_pid(pid_t pid, struct task_struct *tsk,
/* fill in basic acct fields */
stats->version = TASKSTATS_VERSION;
+ stats->nvcsw = tsk->nvcsw;
+ stats->nivcsw = tsk->nivcsw;
bacct_add_tsk(stats, tsk);
/* fill in extended acct fields */
@@ -242,6 +244,8 @@ static int fill_tgid(pid_t tgid, struct task_struct *first,
*/
delayacct_add_tsk(stats, tsk);
+ stats->nvcsw += tsk->nvcsw;
+ stats->nivcsw += tsk->nivcsw;
} while_each_thread(first, tsk);
unlock_task_sighand(first, &flags);
diff --git a/kernel/time.c b/kernel/time.c
index f04791f69408..ffe19149d770 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -57,14 +57,17 @@ EXPORT_SYMBOL(sys_tz);
*/
asmlinkage long sys_time(time_t __user * tloc)
{
- time_t i;
- struct timeval tv;
+ /*
+ * We read xtime.tv_sec atomically - it's updated
+ * atomically by update_wall_time(), so no need to
+ * even read-lock the xtime seqlock:
+ */
+ time_t i = xtime.tv_sec;
- do_gettimeofday(&tv);
- i = tv.tv_sec;
+ smp_rmb(); /* sys_time() results are coherent */
if (tloc) {
- if (put_user(i,tloc))
+ if (put_user(i, tloc))
i = -EFAULT;
}
return i;
@@ -373,12 +376,25 @@ void do_gettimeofday (struct timeval *tv)
tv->tv_sec = sec;
tv->tv_usec = usec;
-}
+ /*
+ * Make sure xtime.tv_sec [returned by sys_time()] always
+ * follows the gettimeofday() result precisely. This
+ * condition is extremely unlikely, it can hit at most
+ * once per second:
+ */
+ if (unlikely(xtime.tv_sec != tv->tv_sec)) {
+ unsigned long flags;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ update_wall_time();
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ }
+}
EXPORT_SYMBOL(do_gettimeofday);
+#else /* CONFIG_TIME_INTERPOLATION */
-#else
#ifndef CONFIG_GENERIC_TIME
/*
* Simulate gettimeofday using do_gettimeofday which only allows a timeval
@@ -394,7 +410,7 @@ void getnstimeofday(struct timespec *tv)
}
EXPORT_SYMBOL_GPL(getnstimeofday);
#endif
-#endif
+#endif /* CONFIG_TIME_INTERPOLATION */
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 76212b2a99de..2ad1c37b8dfe 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -205,47 +205,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
}
/**
- * clockevents_request_device
- */
-struct clock_event_device *clockevents_request_device(unsigned int features,
- cpumask_t cpumask)
-{
- struct clock_event_device *cur, *dev = NULL;
- struct list_head *tmp;
-
- spin_lock(&clockevents_lock);
-
- list_for_each(tmp, &clockevent_devices) {
- cur = list_entry(tmp, struct clock_event_device, list);
-
- if ((cur->features & features) == features &&
- cpus_equal(cpumask, cur->cpumask)) {
- if (!dev || dev->rating < cur->rating)
- dev = cur;
- }
- }
-
- clockevents_exchange_device(NULL, dev);
-
- spin_unlock(&clockevents_lock);
-
- return dev;
-}
-
-/**
- * clockevents_release_device
- */
-void clockevents_release_device(struct clock_event_device *dev)
-{
- spin_lock(&clockevents_lock);
-
- clockevents_exchange_device(dev, NULL);
- clockevents_notify_released();
-
- spin_unlock(&clockevents_lock);
-}
-
-/**
* clockevents_notify - notification about relevant events
*/
void clockevents_notify(unsigned long reason, void *arg)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index cf53bb5814cb..438c6b723ee2 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -13,7 +13,7 @@
#include <linux/timex.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
-
+#include <linux/capability.h>
#include <asm/div64.h>
#include <asm/timex.h>
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 3d1042f82a68..728cedfd3cbd 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -36,9 +36,17 @@ EXPORT_SYMBOL(xtime_lock);
* at zero at system boot time, so wall_to_monotonic will be negative,
* however, we will ALWAYS keep the tv_nsec part positive so we can use
* the usual normalization.
+ *
+ * wall_to_monotonic is moved after resume from suspend for the monotonic
+ * time not to jump. We need to add total_sleep_time to wall_to_monotonic
+ * to get the real boot based time offset.
+ *
+ * - wall_to_monotonic is no longer the boot time, getboottime must be
+ * used instead.
*/
struct timespec xtime __attribute__ ((aligned (16)));
struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+static unsigned long total_sleep_time; /* seconds */
EXPORT_SYMBOL(xtime);
@@ -251,6 +259,7 @@ void __init timekeeping_init(void)
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
+ total_sleep_time = 0;
write_sequnlock_irqrestore(&xtime_lock, flags);
}
@@ -282,6 +291,7 @@ static int timekeeping_resume(struct sys_device *dev)
xtime.tv_sec += sleep_length;
wall_to_monotonic.tv_sec -= sleep_length;
+ total_sleep_time += sleep_length;
}
/* re-base the last cycle value */
clock->cycle_last = clocksource_read(clock);
@@ -476,3 +486,30 @@ void update_wall_time(void)
change_clocksource();
update_vsyscall(&xtime, clock);
}
+
+/**
+ * getboottime - Return the real time of system boot.
+ * @ts: pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ *
+ * This is based on the wall_to_monotonic offset and the total suspend
+ * time. Calls to settimeofday will affect the value returned (which
+ * basically means that however wrong your real time clock is at boot time,
+ * you get the right time here).
+ */
+void getboottime(struct timespec *ts)
+{
+ set_normalized_timespec(ts,
+ - (wall_to_monotonic.tv_sec + total_sleep_time),
+ - wall_to_monotonic.tv_nsec);
+}
+
+/**
+ * monotonic_to_bootbased - Convert the monotonic time to boot based.
+ * @ts: pointer to the timespec to be converted
+ */
+void monotonic_to_bootbased(struct timespec *ts)
+{
+ ts->tv_sec += total_sleep_time;
+}
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 8bbcfb77f7d2..e5edc3a22a08 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -38,7 +38,7 @@ DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases);
static void print_name_offset(struct seq_file *m, void *sym)
{
- char symname[KSYM_NAME_LEN+1];
+ char symname[KSYM_NAME_LEN];
if (lookup_symbol_name((unsigned long)sym, symname) < 0)
SEQ_printf(m, "<%p>", sym);
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 321693724ad7..8ed62fda16c6 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -68,6 +68,7 @@ struct entry {
* Number of timeout events:
*/
unsigned long count;
+ unsigned int timer_flag;
/*
* We save the command-line string to preserve
@@ -231,7 +232,8 @@ static struct entry *tstat_lookup(struct entry *entry, char *comm)
* incremented. Otherwise the timer is registered in a free slot.
*/
void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
- void *timerf, char * comm)
+ void *timerf, char *comm,
+ unsigned int timer_flag)
{
/*
* It doesnt matter which lock we take:
@@ -249,6 +251,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
input.start_func = startf;
input.expire_func = timerf;
input.pid = pid;
+ input.timer_flag = timer_flag;
spin_lock_irqsave(lock, flags);
if (!active)
@@ -266,7 +269,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
static void print_name_offset(struct seq_file *m, unsigned long addr)
{
- char symname[KSYM_NAME_LEN+1];
+ char symname[KSYM_NAME_LEN];
if (lookup_symbol_name(addr, symname) < 0)
seq_printf(m, "<%p>", (void *)addr);
@@ -295,7 +298,7 @@ static int tstats_show(struct seq_file *m, void *v)
period = ktime_to_timespec(time);
ms = period.tv_nsec / 1000000;
- seq_puts(m, "Timer Stats Version: v0.1\n");
+ seq_puts(m, "Timer Stats Version: v0.2\n");
seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
if (atomic_read(&overflow_count))
seq_printf(m, "Overflow: %d entries\n",
@@ -303,8 +306,13 @@ static int tstats_show(struct seq_file *m, void *v)
for (i = 0; i < nr_entries; i++) {
entry = entries + i;
- seq_printf(m, "%4lu, %5d %-16s ",
+ if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
+ seq_printf(m, "%4luD, %5d %-16s ",
entry->count, entry->pid, entry->comm);
+ } else {
+ seq_printf(m, " %4lu, %5d %-16s ",
+ entry->count, entry->pid, entry->comm);
+ }
print_name_offset(m, (unsigned long)entry->start_func);
seq_puts(m, " (");
diff --git a/kernel/timer.c b/kernel/timer.c
index 1a69705c2fb9..b7792fb03387 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -305,6 +305,20 @@ void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
timer->start_pid = current->pid;
}
+
+static void timer_stats_account_timer(struct timer_list *timer)
+{
+ unsigned int flag = 0;
+
+ if (unlikely(tbase_get_deferrable(timer->base)))
+ flag |= TIMER_STATS_FLAG_DEFERRABLE;
+
+ timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+ timer->function, timer->start_comm, flag);
+}
+
+#else
+static void timer_stats_account_timer(struct timer_list *timer) {}
#endif
/**
@@ -1114,6 +1128,7 @@ int do_sysinfo(struct sysinfo *info)
getnstimeofday(&tp);
tp.tv_sec += wall_to_monotonic.tv_sec;
tp.tv_nsec += wall_to_monotonic.tv_nsec;
+ monotonic_to_bootbased(&tp);
if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
tp.tv_sec++;
@@ -1206,7 +1221,8 @@ static int __devinit init_timers_cpu(int cpu)
/*
* The APs use this path later in boot
*/
- base = kmalloc_node(sizeof(*base), GFP_KERNEL,
+ base = kmalloc_node(sizeof(*base),
+ GFP_KERNEL | __GFP_ZERO,
cpu_to_node(cpu));
if (!base)
return -ENOMEM;
@@ -1217,7 +1233,6 @@ static int __devinit init_timers_cpu(int cpu)
kfree(base);
return -ENOMEM;
}
- memset(base, 0, sizeof(*base));
per_cpu(tvec_bases, cpu) = base;
} else {
/*
diff --git a/kernel/user.c b/kernel/user.c
index 4869563080e9..98b82507797a 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -14,20 +14,19 @@
#include <linux/bitops.h>
#include <linux/key.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/user_namespace.h>
/*
* UID task count cache, to get fast user lookup in "alloc_uid"
* when changing user ID's (ie setuid() and friends).
*/
-#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
-#define UIDHASH_SZ (1 << UIDHASH_BITS)
#define UIDHASH_MASK (UIDHASH_SZ - 1)
#define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
-#define uidhashentry(uid) (uidhash_table + __uidhashfn((uid)))
+#define uidhashentry(ns, uid) ((ns)->uidhash_table + __uidhashfn((uid)))
static struct kmem_cache *uid_cachep;
-static struct list_head uidhash_table[UIDHASH_SZ];
/*
* The uidhash_lock is mostly taken from process context, but it is
@@ -94,9 +93,10 @@ struct user_struct *find_user(uid_t uid)
{
struct user_struct *ret;
unsigned long flags;
+ struct user_namespace *ns = current->nsproxy->user_ns;
spin_lock_irqsave(&uidhash_lock, flags);
- ret = uid_hash_find(uid, uidhashentry(uid));
+ ret = uid_hash_find(uid, uidhashentry(ns, uid));
spin_unlock_irqrestore(&uidhash_lock, flags);
return ret;
}
@@ -120,9 +120,9 @@ void free_uid(struct user_struct *up)
}
}
-struct user_struct * alloc_uid(uid_t uid)
+struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
{
- struct list_head *hashent = uidhashentry(uid);
+ struct list_head *hashent = uidhashentry(ns, uid);
struct user_struct *up;
spin_lock_irq(&uidhash_lock);
@@ -211,11 +211,11 @@ static int __init uid_cache_init(void)
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
for(n = 0; n < UIDHASH_SZ; ++n)
- INIT_LIST_HEAD(uidhash_table + n);
+ INIT_LIST_HEAD(init_user_ns.uidhash_table + n);
/* Insert the root user immediately (init already runs as root) */
spin_lock_irq(&uidhash_lock);
- uid_hash_insert(&root_user, uidhashentry(0));
+ uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0));
spin_unlock_irq(&uidhash_lock);
return 0;
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
new file mode 100644
index 000000000000..d055d987850c
--- /dev/null
+++ b/kernel/user_namespace.c
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/nsproxy.h>
+#include <linux/user_namespace.h>
+
+struct user_namespace init_user_ns = {
+ .kref = {
+ .refcount = ATOMIC_INIT(2),
+ },
+ .root_user = &root_user,
+};
+
+EXPORT_SYMBOL_GPL(init_user_ns);
+
+#ifdef CONFIG_USER_NS
+
+/*
+ * Clone a new ns copying an original user ns, setting refcount to 1
+ * @old_ns: namespace to clone
+ * Return NULL on error (failure to kmalloc), new ns otherwise
+ */
+static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
+{
+ struct user_namespace *ns;
+ struct user_struct *new_user;
+ int n;
+
+ ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL);
+ if (!ns)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&ns->kref);
+
+ for (n = 0; n < UIDHASH_SZ; ++n)
+ INIT_LIST_HEAD(ns->uidhash_table + n);
+
+ /* Insert new root user. */
+ ns->root_user = alloc_uid(ns, 0);
+ if (!ns->root_user) {
+ kfree(ns);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Reset current->user with a new one */
+ new_user = alloc_uid(ns, current->uid);
+ if (!new_user) {
+ free_uid(ns->root_user);
+ kfree(ns);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ switch_uid(new_user);
+ return ns;
+}
+
+struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns)
+{
+ struct user_namespace *new_ns;
+
+ BUG_ON(!old_ns);
+ get_user_ns(old_ns);
+
+ if (!(flags & CLONE_NEWUSER))
+ return old_ns;
+
+ new_ns = clone_user_ns(old_ns);
+
+ put_user_ns(old_ns);
+ return new_ns;
+}
+
+void free_user_ns(struct kref *kref)
+{
+ struct user_namespace *ns;
+
+ ns = container_of(kref, struct user_namespace, kref);
+ kfree(ns);
+}
+
+#endif /* CONFIG_USER_NS */
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 160c8c5136bd..9d8180a0f0d8 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -13,6 +13,7 @@
#include <linux/uts.h>
#include <linux/utsname.h>
#include <linux/version.h>
+#include <linux/err.h>
/*
* Clone a new ns copying an original utsname, setting refcount to 1
@@ -24,10 +25,11 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns)
struct uts_namespace *ns;
ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL);
- if (ns) {
- memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
- kref_init(&ns->kref);
- }
+ if (!ns)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
+ kref_init(&ns->kref);
return ns;
}
@@ -37,7 +39,7 @@ static struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns)
* utsname of this process won't be seen by parent, and vice
* versa.
*/
-struct uts_namespace *copy_utsname(int flags, struct uts_namespace *old_ns)
+struct uts_namespace *copy_utsname(unsigned long flags, struct uts_namespace *old_ns)
{
struct uts_namespace *new_ns;
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index f22b9dbd2a9c..c76c06466bfd 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -18,10 +18,7 @@
static void *get_uts(ctl_table *table, int write)
{
char *which = table->data;
-#ifdef CONFIG_UTS_NS
- struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
- which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
-#endif
+
if (!write)
down_read(&uts_sem);
else
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 3bebf73be976..58e5c152a6bb 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -282,8 +282,8 @@ static int worker_thread(void *__cwq)
struct cpu_workqueue_struct *cwq = __cwq;
DEFINE_WAIT(wait);
- if (!cwq->wq->freezeable)
- current->flags |= PF_NOFREEZE;
+ if (cwq->wq->freezeable)
+ set_freezable();
set_user_nice(current, -5);
@@ -382,16 +382,16 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
EXPORT_SYMBOL_GPL(flush_workqueue);
/*
- * Upon a successful return, the caller "owns" WORK_STRUCT_PENDING bit,
+ * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
* so this work can't be re-armed in any way.
*/
static int try_to_grab_pending(struct work_struct *work)
{
struct cpu_workqueue_struct *cwq;
- int ret = 0;
+ int ret = -1;
if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work)))
- return 1;
+ return 0;
/*
* The queueing is in progress, or it is already queued. Try to
@@ -457,10 +457,28 @@ static void wait_on_work(struct work_struct *work)
wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
}
+static int __cancel_work_timer(struct work_struct *work,
+ struct timer_list* timer)
+{
+ int ret;
+
+ do {
+ ret = (timer && likely(del_timer(timer)));
+ if (!ret)
+ ret = try_to_grab_pending(work);
+ wait_on_work(work);
+ } while (unlikely(ret < 0));
+
+ work_clear_pending(work);
+ return ret;
+}
+
/**
* cancel_work_sync - block until a work_struct's callback has terminated
* @work: the work which is to be flushed
*
+ * Returns true if @work was pending.
+ *
* cancel_work_sync() will cancel the work if it is queued. If the work's
* callback appears to be running, cancel_work_sync() will block until it
* has completed.
@@ -476,31 +494,26 @@ static void wait_on_work(struct work_struct *work)
* The caller must ensure that workqueue_struct on which this work was last
* queued can't be destroyed before this function returns.
*/
-void cancel_work_sync(struct work_struct *work)
+int cancel_work_sync(struct work_struct *work)
{
- while (!try_to_grab_pending(work))
- cpu_relax();
- wait_on_work(work);
- work_clear_pending(work);
+ return __cancel_work_timer(work, NULL);
}
EXPORT_SYMBOL_GPL(cancel_work_sync);
/**
- * cancel_rearming_delayed_work - reliably kill off a delayed work.
+ * cancel_delayed_work_sync - reliably kill off a delayed work.
* @dwork: the delayed work struct
*
+ * Returns true if @dwork was pending.
+ *
* It is possible to use this function if @dwork rearms itself via queue_work()
* or queue_delayed_work(). See also the comment for cancel_work_sync().
*/
-void cancel_rearming_delayed_work(struct delayed_work *dwork)
+int cancel_delayed_work_sync(struct delayed_work *dwork)
{
- while (!del_timer(&dwork->timer) &&
- !try_to_grab_pending(&dwork->work))
- cpu_relax();
- wait_on_work(&dwork->work);
- work_clear_pending(&dwork->work);
+ return __cancel_work_timer(&dwork->work, &dwork->timer);
}
-EXPORT_SYMBOL(cancel_rearming_delayed_work);
+EXPORT_SYMBOL(cancel_delayed_work_sync);
static struct workqueue_struct *keventd_wq __read_mostly;
@@ -739,18 +752,17 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
if (cwq->thread == NULL)
return;
+ flush_cpu_workqueue(cwq);
/*
- * If the caller is CPU_DEAD the single flush_cpu_workqueue()
- * is not enough, a concurrent flush_workqueue() can insert a
- * barrier after us.
+ * If the caller is CPU_DEAD and cwq->worklist was not empty,
+ * a concurrent flush_workqueue() can insert a barrier after us.
+ * However, in that case run_workqueue() won't return and check
+ * kthread_should_stop() until it flushes all work_struct's.
* When ->worklist becomes empty it is safe to exit because no
* more work_structs can be queued on this cwq: flush_workqueue
* checks list_empty(), and a "normal" queue_work() can't use
* a dead CPU.
*/
- while (flush_cpu_workqueue(cwq))
- ;
-
kthread_stop(cwq->thread);
cwq->thread = NULL;
}
diff --git a/lib/Kconfig b/lib/Kconfig
index 3eb29d5dc4f5..e5c2c514174a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -41,6 +41,14 @@ config CRC32
kernel tree does. Such modules that use library CRC32 functions
require M here.
+config CRC7
+ tristate "CRC7 functions"
+ help
+ This option is provided for the case where no in-kernel-tree
+ modules require CRC7 functions, but a module built outside
+ the kernel tree does. Such modules that use library CRC7
+ functions require M here.
+
config LIBCRC32C
tristate "CRC32c (Castagnoli, et al) Cyclic Redundancy-Check"
help
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index fab32a286371..640844024ffd 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -152,6 +152,19 @@ config DEBUG_SLAB_LEAK
bool "Memory leak debugging"
depends on DEBUG_SLAB
+config SLUB_DEBUG_ON
+ bool "SLUB debugging on by default"
+ depends on SLUB && SLUB_DEBUG
+ default n
+ help
+ Boot with debugging on by default. SLUB boots by default with
+ the runtime debug capabilities switched off. Enabling this is
+ equivalent to specifying the "slub_debug" parameter on boot.
+ There is no support for more fine grained debug control like
+ possible with slub_debug=xxx. SLUB debugging may be switched
+ off in a kernel built with CONFIG_SLUB_DEBUG_ON by specifying
+ "slub_debug=-".
+
config DEBUG_PREEMPT
bool "Debug preemptible kernel"
depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
diff --git a/lib/Makefile b/lib/Makefile
index d1b366bdf86e..da68b2ca0606 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -21,7 +21,7 @@ CFLAGS_kobject_uevent.o += -DDEBUG
endif
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
-obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
+obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o check_signature.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
@@ -43,6 +43,7 @@ obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
obj-$(CONFIG_CRC16) += crc16.o
obj-$(CONFIG_CRC_ITU_T) += crc-itu-t.o
obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_CRC7) += crc7.o
obj-$(CONFIG_LIBCRC32C) += libcrc32c.o
obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
diff --git a/lib/bug.c b/lib/bug.c
index 014b582c5c4b..530f38f55787 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -38,6 +38,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/bug.h>
+#include <linux/sched.h>
extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
@@ -112,7 +113,7 @@ const struct bug_entry *find_bug(unsigned long bugaddr)
return module_find_bug(bugaddr);
}
-enum bug_trap_type report_bug(unsigned long bugaddr)
+enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
{
const struct bug_entry *bug;
const char *file;
@@ -147,7 +148,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr)
"[verbose debug info unavailable]\n",
(void *)bugaddr);
- dump_stack();
+ show_regs(regs);
return BUG_TRAP_TYPE_WARN;
}
diff --git a/lib/check_signature.c b/lib/check_signature.c
new file mode 100644
index 000000000000..fd6af199247b
--- /dev/null
+++ b/lib/check_signature.c
@@ -0,0 +1,26 @@
+#include <linux/io.h>
+#include <linux/module.h>
+
+/**
+ * check_signature - find BIOS signatures
+ * @io_addr: mmio address to check
+ * @signature: signature block
+ * @length: length of signature
+ *
+ * Perform a signature comparison with the mmio address io_addr. This
+ * address should have been obtained by ioremap.
+ * Returns 1 on a match.
+ */
+
+int check_signature(const volatile void __iomem *io_addr,
+ const unsigned char *signature, int length)
+{
+ while (length--) {
+ if (readb(io_addr) != *signature)
+ return 0;
+ io_addr++;
+ signature++;
+ }
+ return 1;
+}
+EXPORT_SYMBOL(check_signature);
diff --git a/lib/crc7.c b/lib/crc7.c
new file mode 100644
index 000000000000..f1c3a144cec1
--- /dev/null
+++ b/lib/crc7.c
@@ -0,0 +1,68 @@
+/*
+ * crc7.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/crc7.h>
+
+
+/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */
+const u8 crc7_syndrome_table[256] = {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+ 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+ 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+ 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+ 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+ 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+ 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+ 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+ 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+ 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+ 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+ 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+ 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+ 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+ 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+ 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+ 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+ 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+ 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+ 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+ 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+ 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+ 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+ 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+ 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+ 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+ 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+ 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+ 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+ 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+};
+EXPORT_SYMBOL(crc7_syndrome_table);
+
+/**
+ * crc7 - update the CRC7 for the data buffer
+ * @crc: previous CRC7 value
+ * @buffer: data pointer
+ * @len: number of bytes in the buffer
+ * Context: any
+ *
+ * Returns the updated CRC7 value.
+ */
+u8 crc7(u8 crc, const u8 *buffer, size_t len)
+{
+ while (len--)
+ crc = crc7_byte(crc, *buffer++);
+ return crc;
+}
+EXPORT_SYMBOL(crc7);
+
+MODULE_DESCRIPTION("CRC7 calculations");
+MODULE_LICENSE("GPL");
diff --git a/lib/genalloc.c b/lib/genalloc.c
index eb7c2bab9ebf..f6d276db2d58 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -54,11 +54,10 @@ int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size,
int nbytes = sizeof(struct gen_pool_chunk) +
(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
- chunk = kmalloc_node(nbytes, GFP_KERNEL, nid);
+ chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
if (unlikely(chunk == NULL))
return -1;
- memset(chunk, 0, nbytes);
spin_lock_init(&chunk->lock);
chunk->start_addr = addr;
chunk->end_addr = addr + size;
diff --git a/lib/idr.c b/lib/idr.c
index b98f01a2eb94..5ca67b3cfd35 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -391,6 +391,53 @@ void idr_remove(struct idr *idp, int id)
EXPORT_SYMBOL(idr_remove);
/**
+ * idr_remove_all - remove all ids from the given idr tree
+ * @idp: idr handle
+ *
+ * idr_destroy() only frees up unused, cached idp_layers, but this
+ * function will remove all id mappings and leave all idp_layers
+ * unused.
+ *
+ * A typical clean-up sequence for objects stored in an idr tree, will
+ * use idr_for_each() to free all objects, if necessay, then
+ * idr_remove_all() to remove all ids, and idr_destroy() to free
+ * up the cached idr_layers.
+ */
+void idr_remove_all(struct idr *idp)
+{
+ int n, id, max, error = 0;
+ struct idr_layer *p;
+ struct idr_layer *pa[MAX_LEVEL];
+ struct idr_layer **paa = &pa[0];
+
+ n = idp->layers * IDR_BITS;
+ p = idp->top;
+ max = 1 << n;
+
+ id = 0;
+ while (id < max && !error) {
+ while (n > IDR_BITS && p) {
+ n -= IDR_BITS;
+ *paa++ = p;
+ p = p->ary[(id >> n) & IDR_MASK];
+ }
+
+ id += 1 << n;
+ while (n < fls(id)) {
+ if (p) {
+ memset(p, 0, sizeof *p);
+ free_layer(idp, p);
+ }
+ n += IDR_BITS;
+ p = *--paa;
+ }
+ }
+ idp->top = NULL;
+ idp->layers = 0;
+}
+EXPORT_SYMBOL(idr_remove_all);
+
+/**
* idr_destroy - release all cached layers within an idr tree
* idp: idr handle
*/
@@ -437,6 +484,61 @@ void *idr_find(struct idr *idp, int id)
EXPORT_SYMBOL(idr_find);
/**
+ * idr_for_each - iterate through all stored pointers
+ * @idp: idr handle
+ * @fn: function to be called for each pointer
+ * @data: data passed back to callback function
+ *
+ * Iterate over the pointers registered with the given idr. The
+ * callback function will be called for each pointer currently
+ * registered, passing the id, the pointer and the data pointer passed
+ * to this function. It is not safe to modify the idr tree while in
+ * the callback, so functions such as idr_get_new and idr_remove are
+ * not allowed.
+ *
+ * We check the return of @fn each time. If it returns anything other
+ * than 0, we break out and return that value.
+ *
+ * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
+ */
+int idr_for_each(struct idr *idp,
+ int (*fn)(int id, void *p, void *data), void *data)
+{
+ int n, id, max, error = 0;
+ struct idr_layer *p;
+ struct idr_layer *pa[MAX_LEVEL];
+ struct idr_layer **paa = &pa[0];
+
+ n = idp->layers * IDR_BITS;
+ p = idp->top;
+ max = 1 << n;
+
+ id = 0;
+ while (id < max) {
+ while (n > 0 && p) {
+ n -= IDR_BITS;
+ *paa++ = p;
+ p = p->ary[(id >> n) & IDR_MASK];
+ }
+
+ if (p) {
+ error = fn(id, (void *)p, data);
+ if (error)
+ break;
+ }
+
+ id += 1 << n;
+ while (n < fls(id)) {
+ n += IDR_BITS;
+ p = *--paa;
+ }
+ }
+
+ return error;
+}
+EXPORT_SYMBOL(idr_for_each);
+
+/**
* idr_replace - replace pointer for given id
* @idp: idr handle
* @ptr: pointer you want associated with the id
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 850449080e1c..cf22c617baa4 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -3,8 +3,17 @@
*/
#include <linux/percpu_counter.h>
+#include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
#include <linux/module.h>
+#ifdef CONFIG_HOTPLUG_CPU
+static LIST_HEAD(percpu_counters);
+static DEFINE_MUTEX(percpu_counters_lock);
+#endif
+
void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
{
long count;
@@ -36,7 +45,7 @@ s64 percpu_counter_sum(struct percpu_counter *fbc)
spin_lock(&fbc->lock);
ret = fbc->count;
- for_each_possible_cpu(cpu) {
+ for_each_online_cpu(cpu) {
s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
ret += *pcount;
}
@@ -44,3 +53,60 @@ s64 percpu_counter_sum(struct percpu_counter *fbc)
return ret < 0 ? 0 : ret;
}
EXPORT_SYMBOL(percpu_counter_sum);
+
+void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
+{
+ spin_lock_init(&fbc->lock);
+ fbc->count = amount;
+ fbc->counters = alloc_percpu(s32);
+#ifdef CONFIG_HOTPLUG_CPU
+ mutex_lock(&percpu_counters_lock);
+ list_add(&fbc->list, &percpu_counters);
+ mutex_unlock(&percpu_counters_lock);
+#endif
+}
+EXPORT_SYMBOL(percpu_counter_init);
+
+void percpu_counter_destroy(struct percpu_counter *fbc)
+{
+ free_percpu(fbc->counters);
+#ifdef CONFIG_HOTPLUG_CPU
+ mutex_lock(&percpu_counters_lock);
+ list_del(&fbc->list);
+ mutex_unlock(&percpu_counters_lock);
+#endif
+}
+EXPORT_SYMBOL(percpu_counter_destroy);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu;
+ struct percpu_counter *fbc;
+
+ if (action != CPU_DEAD)
+ return NOTIFY_OK;
+
+ cpu = (unsigned long)hcpu;
+ mutex_lock(&percpu_counters_lock);
+ list_for_each_entry(fbc, &percpu_counters, list) {
+ s32 *pcount;
+
+ spin_lock(&fbc->lock);
+ pcount = per_cpu_ptr(fbc->counters, cpu);
+ fbc->count += *pcount;
+ *pcount = 0;
+ spin_unlock(&fbc->lock);
+ }
+ mutex_unlock(&percpu_counters_lock);
+ return NOTIFY_OK;
+}
+
+static int __init percpu_counter_startup(void)
+{
+ hotcpu_notifier(percpu_counter_hotcpu_callback, 0);
+ return 0;
+}
+module_init(percpu_counter_startup);
+#endif
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 017290241261..6b6734df6d2d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -135,6 +135,103 @@ static int skip_atoi(const char **s)
return i;
}
+/* Decimal conversion is by far the most typical, and is used
+ * for /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed
+ * using code from
+ * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
+ * (with permission from the author, Douglas W. Jones). */
+
+/* Formats correctly any integer in [0,99999].
+ * Outputs from one to five digits depending on input.
+ * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
+static char* put_dec_trunc(char *buf, unsigned q)
+{
+ unsigned d3, d2, d1, d0;
+ d1 = (q>>4) & 0xf;
+ d2 = (q>>8) & 0xf;
+ d3 = (q>>12);
+
+ d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+ q = (d0 * 0xcd) >> 11;
+ d0 = d0 - 10*q;
+ *buf++ = d0 + '0'; /* least significant digit */
+ d1 = q + 9*d3 + 5*d2 + d1;
+ if (d1 != 0) {
+ q = (d1 * 0xcd) >> 11;
+ d1 = d1 - 10*q;
+ *buf++ = d1 + '0'; /* next digit */
+
+ d2 = q + 2*d2;
+ if ((d2 != 0) || (d3 != 0)) {
+ q = (d2 * 0xd) >> 7;
+ d2 = d2 - 10*q;
+ *buf++ = d2 + '0'; /* next digit */
+
+ d3 = q + 4*d3;
+ if (d3 != 0) {
+ q = (d3 * 0xcd) >> 11;
+ d3 = d3 - 10*q;
+ *buf++ = d3 + '0'; /* next digit */
+ if (q != 0)
+ *buf++ = q + '0'; /* most sign. digit */
+ }
+ }
+ }
+ return buf;
+}
+/* Same with if's removed. Always emits five digits */
+static char* put_dec_full(char *buf, unsigned q)
+{
+ /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
+ /* but anyway, gcc produces better code with full-sized ints */
+ unsigned d3, d2, d1, d0;
+ d1 = (q>>4) & 0xf;
+ d2 = (q>>8) & 0xf;
+ d3 = (q>>12);
+
+ /* Possible ways to approx. divide by 10 */
+ /* gcc -O2 replaces multiply with shifts and adds */
+ // (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
+ // (x * 0x67) >> 10: 1100111
+ // (x * 0x34) >> 9: 110100 - same
+ // (x * 0x1a) >> 8: 11010 - same
+ // (x * 0x0d) >> 7: 1101 - same, shortest code (on i386)
+
+ d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+ q = (d0 * 0xcd) >> 11;
+ d0 = d0 - 10*q;
+ *buf++ = d0 + '0';
+ d1 = q + 9*d3 + 5*d2 + d1;
+ q = (d1 * 0xcd) >> 11;
+ d1 = d1 - 10*q;
+ *buf++ = d1 + '0';
+
+ d2 = q + 2*d2;
+ q = (d2 * 0xd) >> 7;
+ d2 = d2 - 10*q;
+ *buf++ = d2 + '0';
+
+ d3 = q + 4*d3;
+ q = (d3 * 0xcd) >> 11; /* - shorter code */
+ /* q = (d3 * 0x67) >> 10; - would also work */
+ d3 = d3 - 10*q;
+ *buf++ = d3 + '0';
+ *buf++ = q + '0';
+ return buf;
+}
+/* No inlining helps gcc to use registers better */
+static noinline char* put_dec(char *buf, unsigned long long num)
+{
+ while (1) {
+ unsigned rem;
+ if (num < 100000)
+ return put_dec_trunc(buf, num);
+ rem = do_div(num, 100000);
+ buf = put_dec_full(buf, rem);
+ }
+}
+
#define ZEROPAD 1 /* pad with zero */
#define SIGN 2 /* unsigned/signed long */
#define PLUS 4 /* show plus */
@@ -143,12 +240,14 @@ static int skip_atoi(const char **s)
#define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
+static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
{
- char c,sign,tmp[66];
+ char sign,tmp[66];
const char *digits;
- static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ /* we are called with base 8, 10 or 16, only, thus don't need "g..." */
+ static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */
+ static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+ int need_pfx = ((type & SPECIAL) && base != 10);
int i;
digits = (type & LARGE) ? large_digits : small_digits;
@@ -156,7 +255,6 @@ static char * number(char * buf, char * end, unsigned long long num, int base, i
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return NULL;
- c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
if ((signed long long) num < 0) {
@@ -171,64 +269,85 @@ static char * number(char * buf, char * end, unsigned long long num, int base, i
size--;
}
}
- if (type & SPECIAL) {
+ if (need_pfx) {
+ size--;
if (base == 16)
- size -= 2;
- else if (base == 8)
size--;
}
+
+ /* generate full string in tmp[], in reverse order */
i = 0;
if (num == 0)
- tmp[i++]='0';
- else while (num != 0)
+ tmp[i++] = '0';
+ /* Generic code, for any base:
+ else do {
tmp[i++] = digits[do_div(num,base)];
+ } while (num != 0);
+ */
+ else if (base != 10) { /* 8 or 16 */
+ int mask = base - 1;
+ int shift = 3;
+ if (base == 16) shift = 4;
+ do {
+ tmp[i++] = digits[((unsigned char)num) & mask];
+ num >>= shift;
+ } while (num);
+ } else { /* base 10 */
+ i = put_dec(tmp, num) - tmp;
+ }
+
+ /* printing 100 using %2d gives "100", not "00" */
if (i > precision)
precision = i;
+ /* leading space padding */
size -= precision;
- if (!(type&(ZEROPAD+LEFT))) {
- while(size-->0) {
+ if (!(type & (ZEROPAD+LEFT))) {
+ while(--size >= 0) {
if (buf < end)
*buf = ' ';
++buf;
}
}
+ /* sign */
if (sign) {
if (buf < end)
*buf = sign;
++buf;
}
- if (type & SPECIAL) {
- if (base==8) {
- if (buf < end)
- *buf = '0';
- ++buf;
- } else if (base==16) {
- if (buf < end)
- *buf = '0';
- ++buf;
+ /* "0x" / "0" prefix */
+ if (need_pfx) {
+ if (buf < end)
+ *buf = '0';
+ ++buf;
+ if (base == 16) {
if (buf < end)
- *buf = digits[33];
+ *buf = digits[16]; /* for arbitrary base: digits[33]; */
++buf;
}
}
+ /* zero or space padding */
if (!(type & LEFT)) {
- while (size-- > 0) {
+ char c = (type & ZEROPAD) ? '0' : ' ';
+ while (--size >= 0) {
if (buf < end)
*buf = c;
++buf;
}
}
- while (i < precision--) {
+ /* hmm even more zero padding? */
+ while (i <= --precision) {
if (buf < end)
*buf = '0';
++buf;
}
- while (i-- > 0) {
+ /* actual digits of result */
+ while (--i >= 0) {
if (buf < end)
*buf = tmp[i];
++buf;
}
- while (size-- > 0) {
+ /* trailing space padding */
+ while (--size >= 0) {
if (buf < end)
*buf = ' ';
++buf;
@@ -276,7 +395,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
used for unknown buffer sizes. */
if (unlikely((int) size < 0)) {
/* There can be only one.. */
- static int warn = 1;
+ static char warn = 1;
WARN_ON(warn);
warn = 0;
return 0;
diff --git a/mm/Kconfig b/mm/Kconfig
index 8ac412b45f18..86187221e78f 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -117,7 +117,7 @@ config MEMORY_HOTPLUG
bool "Allow for memory hot-add"
depends on SPARSEMEM || X86_64_ACPI_NUMA
depends on HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG
- depends on (IA64 || X86 || PPC64)
+ depends on (IA64 || X86 || PPC64 || SUPERH)
comment "Memory hotplug is currently incompatible with Software Suspend"
depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
@@ -163,8 +163,16 @@ config ZONE_DMA_FLAG
default "0" if !ZONE_DMA
default "1"
+config BOUNCE
+ def_bool y
+ depends on BLOCK && MMU && (ZONE_DMA || HIGHMEM)
+
config NR_QUICK
int
depends on QUICKLIST
default "2" if (SUPERH && !SUPERH64)
default "1"
+
+config VIRT_TO_BUS
+ def_bool y
+ depends on !ARCH_NO_VIRT_TO_BUS
diff --git a/mm/Makefile b/mm/Makefile
index a9148ea329aa..245e33ab00c4 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -13,9 +13,7 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
$(mmu-y)
-ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy)
-obj-y += bounce.o
-endif
+obj-$(CONFIG_BOUNCE) += bounce.o
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
obj-$(CONFIG_NUMA) += mempolicy.o
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
index b2486cf887a0..00b02623f008 100644
--- a/mm/allocpercpu.c
+++ b/mm/allocpercpu.c
@@ -53,12 +53,9 @@ void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
int node = cpu_to_node(cpu);
BUG_ON(pdata->ptrs[cpu]);
- if (node_online(node)) {
- /* FIXME: kzalloc_node(size, gfp, node) */
- pdata->ptrs[cpu] = kmalloc_node(size, gfp, node);
- if (pdata->ptrs[cpu])
- memset(pdata->ptrs[cpu], 0, size);
- } else
+ if (node_online(node))
+ pdata->ptrs[cpu] = kmalloc_node(size, gfp|__GFP_ZERO, node);
+ else
pdata->ptrs[cpu] = kzalloc(size, gfp);
return pdata->ptrs[cpu];
}
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e5de3781d3fe..f50a2811f9dc 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -55,22 +55,6 @@ long congestion_wait(int rw, long timeout)
}
EXPORT_SYMBOL(congestion_wait);
-long congestion_wait_interruptible(int rw, long timeout)
-{
- long ret;
- DEFINE_WAIT(wait);
- wait_queue_head_t *wqh = &congestion_wqh[rw];
-
- prepare_to_wait(wqh, &wait, TASK_INTERRUPTIBLE);
- if (signal_pending(current))
- ret = -ERESTARTSYS;
- else
- ret = io_schedule_timeout(timeout);
- finish_wait(wqh, &wait);
- return ret;
-}
-EXPORT_SYMBOL(congestion_wait_interruptible);
-
/**
* congestion_end - wake up sleepers on a congested backing_dev_info
* @rw: READ or WRITE
diff --git a/mm/filemap.c b/mm/filemap.c
index c6ebd9f912ab..5d5449f3d41c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -120,6 +120,7 @@ void __remove_from_page_cache(struct page *page)
page->mapping = NULL;
mapping->nrpages--;
__dec_zone_page_state(page, NR_FILE_PAGES);
+ BUG_ON(page_mapped(page));
}
void remove_from_page_cache(struct page *page)
@@ -866,13 +867,11 @@ void do_generic_mapping_read(struct address_space *mapping,
{
struct inode *inode = mapping->host;
unsigned long index;
- unsigned long end_index;
unsigned long offset;
unsigned long last_index;
unsigned long next_index;
unsigned long prev_index;
unsigned int prev_offset;
- loff_t isize;
struct page *cached_page;
int error;
struct file_ra_state ra = *_ra;
@@ -885,27 +884,12 @@ void do_generic_mapping_read(struct address_space *mapping,
last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
offset = *ppos & ~PAGE_CACHE_MASK;
- isize = i_size_read(inode);
- if (!isize)
- goto out;
-
- end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
for (;;) {
struct page *page;
+ unsigned long end_index;
+ loff_t isize;
unsigned long nr, ret;
- /* nr is the maximum number of bytes to copy from this page */
- nr = PAGE_CACHE_SIZE;
- if (index >= end_index) {
- if (index > end_index)
- goto out;
- nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
- if (nr <= offset) {
- goto out;
- }
- }
- nr = nr - offset;
-
cond_resched();
if (index == next_index)
next_index = page_cache_readahead(mapping, &ra, filp,
@@ -920,6 +904,32 @@ find_page:
if (!PageUptodate(page))
goto page_not_up_to_date;
page_ok:
+ /*
+ * i_size must be checked after we know the page is Uptodate.
+ *
+ * Checking i_size after the check allows us to calculate
+ * the correct value for "nr", which means the zero-filled
+ * part of the page is not copied back to userspace (unless
+ * another truncate extends the file - this is desired though).
+ */
+
+ isize = i_size_read(inode);
+ end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+ if (unlikely(!isize || index > end_index)) {
+ page_cache_release(page);
+ goto out;
+ }
+
+ /* nr is the maximum number of bytes to copy from this page */
+ nr = PAGE_CACHE_SIZE;
+ if (index == end_index) {
+ nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+ if (nr <= offset) {
+ page_cache_release(page);
+ goto out;
+ }
+ }
+ nr = nr - offset;
/* If users can be writing to this page using arbitrary
* virtual addresses, take care about potential aliasing
@@ -1006,31 +1016,6 @@ readpage:
unlock_page(page);
}
- /*
- * i_size must be checked after we have done ->readpage.
- *
- * Checking i_size after the readpage allows us to calculate
- * the correct value for "nr", which means the zero-filled
- * part of the page is not copied back to userspace (unless
- * another truncate extends the file - this is desired though).
- */
- isize = i_size_read(inode);
- end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
- if (unlikely(!isize || index > end_index)) {
- page_cache_release(page);
- goto out;
- }
-
- /* nr is the maximum number of bytes to copy from this page */
- nr = PAGE_CACHE_SIZE;
- if (index == end_index) {
- nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
- if (nr <= offset) {
- page_cache_release(page);
- goto out;
- }
- }
- nr = nr - offset;
goto page_ok;
readpage_error:
@@ -1218,6 +1203,8 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
retval = retval ?: desc.error;
break;
}
+ if (desc.count > 0)
+ break;
}
}
out:
@@ -1964,7 +1951,6 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
if (unlikely(*pos + *count > MAX_NON_LFS &&
!(file->f_flags & O_LARGEFILE))) {
if (*pos >= MAX_NON_LFS) {
- send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
if (*count > MAX_NON_LFS - (unsigned long)*pos) {
@@ -1982,7 +1968,6 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
if (likely(!isblk)) {
if (unlikely(*pos >= inode->i_sb->s_maxbytes)) {
if (*count || *pos > inode->i_sb->s_maxbytes) {
- send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
/* zero-length writes at ->s_maxbytes are OK */
diff --git a/mm/highmem.c b/mm/highmem.c
index be8f8d36a8b9..7a967bc35152 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -46,9 +46,14 @@ unsigned int nr_free_highpages (void)
pg_data_t *pgdat;
unsigned int pages = 0;
- for_each_online_pgdat(pgdat)
+ for_each_online_pgdat(pgdat) {
pages += zone_page_state(&pgdat->node_zones[ZONE_HIGHMEM],
NR_FREE_PAGES);
+ if (zone_movable_is_highmem())
+ pages += zone_page_state(
+ &pgdat->node_zones[ZONE_MOVABLE],
+ NR_FREE_PAGES);
+ }
return pages;
}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index a45d1f0691ce..6912bbf33faa 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -27,6 +27,9 @@ unsigned long max_huge_pages;
static struct list_head hugepage_freelists[MAX_NUMNODES];
static unsigned int nr_huge_pages_node[MAX_NUMNODES];
static unsigned int free_huge_pages_node[MAX_NUMNODES];
+static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
+unsigned long hugepages_treat_as_movable;
+
/*
* Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
*/
@@ -66,14 +69,15 @@ static void enqueue_huge_page(struct page *page)
static struct page *dequeue_huge_page(struct vm_area_struct *vma,
unsigned long address)
{
- int nid = numa_node_id();
+ int nid;
struct page *page = NULL;
- struct zonelist *zonelist = huge_zonelist(vma, address);
+ struct zonelist *zonelist = huge_zonelist(vma, address,
+ htlb_alloc_mask);
struct zone **z;
for (z = zonelist->zones; *z; z++) {
nid = zone_to_nid(*z);
- if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
+ if (cpuset_zone_allowed_softwall(*z, htlb_alloc_mask) &&
!list_empty(&hugepage_freelists[nid]))
break;
}
@@ -101,13 +105,20 @@ static void free_huge_page(struct page *page)
static int alloc_fresh_huge_page(void)
{
- static int nid = 0;
+ static int prev_nid;
struct page *page;
- page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
- HUGETLB_PAGE_ORDER);
- nid = next_node(nid, node_online_map);
+ static DEFINE_SPINLOCK(nid_lock);
+ int nid;
+
+ spin_lock(&nid_lock);
+ nid = next_node(prev_nid, node_online_map);
if (nid == MAX_NUMNODES)
nid = first_node(node_online_map);
+ prev_nid = nid;
+ spin_unlock(&nid_lock);
+
+ page = alloc_pages_node(nid, htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
+ HUGETLB_PAGE_ORDER);
if (page) {
set_compound_page_dtor(page, free_huge_page);
spin_lock(&hugetlb_lock);
@@ -256,6 +267,19 @@ int hugetlb_sysctl_handler(struct ctl_table *table, int write,
max_huge_pages = set_max_huge_pages(max_huge_pages);
return 0;
}
+
+int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
+ struct file *file, void __user *buffer,
+ size_t *length, loff_t *ppos)
+{
+ proc_dointvec(table, write, file, buffer, length, ppos);
+ if (hugepages_treat_as_movable)
+ htlb_alloc_mask = GFP_HIGHUSER_MOVABLE;
+ else
+ htlb_alloc_mask = GFP_HIGHUSER;
+ return 0;
+}
+
#endif /* CONFIG_SYSCTL */
int hugetlb_report_meminfo(char *buf)
@@ -474,7 +498,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
return VM_FAULT_MINOR;
}
-int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
+static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, pte_t *ptep, int write_access)
{
int ret = VM_FAULT_SIGBUS;
diff --git a/mm/madvise.c b/mm/madvise.c
index 60542d006ec1..93ee375b38e7 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -287,9 +287,11 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
struct vm_area_struct * vma, *prev;
int unmapped_error = 0;
int error = -EINVAL;
+ int write;
size_t len;
- if (madvise_need_mmap_write(behavior))
+ write = madvise_need_mmap_write(behavior);
+ if (write)
down_write(&current->mm->mmap_sem);
else
down_read(&current->mm->mmap_sem);
@@ -354,7 +356,7 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
vma = find_vma(current->mm, start);
}
out:
- if (madvise_need_mmap_write(behavior))
+ if (write)
up_write(&current->mm->mmap_sem);
else
up_read(&current->mm->mmap_sem);
diff --git a/mm/memory.c b/mm/memory.c
index f64cbf9baa36..9c6ff7fffdc8 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -78,11 +78,9 @@ unsigned long num_physpages;
* and ZONE_HIGHMEM.
*/
void * high_memory;
-unsigned long vmalloc_earlyreserve;
EXPORT_SYMBOL(num_physpages);
EXPORT_SYMBOL(high_memory);
-EXPORT_SYMBOL(vmalloc_earlyreserve);
int randomize_va_space __read_mostly = 1;
@@ -1055,6 +1053,14 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
do {
struct page *page;
+ /*
+ * If tsk is ooming, cut off its access to large memory
+ * allocations. It has a pending SIGKILL, but it can't
+ * be processed until returning to user space.
+ */
+ if (unlikely(test_tsk_thread_flag(tsk, TIF_MEMDIE)))
+ return -ENOMEM;
+
if (write)
foll_flags |= FOLL_WRITE;
@@ -1709,11 +1715,11 @@ gotten:
if (unlikely(anon_vma_prepare(vma)))
goto oom;
if (old_page == ZERO_PAGE(address)) {
- new_page = alloc_zeroed_user_highpage(vma, address);
+ new_page = alloc_zeroed_user_highpage_movable(vma, address);
if (!new_page)
goto oom;
} else {
- new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+ new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
if (!new_page)
goto oom;
cow_user_page(new_page, old_page, address, vma);
@@ -2231,7 +2237,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (unlikely(anon_vma_prepare(vma)))
goto oom;
- page = alloc_zeroed_user_highpage(vma, address);
+ page = alloc_zeroed_user_highpage_movable(vma, address);
if (!page)
goto oom;
@@ -2334,7 +2340,8 @@ retry:
if (unlikely(anon_vma_prepare(vma)))
goto oom;
- page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+ page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+ vma, address);
if (!page)
goto oom;
copy_user_highpage(page, new_page, address, vma);
@@ -2673,7 +2680,7 @@ int make_pages_present(unsigned long addr, unsigned long end)
write = (vma->vm_flags & VM_WRITE) != 0;
BUG_ON(addr >= end);
BUG_ON(end > vma->vm_end);
- len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
+ len = DIV_ROUND_UP(end, PAGE_SIZE) - addr/PAGE_SIZE;
ret = get_user_pages(current, current->mm, addr,
len, write, 0, NULL, NULL);
if (ret < 0)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d76e8eb342d0..9f4e9b95e8f2 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -101,8 +101,6 @@
static struct kmem_cache *policy_cache;
static struct kmem_cache *sn_cache;
-#define PDprintk(fmt...)
-
/* Highest zone. An specific allocation for a zone below that is not
policied. */
enum zone_type policy_zone = 0;
@@ -175,7 +173,9 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
{
struct mempolicy *policy;
- PDprintk("setting mode %d nodes[0] %lx\n", mode, nodes_addr(*nodes)[0]);
+ pr_debug("setting mode %d nodes[0] %lx\n",
+ mode, nodes ? nodes_addr(*nodes)[0] : -1);
+
if (mode == MPOL_DEFAULT)
return NULL;
policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
@@ -379,7 +379,7 @@ static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
int err = 0;
struct mempolicy *old = vma->vm_policy;
- PDprintk("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
+ pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
vma->vm_start, vma->vm_end, vma->vm_pgoff,
vma->vm_ops, vma->vm_file,
vma->vm_ops ? vma->vm_ops->set_policy : NULL);
@@ -594,7 +594,7 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
static struct page *new_node_page(struct page *page, unsigned long node, int **x)
{
- return alloc_pages_node(node, GFP_HIGHUSER, 0);
+ return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
}
/*
@@ -710,7 +710,8 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
{
struct vm_area_struct *vma = (struct vm_area_struct *)private;
- return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma));
+ return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
+ page_address_in_vma(page, vma));
}
#else
@@ -776,8 +777,8 @@ long do_mbind(unsigned long start, unsigned long len,
if (!new)
flags |= MPOL_MF_DISCONTIG_OK;
- PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
- mode,nodes_addr(nodes)[0]);
+ pr_debug("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
+ mode, nmask ? nodes_addr(*nmask)[0] : -1);
down_write(&mm->mmap_sem);
vma = check_range(mm, start, end, nmask,
@@ -1202,7 +1203,8 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
#ifdef CONFIG_HUGETLBFS
/* Return a zonelist suitable for a huge page allocation. */
-struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
+struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
+ gfp_t gfp_flags)
{
struct mempolicy *pol = get_vma_policy(current, vma, addr);
@@ -1210,7 +1212,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
unsigned nid;
nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
- return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+ return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags);
}
return zonelist_policy(GFP_HIGHUSER, pol);
}
@@ -1434,7 +1436,7 @@ static void sp_insert(struct shared_policy *sp, struct sp_node *new)
}
rb_link_node(&new->nd, parent, p);
rb_insert_color(&new->nd, &sp->root);
- PDprintk("inserting %lx-%lx: %d\n", new->start, new->end,
+ pr_debug("inserting %lx-%lx: %d\n", new->start, new->end,
new->policy ? new->policy->policy : 0);
}
@@ -1459,7 +1461,7 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx)
static void sp_delete(struct shared_policy *sp, struct sp_node *n)
{
- PDprintk("deleting %lx-l%x\n", n->start, n->end);
+ pr_debug("deleting %lx-l%lx\n", n->start, n->end);
rb_erase(&n->nd, &sp->root);
mpol_free(n->policy);
kmem_cache_free(sn_cache, n);
@@ -1558,10 +1560,10 @@ int mpol_set_shared_policy(struct shared_policy *info,
struct sp_node *new = NULL;
unsigned long sz = vma_pages(vma);
- PDprintk("set_shared_policy %lx sz %lu %d %lx\n",
+ pr_debug("set_shared_policy %lx sz %lu %d %lx\n",
vma->vm_pgoff,
sz, npol? npol->policy : -1,
- npol ? nodes_addr(npol->v.nodes)[0] : -1);
+ npol ? nodes_addr(npol->v.nodes)[0] : -1);
if (npol) {
new = sp_alloc(vma->vm_pgoff, vma->vm_pgoff + sz, npol);
@@ -1597,6 +1599,10 @@ void mpol_free_shared_policy(struct shared_policy *p)
/* assumes fs == KERNEL_DS */
void __init numa_policy_init(void)
{
+ nodemask_t interleave_nodes;
+ unsigned long largest = 0;
+ int nid, prefer = 0;
+
policy_cache = kmem_cache_create("numa_policy",
sizeof(struct mempolicy),
0, SLAB_PANIC, NULL, NULL);
@@ -1605,10 +1611,31 @@ void __init numa_policy_init(void)
sizeof(struct sp_node),
0, SLAB_PANIC, NULL, NULL);
- /* Set interleaving policy for system init. This way not all
- the data structures allocated at system boot end up in node zero. */
+ /*
+ * Set interleaving policy for system init. Interleaving is only
+ * enabled across suitably sized nodes (default is >= 16MB), or
+ * fall back to the largest node if they're all smaller.
+ */
+ nodes_clear(interleave_nodes);
+ for_each_online_node(nid) {
+ unsigned long total_pages = node_present_pages(nid);
+
+ /* Preserve the largest node */
+ if (largest < total_pages) {
+ largest = total_pages;
+ prefer = nid;
+ }
+
+ /* Interleave this node? */
+ if ((total_pages << PAGE_SHIFT) >= (16 << 20))
+ node_set(nid, interleave_nodes);
+ }
+
+ /* All too small, use the largest */
+ if (unlikely(nodes_empty(interleave_nodes)))
+ node_set(prefer, interleave_nodes);
- if (do_set_mempolicy(MPOL_INTERLEAVE, &node_online_map))
+ if (do_set_mempolicy(MPOL_INTERLEAVE, &interleave_nodes))
printk("numa_policy_init: interleaving failed\n");
}
diff --git a/mm/mempool.c b/mm/mempool.c
index cc1ca86dfc24..02d5ec3feabc 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -62,10 +62,9 @@ mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
mempool_free_t *free_fn, void *pool_data, int node_id)
{
mempool_t *pool;
- pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id);
+ pool = kmalloc_node(sizeof(*pool), GFP_KERNEL | __GFP_ZERO, node_id);
if (!pool)
return NULL;
- memset(pool, 0, sizeof(*pool));
pool->elements = kmalloc_node(min_nr * sizeof(void *),
GFP_KERNEL, node_id);
if (!pool->elements) {
@@ -263,6 +262,9 @@ void mempool_free(void *element, mempool_t *pool)
{
unsigned long flags;
+ if (unlikely(element == NULL))
+ return;
+
smp_mb();
if (pool->curr_nr < pool->min_nr) {
spin_lock_irqsave(&pool->lock, flags);
diff --git a/mm/migrate.c b/mm/migrate.c
index a91ca00abebe..34d8ada053e4 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -761,7 +761,8 @@ static struct page *new_page_node(struct page *p, unsigned long private,
*result = &pm->status;
- return alloc_pages_node(pm->node, GFP_HIGHUSER | GFP_THISNODE, 0);
+ return alloc_pages_node(pm->node,
+ GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0);
}
/*
diff --git a/mm/mlock.c b/mm/mlock.c
index 4d3fea267e0d..7b2656055d6a 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -244,9 +244,12 @@ int user_shm_lock(size_t size, struct user_struct *user)
locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ if (lock_limit == RLIM_INFINITY)
+ allowed = 1;
lock_limit >>= PAGE_SHIFT;
spin_lock(&shmlock_user_lock);
- if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
+ if (!allowed &&
+ locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
goto out;
get_uid(user);
user->locked_shm += locked;
diff --git a/mm/mmap.c b/mm/mmap.c
index 9f70c8e8c871..144b4a290f2c 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -894,14 +894,11 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unsigned long flags, unsigned long pgoff)
{
struct mm_struct * mm = current->mm;
- struct vm_area_struct * vma, * prev;
struct inode *inode;
unsigned int vm_flags;
- int correct_wcount = 0;
int error;
- struct rb_node ** rb_link, * rb_parent;
int accountable = 1;
- unsigned long charged = 0, reqprot = prot;
+ unsigned long reqprot = prot;
/*
* Does the application expect PROT_READ to imply PROT_EXEC?
@@ -1027,6 +1024,24 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
if (error)
return error;
+ return mmap_region(file, addr, len, flags, vm_flags, pgoff,
+ accountable);
+}
+EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long mmap_region(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long flags,
+ unsigned int vm_flags, unsigned long pgoff,
+ int accountable)
+{
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma, *prev;
+ int correct_wcount = 0;
+ int error;
+ struct rb_node **rb_link, *rb_parent;
+ unsigned long charged = 0;
+ struct inode *inode = file ? file->f_path.dentry->d_inode : NULL;
+
/* Clear old maps */
error = -ENOMEM;
munmap_back:
@@ -1175,8 +1190,6 @@ unacct_error:
return error;
}
-EXPORT_SYMBOL(do_mmap_pgoff);
-
/* Get an address range which is currently unmapped.
* For shmat() with addr=0.
*
diff --git a/mm/nommu.c b/mm/nommu.c
index 989e2e9af5c3..8bbbf147a794 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -367,6 +367,11 @@ struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
return find_vma(mm, addr);
}
+int expand_stack(struct vm_area_struct *vma, unsigned long address)
+{
+ return -ENOMEM;
+}
+
/*
* look up the first VMA exactly that exactly matches addr
* - should be called with mm->mmap_sem at least held readlocked
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index eec1481ba44f..886ea0d5a136 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -476,15 +476,13 @@ static void wb_kupdate(unsigned long arg)
* sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
*/
int dirty_writeback_centisecs_handler(ctl_table *table, int write,
- struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+ struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
{
proc_dointvec_userhz_jiffies(table, write, file, buffer, length, ppos);
- if (dirty_writeback_interval) {
- mod_timer(&wb_timer,
- jiffies + dirty_writeback_interval);
- } else {
+ if (dirty_writeback_interval)
+ mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
+ else
del_timer(&wb_timer);
- }
return 0;
}
@@ -826,6 +824,7 @@ int __set_page_dirty_nobuffers(struct page *page)
mapping2 = page_mapping(page);
if (mapping2) { /* Race with truncate? */
BUG_ON(mapping2 != mapping);
+ WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
if (mapping_cap_account_dirty(mapping)) {
__inc_zone_page_state(page, NR_FILE_DIRTY);
task_io_account_write(PAGE_CACHE_SIZE);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 05ace44852eb..e2a10b957f23 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -80,8 +80,9 @@ int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = {
256,
#endif
#ifdef CONFIG_HIGHMEM
- 32
+ 32,
#endif
+ 32,
};
EXPORT_SYMBOL(totalram_pages);
@@ -95,8 +96,9 @@ static char * const zone_names[MAX_NR_ZONES] = {
#endif
"Normal",
#ifdef CONFIG_HIGHMEM
- "HighMem"
+ "HighMem",
#endif
+ "Movable",
};
int min_free_kbytes = 1024;
@@ -126,14 +128,21 @@ static unsigned long __meminitdata dma_reserve;
#endif
#endif
- struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
- int __meminitdata nr_nodemap_entries;
- unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
- unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
+ static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
+ static int __meminitdata nr_nodemap_entries;
+ static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
+ static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
- unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
- unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
+ static unsigned long __meminitdata node_boundary_start_pfn[MAX_NUMNODES];
+ static unsigned long __meminitdata node_boundary_end_pfn[MAX_NUMNODES];
#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+ unsigned long __initdata required_kernelcore;
+ unsigned long __initdata required_movablecore;
+ unsigned long __initdata zone_movable_pfn[MAX_NUMNODES];
+
+ /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
+ int movable_zone;
+ EXPORT_SYMBOL(movable_zone);
#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
#if MAX_NUMNODES > 1
@@ -900,11 +909,13 @@ static struct fail_page_alloc_attr {
u32 ignore_gfp_highmem;
u32 ignore_gfp_wait;
+ u32 min_order;
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
struct dentry *ignore_gfp_highmem_file;
struct dentry *ignore_gfp_wait_file;
+ struct dentry *min_order_file;
#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
@@ -912,6 +923,7 @@ static struct fail_page_alloc_attr {
.attr = FAULT_ATTR_INITIALIZER,
.ignore_gfp_wait = 1,
.ignore_gfp_highmem = 1,
+ .min_order = 1,
};
static int __init setup_fail_page_alloc(char *str)
@@ -922,6 +934,8 @@ __setup("fail_page_alloc=", setup_fail_page_alloc);
static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
{
+ if (order < fail_page_alloc.min_order)
+ return 0;
if (gfp_mask & __GFP_NOFAIL)
return 0;
if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM))
@@ -953,12 +967,17 @@ static int __init fail_page_alloc_debugfs(void)
fail_page_alloc.ignore_gfp_highmem_file =
debugfs_create_bool("ignore-gfp-highmem", mode, dir,
&fail_page_alloc.ignore_gfp_highmem);
+ fail_page_alloc.min_order_file =
+ debugfs_create_u32("min-order", mode, dir,
+ &fail_page_alloc.min_order);
if (!fail_page_alloc.ignore_gfp_wait_file ||
- !fail_page_alloc.ignore_gfp_highmem_file) {
+ !fail_page_alloc.ignore_gfp_highmem_file ||
+ !fail_page_alloc.min_order_file) {
err = -ENOMEM;
debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
+ debugfs_remove(fail_page_alloc.min_order_file);
cleanup_fault_attr_dentries(&fail_page_alloc.attr);
}
@@ -1314,7 +1333,7 @@ nofail_alloc:
reclaim_state.reclaimed_slab = 0;
p->reclaim_state = &reclaim_state;
- did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask);
+ did_some_progress = try_to_free_pages(zonelist->zones, order, gfp_mask);
p->reclaim_state = NULL;
p->flags &= ~PF_MEMALLOC;
@@ -1351,7 +1370,8 @@ nofail_alloc:
*/
do_retry = 0;
if (!(gfp_mask & __GFP_NORETRY)) {
- if ((order <= 3) || (gfp_mask & __GFP_REPEAT))
+ if ((order <= PAGE_ALLOC_COSTLY_ORDER) ||
+ (gfp_mask & __GFP_REPEAT))
do_retry = 1;
if (gfp_mask & __GFP_NOFAIL)
do_retry = 1;
@@ -1464,13 +1484,14 @@ unsigned int nr_free_buffer_pages(void)
{
return nr_free_zone_pages(gfp_zone(GFP_USER));
}
+EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
/*
* Amount of free RAM allocatable within all zones
*/
unsigned int nr_free_pagecache_pages(void)
{
- return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
+ return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE));
}
static inline void show_node(struct zone *zone)
@@ -1621,8 +1642,8 @@ void show_free_areas(void)
*
* Add all populated zones of a node to the zonelist.
*/
-static int __meminit build_zonelists_node(pg_data_t *pgdat,
- struct zonelist *zonelist, int nr_zones, enum zone_type zone_type)
+static int build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,
+ int nr_zones, enum zone_type zone_type)
{
struct zone *zone;
@@ -1641,9 +1662,102 @@ static int __meminit build_zonelists_node(pg_data_t *pgdat,
return nr_zones;
}
+
+/*
+ * zonelist_order:
+ * 0 = automatic detection of better ordering.
+ * 1 = order by ([node] distance, -zonetype)
+ * 2 = order by (-zonetype, [node] distance)
+ *
+ * If not NUMA, ZONELIST_ORDER_ZONE and ZONELIST_ORDER_NODE will create
+ * the same zonelist. So only NUMA can configure this param.
+ */
+#define ZONELIST_ORDER_DEFAULT 0
+#define ZONELIST_ORDER_NODE 1
+#define ZONELIST_ORDER_ZONE 2
+
+/* zonelist order in the kernel.
+ * set_zonelist_order() will set this to NODE or ZONE.
+ */
+static int current_zonelist_order = ZONELIST_ORDER_DEFAULT;
+static char zonelist_order_name[3][8] = {"Default", "Node", "Zone"};
+
+
#ifdef CONFIG_NUMA
+/* The value user specified ....changed by config */
+static int user_zonelist_order = ZONELIST_ORDER_DEFAULT;
+/* string for sysctl */
+#define NUMA_ZONELIST_ORDER_LEN 16
+char numa_zonelist_order[16] = "default";
+
+/*
+ * interface for configure zonelist ordering.
+ * command line option "numa_zonelist_order"
+ * = "[dD]efault - default, automatic configuration.
+ * = "[nN]ode - order by node locality, then by zone within node
+ * = "[zZ]one - order by zone, then by locality within zone
+ */
+
+static int __parse_numa_zonelist_order(char *s)
+{
+ if (*s == 'd' || *s == 'D') {
+ user_zonelist_order = ZONELIST_ORDER_DEFAULT;
+ } else if (*s == 'n' || *s == 'N') {
+ user_zonelist_order = ZONELIST_ORDER_NODE;
+ } else if (*s == 'z' || *s == 'Z') {
+ user_zonelist_order = ZONELIST_ORDER_ZONE;
+ } else {
+ printk(KERN_WARNING
+ "Ignoring invalid numa_zonelist_order value: "
+ "%s\n", s);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static __init int setup_numa_zonelist_order(char *s)
+{
+ if (s)
+ return __parse_numa_zonelist_order(s);
+ return 0;
+}
+early_param("numa_zonelist_order", setup_numa_zonelist_order);
+
+/*
+ * sysctl handler for numa_zonelist_order
+ */
+int numa_zonelist_order_handler(ctl_table *table, int write,
+ struct file *file, void __user *buffer, size_t *length,
+ loff_t *ppos)
+{
+ char saved_string[NUMA_ZONELIST_ORDER_LEN];
+ int ret;
+
+ if (write)
+ strncpy(saved_string, (char*)table->data,
+ NUMA_ZONELIST_ORDER_LEN);
+ ret = proc_dostring(table, write, file, buffer, length, ppos);
+ if (ret)
+ return ret;
+ if (write) {
+ int oldval = user_zonelist_order;
+ if (__parse_numa_zonelist_order((char*)table->data)) {
+ /*
+ * bogus value. restore saved string
+ */
+ strncpy((char*)table->data, saved_string,
+ NUMA_ZONELIST_ORDER_LEN);
+ user_zonelist_order = oldval;
+ } else if (oldval != user_zonelist_order)
+ build_all_zonelists();
+ }
+ return 0;
+}
+
+
#define MAX_NODE_LOAD (num_online_nodes())
-static int __meminitdata node_load[MAX_NUMNODES];
+static int node_load[MAX_NUMNODES];
+
/**
* find_next_best_node - find the next node that should appear in a given node's fallback list
* @node: node whose fallback list we're appending
@@ -1658,7 +1772,7 @@ static int __meminitdata node_load[MAX_NUMNODES];
* on them otherwise.
* It returns -1 if no node is found.
*/
-static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask)
+static int find_next_best_node(int node, nodemask_t *used_node_mask)
{
int n, val;
int min_val = INT_MAX;
@@ -1704,13 +1818,129 @@ static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask)
return best_node;
}
-static void __meminit build_zonelists(pg_data_t *pgdat)
+
+/*
+ * Build zonelists ordered by node and zones within node.
+ * This results in maximum locality--normal zone overflows into local
+ * DMA zone, if any--but risks exhausting DMA zone.
+ */
+static void build_zonelists_in_node_order(pg_data_t *pgdat, int node)
+{
+ enum zone_type i;
+ int j;
+ struct zonelist *zonelist;
+
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ zonelist = pgdat->node_zonelists + i;
+ for (j = 0; zonelist->zones[j] != NULL; j++)
+ ;
+ j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
+ zonelist->zones[j] = NULL;
+ }
+}
+
+/*
+ * Build zonelists ordered by zone and nodes within zones.
+ * This results in conserving DMA zone[s] until all Normal memory is
+ * exhausted, but results in overflowing to remote node while memory
+ * may still exist in local DMA zone.
+ */
+static int node_order[MAX_NUMNODES];
+
+static void build_zonelists_in_zone_order(pg_data_t *pgdat, int nr_nodes)
{
- int j, node, local_node;
enum zone_type i;
- int prev_node, load;
+ int pos, j, node;
+ int zone_type; /* needs to be signed */
+ struct zone *z;
struct zonelist *zonelist;
+
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ zonelist = pgdat->node_zonelists + i;
+ pos = 0;
+ for (zone_type = i; zone_type >= 0; zone_type--) {
+ for (j = 0; j < nr_nodes; j++) {
+ node = node_order[j];
+ z = &NODE_DATA(node)->node_zones[zone_type];
+ if (populated_zone(z)) {
+ zonelist->zones[pos++] = z;
+ check_highest_zone(zone_type);
+ }
+ }
+ }
+ zonelist->zones[pos] = NULL;
+ }
+}
+
+static int default_zonelist_order(void)
+{
+ int nid, zone_type;
+ unsigned long low_kmem_size,total_size;
+ struct zone *z;
+ int average_size;
+ /*
+ * ZONE_DMA and ZONE_DMA32 can be very small area in the sytem.
+ * If they are really small and used heavily, the system can fall
+ * into OOM very easily.
+ * This function detect ZONE_DMA/DMA32 size and confgigures zone order.
+ */
+ /* Is there ZONE_NORMAL ? (ex. ppc has only DMA zone..) */
+ low_kmem_size = 0;
+ total_size = 0;
+ for_each_online_node(nid) {
+ for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) {
+ z = &NODE_DATA(nid)->node_zones[zone_type];
+ if (populated_zone(z)) {
+ if (zone_type < ZONE_NORMAL)
+ low_kmem_size += z->present_pages;
+ total_size += z->present_pages;
+ }
+ }
+ }
+ if (!low_kmem_size || /* there are no DMA area. */
+ low_kmem_size > total_size/2) /* DMA/DMA32 is big. */
+ return ZONELIST_ORDER_NODE;
+ /*
+ * look into each node's config.
+ * If there is a node whose DMA/DMA32 memory is very big area on
+ * local memory, NODE_ORDER may be suitable.
+ */
+ average_size = total_size / (num_online_nodes() + 1);
+ for_each_online_node(nid) {
+ low_kmem_size = 0;
+ total_size = 0;
+ for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) {
+ z = &NODE_DATA(nid)->node_zones[zone_type];
+ if (populated_zone(z)) {
+ if (zone_type < ZONE_NORMAL)
+ low_kmem_size += z->present_pages;
+ total_size += z->present_pages;
+ }
+ }
+ if (low_kmem_size &&
+ total_size > average_size && /* ignore small node */
+ low_kmem_size > total_size * 70/100)
+ return ZONELIST_ORDER_NODE;
+ }
+ return ZONELIST_ORDER_ZONE;
+}
+
+static void set_zonelist_order(void)
+{
+ if (user_zonelist_order == ZONELIST_ORDER_DEFAULT)
+ current_zonelist_order = default_zonelist_order();
+ else
+ current_zonelist_order = user_zonelist_order;
+}
+
+static void build_zonelists(pg_data_t *pgdat)
+{
+ int j, node, load;
+ enum zone_type i;
nodemask_t used_mask;
+ int local_node, prev_node;
+ struct zonelist *zonelist;
+ int order = current_zonelist_order;
/* initialize zonelists */
for (i = 0; i < MAX_NR_ZONES; i++) {
@@ -1723,6 +1953,11 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
load = num_online_nodes();
prev_node = local_node;
nodes_clear(used_mask);
+
+ memset(node_load, 0, sizeof(node_load));
+ memset(node_order, 0, sizeof(node_order));
+ j = 0;
+
while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
int distance = node_distance(local_node, node);
@@ -1738,23 +1973,25 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
* So adding penalty to the first node in same
* distance group to make it round-robin.
*/
-
if (distance != node_distance(local_node, prev_node))
- node_load[node] += load;
+ node_load[node] = load;
+
prev_node = node;
load--;
- for (i = 0; i < MAX_NR_ZONES; i++) {
- zonelist = pgdat->node_zonelists + i;
- for (j = 0; zonelist->zones[j] != NULL; j++);
+ if (order == ZONELIST_ORDER_NODE)
+ build_zonelists_in_node_order(pgdat, node);
+ else
+ node_order[j++] = node; /* remember order */
+ }
- j = build_zonelists_node(NODE_DATA(node), zonelist, j, i);
- zonelist->zones[j] = NULL;
- }
+ if (order == ZONELIST_ORDER_ZONE) {
+ /* calculate node order -- i.e., DMA last! */
+ build_zonelists_in_zone_order(pgdat, j);
}
}
/* Construct the zonelist performance cache - see further mmzone.h */
-static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+static void build_zonelist_cache(pg_data_t *pgdat)
{
int i;
@@ -1771,9 +2008,15 @@ static void __meminit build_zonelist_cache(pg_data_t *pgdat)
}
}
+
#else /* CONFIG_NUMA */
-static void __meminit build_zonelists(pg_data_t *pgdat)
+static void set_zonelist_order(void)
+{
+ current_zonelist_order = ZONELIST_ORDER_ZONE;
+}
+
+static void build_zonelists(pg_data_t *pgdat)
{
int node, local_node;
enum zone_type i,j;
@@ -1809,7 +2052,7 @@ static void __meminit build_zonelists(pg_data_t *pgdat)
}
/* non-NUMA variant of zonelist performance cache - just NULL zlcache_ptr */
-static void __meminit build_zonelist_cache(pg_data_t *pgdat)
+static void build_zonelist_cache(pg_data_t *pgdat)
{
int i;
@@ -1820,7 +2063,7 @@ static void __meminit build_zonelist_cache(pg_data_t *pgdat)
#endif /* CONFIG_NUMA */
/* return values int ....just for stop_machine_run() */
-static int __meminit __build_all_zonelists(void *dummy)
+static int __build_all_zonelists(void *dummy)
{
int nid;
@@ -1831,8 +2074,10 @@ static int __meminit __build_all_zonelists(void *dummy)
return 0;
}
-void __meminit build_all_zonelists(void)
+void build_all_zonelists(void)
{
+ set_zonelist_order();
+
if (system_state == SYSTEM_BOOTING) {
__build_all_zonelists(NULL);
cpuset_init_current_mems_allowed();
@@ -1843,8 +2088,13 @@ void __meminit build_all_zonelists(void)
/* cpuset refresh routine should be here */
}
vm_total_pages = nr_free_pagecache_pages();
- printk("Built %i zonelists. Total pages: %ld\n",
- num_online_nodes(), vm_total_pages);
+ printk("Built %i zonelists in %s order. Total pages: %ld\n",
+ num_online_nodes(),
+ zonelist_order_name[current_zonelist_order],
+ vm_total_pages);
+#ifdef CONFIG_NUMA
+ printk("Policy zone: %s\n", zone_names[policy_zone]);
+#endif
}
/*
@@ -1953,8 +2203,8 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
}
}
-void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
- unsigned long size)
+static void __meminit zone_init_free_lists(struct pglist_data *pgdat,
+ struct zone *zone, unsigned long size)
{
int order;
for (order = 0; order < MAX_ORDER ; order++) {
@@ -2370,7 +2620,7 @@ void __init push_node_boundaries(unsigned int nid,
}
/* If necessary, push the node boundary out for reserve hotadd */
-static void __init account_node_boundary(unsigned int nid,
+static void __meminit account_node_boundary(unsigned int nid,
unsigned long *start_pfn, unsigned long *end_pfn)
{
printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
@@ -2390,7 +2640,7 @@ static void __init account_node_boundary(unsigned int nid,
void __init push_node_boundaries(unsigned int nid,
unsigned long start_pfn, unsigned long end_pfn) {}
-static void __init account_node_boundary(unsigned int nid,
+static void __meminit account_node_boundary(unsigned int nid,
unsigned long *start_pfn, unsigned long *end_pfn) {}
#endif
@@ -2428,10 +2678,67 @@ void __meminit get_pfn_range_for_nid(unsigned int nid,
}
/*
+ * This finds a zone that can be used for ZONE_MOVABLE pages. The
+ * assumption is made that zones within a node are ordered in monotonic
+ * increasing memory addresses so that the "highest" populated zone is used
+ */
+void __init find_usable_zone_for_movable(void)
+{
+ int zone_index;
+ for (zone_index = MAX_NR_ZONES - 1; zone_index >= 0; zone_index--) {
+ if (zone_index == ZONE_MOVABLE)
+ continue;
+
+ if (arch_zone_highest_possible_pfn[zone_index] >
+ arch_zone_lowest_possible_pfn[zone_index])
+ break;
+ }
+
+ VM_BUG_ON(zone_index == -1);
+ movable_zone = zone_index;
+}
+
+/*
+ * The zone ranges provided by the architecture do not include ZONE_MOVABLE
+ * because it is sized independant of architecture. Unlike the other zones,
+ * the starting point for ZONE_MOVABLE is not fixed. It may be different
+ * in each node depending on the size of each node and how evenly kernelcore
+ * is distributed. This helper function adjusts the zone ranges
+ * provided by the architecture for a given node by using the end of the
+ * highest usable zone for ZONE_MOVABLE. This preserves the assumption that
+ * zones within a node are in order of monotonic increases memory addresses
+ */
+void __meminit adjust_zone_range_for_zone_movable(int nid,
+ unsigned long zone_type,
+ unsigned long node_start_pfn,
+ unsigned long node_end_pfn,
+ unsigned long *zone_start_pfn,
+ unsigned long *zone_end_pfn)
+{
+ /* Only adjust if ZONE_MOVABLE is on this node */
+ if (zone_movable_pfn[nid]) {
+ /* Size ZONE_MOVABLE */
+ if (zone_type == ZONE_MOVABLE) {
+ *zone_start_pfn = zone_movable_pfn[nid];
+ *zone_end_pfn = min(node_end_pfn,
+ arch_zone_highest_possible_pfn[movable_zone]);
+
+ /* Adjust for ZONE_MOVABLE starting within this range */
+ } else if (*zone_start_pfn < zone_movable_pfn[nid] &&
+ *zone_end_pfn > zone_movable_pfn[nid]) {
+ *zone_end_pfn = zone_movable_pfn[nid];
+
+ /* Check if this whole range is within ZONE_MOVABLE */
+ } else if (*zone_start_pfn >= zone_movable_pfn[nid])
+ *zone_start_pfn = *zone_end_pfn;
+ }
+}
+
+/*
* Return the number of pages a zone spans in a node, including holes
* present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
*/
-unsigned long __meminit zone_spanned_pages_in_node(int nid,
+static unsigned long __meminit zone_spanned_pages_in_node(int nid,
unsigned long zone_type,
unsigned long *ignored)
{
@@ -2442,6 +2749,9 @@ unsigned long __meminit zone_spanned_pages_in_node(int nid,
get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+ adjust_zone_range_for_zone_movable(nid, zone_type,
+ node_start_pfn, node_end_pfn,
+ &zone_start_pfn, &zone_end_pfn);
/* Check that this node has pages within the zone's required range */
if (zone_end_pfn < node_start_pfn || zone_start_pfn > node_end_pfn)
@@ -2519,7 +2829,7 @@ unsigned long __init absent_pages_in_range(unsigned long start_pfn,
}
/* Return the number of page frames in holes in a zone on a node */
-unsigned long __meminit zone_absent_pages_in_node(int nid,
+static unsigned long __meminit zone_absent_pages_in_node(int nid,
unsigned long zone_type,
unsigned long *ignored)
{
@@ -2532,18 +2842,21 @@ unsigned long __meminit zone_absent_pages_in_node(int nid,
zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type],
node_end_pfn);
+ adjust_zone_range_for_zone_movable(nid, zone_type,
+ node_start_pfn, node_end_pfn,
+ &zone_start_pfn, &zone_end_pfn);
return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
}
#else
-static inline unsigned long zone_spanned_pages_in_node(int nid,
+static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
unsigned long zone_type,
unsigned long *zones_size)
{
return zones_size[zone_type];
}
-static inline unsigned long zone_absent_pages_in_node(int nid,
+static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
unsigned long zone_type,
unsigned long *zholes_size)
{
@@ -2909,6 +3222,157 @@ unsigned long __init find_max_pfn_with_active_regions(void)
return max_pfn;
}
+unsigned long __init early_calculate_totalpages(void)
+{
+ int i;
+ unsigned long totalpages = 0;
+
+ for (i = 0; i < nr_nodemap_entries; i++)
+ totalpages += early_node_map[i].end_pfn -
+ early_node_map[i].start_pfn;
+
+ return totalpages;
+}
+
+/*
+ * Find the PFN the Movable zone begins in each node. Kernel memory
+ * is spread evenly between nodes as long as the nodes have enough
+ * memory. When they don't, some nodes will have more kernelcore than
+ * others
+ */
+void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
+{
+ int i, nid;
+ unsigned long usable_startpfn;
+ unsigned long kernelcore_node, kernelcore_remaining;
+ int usable_nodes = num_online_nodes();
+
+ /*
+ * If movablecore was specified, calculate what size of
+ * kernelcore that corresponds so that memory usable for
+ * any allocation type is evenly spread. If both kernelcore
+ * and movablecore are specified, then the value of kernelcore
+ * will be used for required_kernelcore if it's greater than
+ * what movablecore would have allowed.
+ */
+ if (required_movablecore) {
+ unsigned long totalpages = early_calculate_totalpages();
+ unsigned long corepages;
+
+ /*
+ * Round-up so that ZONE_MOVABLE is at least as large as what
+ * was requested by the user
+ */
+ required_movablecore =
+ roundup(required_movablecore, MAX_ORDER_NR_PAGES);
+ corepages = totalpages - required_movablecore;
+
+ required_kernelcore = max(required_kernelcore, corepages);
+ }
+
+ /* If kernelcore was not specified, there is no ZONE_MOVABLE */
+ if (!required_kernelcore)
+ return;
+
+ /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */
+ find_usable_zone_for_movable();
+ usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone];
+
+restart:
+ /* Spread kernelcore memory as evenly as possible throughout nodes */
+ kernelcore_node = required_kernelcore / usable_nodes;
+ for_each_online_node(nid) {
+ /*
+ * Recalculate kernelcore_node if the division per node
+ * now exceeds what is necessary to satisfy the requested
+ * amount of memory for the kernel
+ */
+ if (required_kernelcore < kernelcore_node)
+ kernelcore_node = required_kernelcore / usable_nodes;
+
+ /*
+ * As the map is walked, we track how much memory is usable
+ * by the kernel using kernelcore_remaining. When it is
+ * 0, the rest of the node is usable by ZONE_MOVABLE
+ */
+ kernelcore_remaining = kernelcore_node;
+
+ /* Go through each range of PFNs within this node */
+ for_each_active_range_index_in_nid(i, nid) {
+ unsigned long start_pfn, end_pfn;
+ unsigned long size_pages;
+
+ start_pfn = max(early_node_map[i].start_pfn,
+ zone_movable_pfn[nid]);
+ end_pfn = early_node_map[i].end_pfn;
+ if (start_pfn >= end_pfn)
+ continue;
+
+ /* Account for what is only usable for kernelcore */
+ if (start_pfn < usable_startpfn) {
+ unsigned long kernel_pages;
+ kernel_pages = min(end_pfn, usable_startpfn)
+ - start_pfn;
+
+ kernelcore_remaining -= min(kernel_pages,
+ kernelcore_remaining);
+ required_kernelcore -= min(kernel_pages,
+ required_kernelcore);
+
+ /* Continue if range is now fully accounted */
+ if (end_pfn <= usable_startpfn) {
+
+ /*
+ * Push zone_movable_pfn to the end so
+ * that if we have to rebalance
+ * kernelcore across nodes, we will
+ * not double account here
+ */
+ zone_movable_pfn[nid] = end_pfn;
+ continue;
+ }
+ start_pfn = usable_startpfn;
+ }
+
+ /*
+ * The usable PFN range for ZONE_MOVABLE is from
+ * start_pfn->end_pfn. Calculate size_pages as the
+ * number of pages used as kernelcore
+ */
+ size_pages = end_pfn - start_pfn;
+ if (size_pages > kernelcore_remaining)
+ size_pages = kernelcore_remaining;
+ zone_movable_pfn[nid] = start_pfn + size_pages;
+
+ /*
+ * Some kernelcore has been met, update counts and
+ * break if the kernelcore for this node has been
+ * satisified
+ */
+ required_kernelcore -= min(required_kernelcore,
+ size_pages);
+ kernelcore_remaining -= size_pages;
+ if (!kernelcore_remaining)
+ break;
+ }
+ }
+
+ /*
+ * If there is still required_kernelcore, we do another pass with one
+ * less node in the count. This will push zone_movable_pfn[nid] further
+ * along on the nodes that still have memory until kernelcore is
+ * satisified
+ */
+ usable_nodes--;
+ if (usable_nodes && required_kernelcore > usable_nodes)
+ goto restart;
+
+ /* Align start of ZONE_MOVABLE on all nids to MAX_ORDER_NR_PAGES */
+ for (nid = 0; nid < MAX_NUMNODES; nid++)
+ zone_movable_pfn[nid] =
+ roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES);
+}
+
/**
* free_area_init_nodes - Initialise all pg_data_t and zone data
* @max_zone_pfn: an array of max PFNs for each zone
@@ -2938,19 +3402,37 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
for (i = 1; i < MAX_NR_ZONES; i++) {
+ if (i == ZONE_MOVABLE)
+ continue;
arch_zone_lowest_possible_pfn[i] =
arch_zone_highest_possible_pfn[i-1];
arch_zone_highest_possible_pfn[i] =
max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
}
+ arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0;
+ arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;
+
+ /* Find the PFNs that ZONE_MOVABLE begins at in each node */
+ memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn));
+ find_zone_movable_pfns_for_nodes(zone_movable_pfn);
/* Print out the zone ranges */
printk("Zone PFN ranges:\n");
- for (i = 0; i < MAX_NR_ZONES; i++)
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ if (i == ZONE_MOVABLE)
+ continue;
printk(" %-8s %8lu -> %8lu\n",
zone_names[i],
arch_zone_lowest_possible_pfn[i],
arch_zone_highest_possible_pfn[i]);
+ }
+
+ /* Print out the PFNs ZONE_MOVABLE begins at in each node */
+ printk("Movable zone start PFN for each node\n");
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ if (zone_movable_pfn[i])
+ printk(" Node %d: %lu\n", i, zone_movable_pfn[i]);
+ }
/* Print out the early_node_map[] */
printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
@@ -2967,6 +3449,43 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
find_min_pfn_for_node(nid), NULL);
}
}
+
+static int __init cmdline_parse_core(char *p, unsigned long *core)
+{
+ unsigned long long coremem;
+ if (!p)
+ return -EINVAL;
+
+ coremem = memparse(p, &p);
+ *core = coremem >> PAGE_SHIFT;
+
+ /* Paranoid check that UL is enough for the coremem value */
+ WARN_ON((coremem >> PAGE_SHIFT) > ULONG_MAX);
+
+ return 0;
+}
+
+/*
+ * kernelcore=size sets the amount of memory for use for allocations that
+ * cannot be reclaimed or migrated.
+ */
+static int __init cmdline_parse_kernelcore(char *p)
+{
+ return cmdline_parse_core(p, &required_kernelcore);
+}
+
+/*
+ * movablecore=size sets the amount of memory for use for allocations that
+ * can be reclaimed or migrated.
+ */
+static int __init cmdline_parse_movablecore(char *p)
+{
+ return cmdline_parse_core(p, &required_movablecore);
+}
+
+early_param("kernelcore", cmdline_parse_kernelcore);
+early_param("movablecore", cmdline_parse_movablecore);
+
#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
/**
@@ -3355,13 +3874,28 @@ void *__init alloc_large_system_hash(const char *tablename,
for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
;
table = (void*) __get_free_pages(GFP_ATOMIC, order);
+ /*
+ * If bucketsize is not a power-of-two, we may free
+ * some pages at the end of hash table.
+ */
+ if (table) {
+ unsigned long alloc_end = (unsigned long)table +
+ (PAGE_SIZE << order);
+ unsigned long used = (unsigned long)table +
+ PAGE_ALIGN(size);
+ split_page(virt_to_page(table), order);
+ while (used < alloc_end) {
+ free_page(used);
+ used += PAGE_SIZE;
+ }
+ }
}
} while (!table && size > PAGE_SIZE && --log2qty);
if (!table)
panic("Failed to allocate %s hash table\n", tablename);
- printk("%s hash table entries: %d (order: %d, %lu bytes)\n",
+ printk(KERN_INFO "%s hash table entries: %d (order: %d, %lu bytes)\n",
tablename,
(1U << log2qty),
ilog2(size) - PAGE_SHIFT,
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 8ce0900dc95c..8f6ee073c0e3 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -92,6 +92,7 @@ struct pdflush_work {
static int __pdflush(struct pdflush_work *my_work)
{
current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+ set_freezable();
my_work->fn = NULL;
my_work->who = current;
INIT_LIST_HEAD(&my_work->list);
diff --git a/mm/shmem.c b/mm/shmem.c
index 0493e4d0bcaa..96fa79fb6ad3 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/xattr.h>
+#include <linux/exportfs.h>
#include <linux/generic_acl.h>
#include <linux/mm.h>
#include <linux/mman.h>
@@ -93,8 +94,11 @@ static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
* The above definition of ENTRIES_PER_PAGE, and the use of
* BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
* might be reconsidered if it ever diverges from PAGE_SIZE.
+ *
+ * __GFP_MOVABLE is masked out as swap vectors cannot move
*/
- return alloc_pages(gfp_mask, PAGE_CACHE_SHIFT-PAGE_SHIFT);
+ return alloc_pages((gfp_mask & ~__GFP_MOVABLE) | __GFP_ZERO,
+ PAGE_CACHE_SHIFT-PAGE_SHIFT);
}
static inline void shmem_dir_free(struct page *page)
@@ -372,7 +376,7 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
}
spin_unlock(&info->lock);
- page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
+ page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
if (page)
set_page_private(page, 0);
spin_lock(&info->lock);
diff --git a/mm/slab.c b/mm/slab.c
index b344e6707128..96d30ee256ef 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -775,6 +775,9 @@ static inline struct kmem_cache *__find_general_cachep(size_t size,
*/
BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
#endif
+ if (!size)
+ return ZERO_SIZE_PTR;
+
while (size > csizep->cs_size)
csizep++;
@@ -929,7 +932,7 @@ static void next_reap_node(void)
* the CPUs getting into lockstep and contending for the global cache chain
* lock.
*/
-static void __devinit start_cpu_timer(int cpu)
+static void __cpuinit start_cpu_timer(int cpu)
{
struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
@@ -2351,7 +2354,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* this should not happen at all.
* But leave a BUG_ON for some lucky dude.
*/
- BUG_ON(!cachep->slabp_cache);
+ BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
}
cachep->ctor = ctor;
cachep->name = name;
@@ -2743,7 +2746,7 @@ static int cache_grow(struct kmem_cache *cachep,
* Be lazy and only check for valid flags here, keeping it out of the
* critical path in kmem_cache_alloc().
*/
- BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+ BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
local_flags = (flags & GFP_LEVEL_MASK);
/* Take the l3 list lock to change the colour_next on this node */
@@ -3389,6 +3392,9 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
local_irq_restore(save_flags);
ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
+ if (unlikely((flags & __GFP_ZERO) && ptr))
+ memset(ptr, 0, obj_size(cachep));
+
return ptr;
}
@@ -3440,6 +3446,9 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
prefetchw(objp);
+ if (unlikely((flags & __GFP_ZERO) && objp))
+ memset(objp, 0, obj_size(cachep));
+
return objp;
}
@@ -3581,23 +3590,6 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
EXPORT_SYMBOL(kmem_cache_alloc);
/**
- * kmem_cache_zalloc - Allocate an object. The memory is set to zero.
- * @cache: The cache to allocate from.
- * @flags: See kmalloc().
- *
- * Allocate an object from this cache and set the allocated memory to zero.
- * The flags are only relevant if the cache has no available objects.
- */
-void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
-{
- void *ret = __cache_alloc(cache, flags, __builtin_return_address(0));
- if (ret)
- memset(ret, 0, obj_size(cache));
- return ret;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
-
-/**
* kmem_ptr_validate - check if an untrusted pointer might
* be a slab entry.
* @cachep: the cache we're checking against
@@ -3653,8 +3645,8 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller)
struct kmem_cache *cachep;
cachep = kmem_find_general_cachep(size, flags);
- if (unlikely(cachep == NULL))
- return NULL;
+ if (unlikely(ZERO_OR_NULL_PTR(cachep)))
+ return cachep;
return kmem_cache_alloc_node(cachep, flags, node);
}
@@ -3726,52 +3718,6 @@ EXPORT_SYMBOL(__kmalloc);
#endif
/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes. If @p is %NULL, krealloc()
- * behaves exactly like kmalloc(). If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
- */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
-{
- struct kmem_cache *cache, *new_cache;
- void *ret;
-
- if (unlikely(!p))
- return kmalloc_track_caller(new_size, flags);
-
- if (unlikely(!new_size)) {
- kfree(p);
- return NULL;
- }
-
- cache = virt_to_cache(p);
- new_cache = __find_general_cachep(new_size, flags);
-
- /*
- * If new size fits in the current cache, bail out.
- */
- if (likely(cache == new_cache))
- return (void *)p;
-
- /*
- * We are on the slow-path here so do not use __cache_alloc
- * because it bloats kernel text.
- */
- ret = kmalloc_track_caller(new_size, flags);
- if (ret) {
- memcpy(ret, p, min(new_size, ksize(p)));
- kfree(p);
- }
- return ret;
-}
-EXPORT_SYMBOL(krealloc);
-
-/**
* kmem_cache_free - Deallocate an object
* @cachep: The cache the allocation was from.
* @objp: The previously allocated object.
@@ -3806,7 +3752,7 @@ void kfree(const void *objp)
struct kmem_cache *c;
unsigned long flags;
- if (unlikely(!objp))
+ if (unlikely(ZERO_OR_NULL_PTR(objp)))
return;
local_irq_save(flags);
kfree_debugcheck(objp);
@@ -4157,26 +4103,17 @@ static void print_slabinfo_header(struct seq_file *m)
static void *s_start(struct seq_file *m, loff_t *pos)
{
loff_t n = *pos;
- struct list_head *p;
mutex_lock(&cache_chain_mutex);
if (!n)
print_slabinfo_header(m);
- p = cache_chain.next;
- while (n--) {
- p = p->next;
- if (p == &cache_chain)
- return NULL;
- }
- return list_entry(p, struct kmem_cache, next);
+
+ return seq_list_start(&cache_chain, *pos);
}
static void *s_next(struct seq_file *m, void *p, loff_t *pos)
{
- struct kmem_cache *cachep = p;
- ++*pos;
- return cachep->next.next == &cache_chain ?
- NULL : list_entry(cachep->next.next, struct kmem_cache, next);
+ return seq_list_next(p, &cache_chain, pos);
}
static void s_stop(struct seq_file *m, void *p)
@@ -4186,7 +4123,7 @@ static void s_stop(struct seq_file *m, void *p)
static int s_show(struct seq_file *m, void *p)
{
- struct kmem_cache *cachep = p;
+ struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
struct slab *slabp;
unsigned long active_objs;
unsigned long num_objs;
@@ -4355,17 +4292,8 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer,
static void *leaks_start(struct seq_file *m, loff_t *pos)
{
- loff_t n = *pos;
- struct list_head *p;
-
mutex_lock(&cache_chain_mutex);
- p = cache_chain.next;
- while (n--) {
- p = p->next;
- if (p == &cache_chain)
- return NULL;
- }
- return list_entry(p, struct kmem_cache, next);
+ return seq_list_start(&cache_chain, *pos);
}
static inline int add_caller(unsigned long *n, unsigned long v)
@@ -4416,7 +4344,7 @@ static void show_symbol(struct seq_file *m, unsigned long address)
{
#ifdef CONFIG_KALLSYMS
unsigned long offset, size;
- char modname[MODULE_NAME_LEN + 1], name[KSYM_NAME_LEN + 1];
+ char modname[MODULE_NAME_LEN], name[KSYM_NAME_LEN];
if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
@@ -4430,7 +4358,7 @@ static void show_symbol(struct seq_file *m, unsigned long address)
static int leaks_show(struct seq_file *m, void *p)
{
- struct kmem_cache *cachep = p;
+ struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
struct slab *slabp;
struct kmem_list3 *l3;
const char *name;
@@ -4511,7 +4439,7 @@ const struct seq_operations slabstats_op = {
*/
size_t ksize(const void *objp)
{
- if (unlikely(objp == NULL))
+ if (unlikely(ZERO_OR_NULL_PTR(objp)))
return 0;
return obj_size(virt_to_cache(objp));
diff --git a/mm/slob.c b/mm/slob.c
index 71976c5d40d3..c89ef116d7aa 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -3,57 +3,159 @@
*
* Matt Mackall <mpm@selenic.com> 12/30/03
*
+ * NUMA support by Paul Mundt, 2007.
+ *
* How SLOB works:
*
* The core of SLOB is a traditional K&R style heap allocator, with
* support for returning aligned objects. The granularity of this
- * allocator is 8 bytes on x86, though it's perhaps possible to reduce
- * this to 4 if it's deemed worth the effort. The slob heap is a
- * singly-linked list of pages from __get_free_page, grown on demand
- * and allocation from the heap is currently first-fit.
+ * allocator is as little as 2 bytes, however typically most architectures
+ * will require 4 bytes on 32-bit and 8 bytes on 64-bit.
+ *
+ * The slob heap is a linked list of pages from alloc_pages(), and
+ * within each page, there is a singly-linked list of free blocks (slob_t).
+ * The heap is grown on demand and allocation from the heap is currently
+ * first-fit.
*
* Above this is an implementation of kmalloc/kfree. Blocks returned
- * from kmalloc are 8-byte aligned and prepended with a 8-byte header.
+ * from kmalloc are prepended with a 4-byte header with the kmalloc size.
* If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
- * __get_free_pages directly so that it can return page-aligned blocks
- * and keeps a linked list of such pages and their orders. These
- * objects are detected in kfree() by their page alignment.
+ * alloc_pages() directly, allocating compound pages so the page order
+ * does not have to be separately tracked, and also stores the exact
+ * allocation size in page->private so that it can be used to accurately
+ * provide ksize(). These objects are detected in kfree() because slob_page()
+ * is false for them.
*
* SLAB is emulated on top of SLOB by simply calling constructors and
- * destructors for every SLAB allocation. Objects are returned with
- * the 8-byte alignment unless the SLAB_HWCACHE_ALIGN flag is
- * set, in which case the low-level allocator will fragment blocks to
- * create the proper alignment. Again, objects of page-size or greater
- * are allocated by calling __get_free_pages. As SLAB objects know
- * their size, no separate size bookkeeping is necessary and there is
- * essentially no allocation space overhead.
+ * destructors for every SLAB allocation. Objects are returned with the
+ * 4-byte alignment unless the SLAB_HWCACHE_ALIGN flag is set, in which
+ * case the low-level allocator will fragment blocks to create the proper
+ * alignment. Again, objects of page-size or greater are allocated by
+ * calling alloc_pages(). As SLAB objects know their size, no separate
+ * size bookkeeping is necessary and there is essentially no allocation
+ * space overhead, and compound pages aren't needed for multi-page
+ * allocations.
+ *
+ * NUMA support in SLOB is fairly simplistic, pushing most of the real
+ * logic down to the page allocator, and simply doing the node accounting
+ * on the upper levels. In the event that a node id is explicitly
+ * provided, alloc_pages_node() with the specified node id is used
+ * instead. The common case (or when the node id isn't explicitly provided)
+ * will default to the current node, as per numa_node_id().
+ *
+ * Node aware pages are still inserted in to the global freelist, and
+ * these are scanned for by matching against the node id encoded in the
+ * page flags. As a result, block allocations that can be satisfied from
+ * the freelist will only be done so on pages residing on the same node,
+ * in order to prevent random node placement.
*/
+#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/cache.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/timer.h>
#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+
+/*
+ * slob_block has a field 'units', which indicates size of block if +ve,
+ * or offset of next block if -ve (in SLOB_UNITs).
+ *
+ * Free blocks of size 1 unit simply contain the offset of the next block.
+ * Those with larger size contain their size in the first SLOB_UNIT of
+ * memory, and the offset of the next free block in the second SLOB_UNIT.
+ */
+#if PAGE_SIZE <= (32767 * 2)
+typedef s16 slobidx_t;
+#else
+typedef s32 slobidx_t;
+#endif
struct slob_block {
- int units;
- struct slob_block *next;
+ slobidx_t units;
};
typedef struct slob_block slob_t;
+/*
+ * We use struct page fields to manage some slob allocation aspects,
+ * however to avoid the horrible mess in include/linux/mm_types.h, we'll
+ * just define our own struct page type variant here.
+ */
+struct slob_page {
+ union {
+ struct {
+ unsigned long flags; /* mandatory */
+ atomic_t _count; /* mandatory */
+ slobidx_t units; /* free units left in page */
+ unsigned long pad[2];
+ slob_t *free; /* first free slob_t in page */
+ struct list_head list; /* linked list of free pages */
+ };
+ struct page page;
+ };
+};
+static inline void struct_slob_page_wrong_size(void)
+{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); }
+
+/*
+ * free_slob_page: call before a slob_page is returned to the page allocator.
+ */
+static inline void free_slob_page(struct slob_page *sp)
+{
+ reset_page_mapcount(&sp->page);
+ sp->page.mapping = NULL;
+}
+
+/*
+ * All (partially) free slob pages go on this list.
+ */
+static LIST_HEAD(free_slob_pages);
+
+/*
+ * slob_page: True for all slob pages (false for bigblock pages)
+ */
+static inline int slob_page(struct slob_page *sp)
+{
+ return test_bit(PG_active, &sp->flags);
+}
+
+static inline void set_slob_page(struct slob_page *sp)
+{
+ __set_bit(PG_active, &sp->flags);
+}
+
+static inline void clear_slob_page(struct slob_page *sp)
+{
+ __clear_bit(PG_active, &sp->flags);
+}
+
+/*
+ * slob_page_free: true for pages on free_slob_pages list.
+ */
+static inline int slob_page_free(struct slob_page *sp)
+{
+ return test_bit(PG_private, &sp->flags);
+}
+
+static inline void set_slob_page_free(struct slob_page *sp)
+{
+ list_add(&sp->list, &free_slob_pages);
+ __set_bit(PG_private, &sp->flags);
+}
+
+static inline void clear_slob_page_free(struct slob_page *sp)
+{
+ list_del(&sp->list);
+ __clear_bit(PG_private, &sp->flags);
+}
+
#define SLOB_UNIT sizeof(slob_t)
#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
#define SLOB_ALIGN L1_CACHE_BYTES
-struct bigblock {
- int order;
- void *pages;
- struct bigblock *next;
-};
-typedef struct bigblock bigblock_t;
-
/*
* struct slob_rcu is inserted at the tail of allocated slob blocks, which
* were created with a SLAB_DESTROY_BY_RCU slab. slob_rcu is used to free
@@ -64,215 +166,321 @@ struct slob_rcu {
int size;
};
-static slob_t arena = { .next = &arena, .units = 1 };
-static slob_t *slobfree = &arena;
-static bigblock_t *bigblocks;
+/*
+ * slob_lock protects all slob allocator structures.
+ */
static DEFINE_SPINLOCK(slob_lock);
-static DEFINE_SPINLOCK(block_lock);
-static void slob_free(void *b, int size);
-static void slob_timer_cbk(void);
+/*
+ * Encode the given size and next info into a free slob block s.
+ */
+static void set_slob(slob_t *s, slobidx_t size, slob_t *next)
+{
+ slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+ slobidx_t offset = next - base;
+
+ if (size > 1) {
+ s[0].units = size;
+ s[1].units = offset;
+ } else
+ s[0].units = -offset;
+}
+
+/*
+ * Return the size of a slob block.
+ */
+static slobidx_t slob_units(slob_t *s)
+{
+ if (s->units > 0)
+ return s->units;
+ return 1;
+}
+
+/*
+ * Return the next free slob block pointer after this one.
+ */
+static slob_t *slob_next(slob_t *s)
+{
+ slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+ slobidx_t next;
+
+ if (s[0].units < 0)
+ next = -s[0].units;
+ else
+ next = s[1].units;
+ return base+next;
+}
+/*
+ * Returns true if s is the last free block in its page.
+ */
+static int slob_last(slob_t *s)
+{
+ return !((unsigned long)slob_next(s) & ~PAGE_MASK);
+}
-static void *slob_alloc(size_t size, gfp_t gfp, int align)
+static void *slob_new_page(gfp_t gfp, int order, int node)
+{
+ void *page;
+
+#ifdef CONFIG_NUMA
+ if (node != -1)
+ page = alloc_pages_node(node, gfp, order);
+ else
+#endif
+ page = alloc_pages(gfp, order);
+
+ if (!page)
+ return NULL;
+
+ return page_address(page);
+}
+
+/*
+ * Allocate a slob block within a given slob_page sp.
+ */
+static void *slob_page_alloc(struct slob_page *sp, size_t size, int align)
{
slob_t *prev, *cur, *aligned = 0;
int delta = 0, units = SLOB_UNITS(size);
- unsigned long flags;
- spin_lock_irqsave(&slob_lock, flags);
- prev = slobfree;
- for (cur = prev->next; ; prev = cur, cur = cur->next) {
+ for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) {
+ slobidx_t avail = slob_units(cur);
+
if (align) {
aligned = (slob_t *)ALIGN((unsigned long)cur, align);
delta = aligned - cur;
}
- if (cur->units >= units + delta) { /* room enough? */
+ if (avail >= units + delta) { /* room enough? */
+ slob_t *next;
+
if (delta) { /* need to fragment head to align? */
- aligned->units = cur->units - delta;
- aligned->next = cur->next;
- cur->next = aligned;
- cur->units = delta;
+ next = slob_next(cur);
+ set_slob(aligned, avail - delta, next);
+ set_slob(cur, delta, aligned);
prev = cur;
cur = aligned;
+ avail = slob_units(cur);
}
- if (cur->units == units) /* exact fit? */
- prev->next = cur->next; /* unlink */
- else { /* fragment */
- prev->next = cur + units;
- prev->next->units = cur->units - units;
- prev->next->next = cur->next;
- cur->units = units;
+ next = slob_next(cur);
+ if (avail == units) { /* exact fit? unlink. */
+ if (prev)
+ set_slob(prev, slob_units(prev), next);
+ else
+ sp->free = next;
+ } else { /* fragment */
+ if (prev)
+ set_slob(prev, slob_units(prev), cur + units);
+ else
+ sp->free = cur + units;
+ set_slob(cur + units, avail - units, next);
}
- slobfree = prev;
- spin_unlock_irqrestore(&slob_lock, flags);
+ sp->units -= units;
+ if (!sp->units)
+ clear_slob_page_free(sp);
return cur;
}
- if (cur == slobfree) {
- spin_unlock_irqrestore(&slob_lock, flags);
-
- if (size == PAGE_SIZE) /* trying to shrink arena? */
- return 0;
+ if (slob_last(cur))
+ return NULL;
+ }
+}
- cur = (slob_t *)__get_free_page(gfp);
- if (!cur)
- return 0;
+/*
+ * slob_alloc: entry point into the slob allocator.
+ */
+static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
+{
+ struct slob_page *sp;
+ slob_t *b = NULL;
+ unsigned long flags;
- slob_free(cur, PAGE_SIZE);
- spin_lock_irqsave(&slob_lock, flags);
- cur = slobfree;
+ spin_lock_irqsave(&slob_lock, flags);
+ /* Iterate through each partially free page, try to find room */
+ list_for_each_entry(sp, &free_slob_pages, list) {
+#ifdef CONFIG_NUMA
+ /*
+ * If there's a node specification, search for a partial
+ * page with a matching node id in the freelist.
+ */
+ if (node != -1 && page_to_nid(&sp->page) != node)
+ continue;
+#endif
+
+ if (sp->units >= SLOB_UNITS(size)) {
+ b = slob_page_alloc(sp, size, align);
+ if (b)
+ break;
}
}
+ spin_unlock_irqrestore(&slob_lock, flags);
+
+ /* Not enough space: must allocate a new page */
+ if (!b) {
+ b = slob_new_page(gfp, 0, node);
+ if (!b)
+ return 0;
+ sp = (struct slob_page *)virt_to_page(b);
+ set_slob_page(sp);
+
+ spin_lock_irqsave(&slob_lock, flags);
+ sp->units = SLOB_UNITS(PAGE_SIZE);
+ sp->free = b;
+ INIT_LIST_HEAD(&sp->list);
+ set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
+ set_slob_page_free(sp);
+ b = slob_page_alloc(sp, size, align);
+ BUG_ON(!b);
+ spin_unlock_irqrestore(&slob_lock, flags);
+ }
+ if (unlikely((gfp & __GFP_ZERO) && b))
+ memset(b, 0, size);
+ return b;
}
+/*
+ * slob_free: entry point into the slob allocator.
+ */
static void slob_free(void *block, int size)
{
- slob_t *cur, *b = (slob_t *)block;
+ struct slob_page *sp;
+ slob_t *prev, *next, *b = (slob_t *)block;
+ slobidx_t units;
unsigned long flags;
- if (!block)
+ if (ZERO_OR_NULL_PTR(block))
return;
+ BUG_ON(!size);
- if (size)
- b->units = SLOB_UNITS(size);
+ sp = (struct slob_page *)virt_to_page(block);
+ units = SLOB_UNITS(size);
- /* Find reinsertion point */
spin_lock_irqsave(&slob_lock, flags);
- for (cur = slobfree; !(b > cur && b < cur->next); cur = cur->next)
- if (cur >= cur->next && (b > cur || b < cur->next))
- break;
-
- if (b + b->units == cur->next) {
- b->units += cur->next->units;
- b->next = cur->next->next;
- } else
- b->next = cur->next;
-
- if (cur + cur->units == b) {
- cur->units += b->units;
- cur->next = b->next;
- } else
- cur->next = b;
- slobfree = cur;
-
- spin_unlock_irqrestore(&slob_lock, flags);
-}
-
-void *__kmalloc(size_t size, gfp_t gfp)
-{
- slob_t *m;
- bigblock_t *bb;
- unsigned long flags;
+ if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
+ /* Go directly to page allocator. Do not pass slob allocator */
+ if (slob_page_free(sp))
+ clear_slob_page_free(sp);
+ clear_slob_page(sp);
+ free_slob_page(sp);
+ free_page((unsigned long)b);
+ goto out;
+ }
- if (size < PAGE_SIZE - SLOB_UNIT) {
- m = slob_alloc(size + SLOB_UNIT, gfp, 0);
- return m ? (void *)(m + 1) : 0;
+ if (!slob_page_free(sp)) {
+ /* This slob page is about to become partially free. Easy! */
+ sp->units = units;
+ sp->free = b;
+ set_slob(b, units,
+ (void *)((unsigned long)(b +
+ SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
+ set_slob_page_free(sp);
+ goto out;
}
- bb = slob_alloc(sizeof(bigblock_t), gfp, 0);
- if (!bb)
- return 0;
+ /*
+ * Otherwise the page is already partially free, so find reinsertion
+ * point.
+ */
+ sp->units += units;
- bb->order = get_order(size);
- bb->pages = (void *)__get_free_pages(gfp, bb->order);
+ if (b < sp->free) {
+ set_slob(b, units, sp->free);
+ sp->free = b;
+ } else {
+ prev = sp->free;
+ next = slob_next(prev);
+ while (b > next) {
+ prev = next;
+ next = slob_next(prev);
+ }
- if (bb->pages) {
- spin_lock_irqsave(&block_lock, flags);
- bb->next = bigblocks;
- bigblocks = bb;
- spin_unlock_irqrestore(&block_lock, flags);
- return bb->pages;
+ if (!slob_last(prev) && b + units == next) {
+ units += slob_units(next);
+ set_slob(b, units, slob_next(next));
+ } else
+ set_slob(b, units, next);
+
+ if (prev + slob_units(prev) == b) {
+ units = slob_units(b) + slob_units(prev);
+ set_slob(prev, units, slob_next(b));
+ } else
+ set_slob(prev, slob_units(prev), b);
}
-
- slob_free(bb, sizeof(bigblock_t));
- return 0;
+out:
+ spin_unlock_irqrestore(&slob_lock, flags);
}
-EXPORT_SYMBOL(__kmalloc);
-/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- *
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes. If @p is %NULL, krealloc()
- * behaves exactly like kmalloc(). If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
+/*
+ * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
*/
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
+
+#ifndef ARCH_KMALLOC_MINALIGN
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long)
+#endif
+
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
+#endif
+
+void *__kmalloc_node(size_t size, gfp_t gfp, int node)
{
- void *ret;
+ unsigned int *m;
+ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
- if (unlikely(!p))
- return kmalloc_track_caller(new_size, flags);
+ if (size < PAGE_SIZE - align) {
+ if (!size)
+ return ZERO_SIZE_PTR;
- if (unlikely(!new_size)) {
- kfree(p);
- return NULL;
- }
+ m = slob_alloc(size + align, gfp, align, node);
+ if (m)
+ *m = size;
+ return (void *)m + align;
+ } else {
+ void *ret;
- ret = kmalloc_track_caller(new_size, flags);
- if (ret) {
- memcpy(ret, p, min(new_size, ksize(p)));
- kfree(p);
+ ret = slob_new_page(gfp | __GFP_COMP, get_order(size), node);
+ if (ret) {
+ struct page *page;
+ page = virt_to_page(ret);
+ page->private = size;
+ }
+ return ret;
}
- return ret;
}
-EXPORT_SYMBOL(krealloc);
+EXPORT_SYMBOL(__kmalloc_node);
void kfree(const void *block)
{
- bigblock_t *bb, **last = &bigblocks;
- unsigned long flags;
+ struct slob_page *sp;
- if (!block)
+ if (ZERO_OR_NULL_PTR(block))
return;
- if (!((unsigned long)block & (PAGE_SIZE-1))) {
- /* might be on the big block list */
- spin_lock_irqsave(&block_lock, flags);
- for (bb = bigblocks; bb; last = &bb->next, bb = bb->next) {
- if (bb->pages == block) {
- *last = bb->next;
- spin_unlock_irqrestore(&block_lock, flags);
- free_pages((unsigned long)block, bb->order);
- slob_free(bb, sizeof(bigblock_t));
- return;
- }
- }
- spin_unlock_irqrestore(&block_lock, flags);
- }
-
- slob_free((slob_t *)block - 1, 0);
- return;
+ sp = (struct slob_page *)virt_to_page(block);
+ if (slob_page(sp)) {
+ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+ unsigned int *m = (unsigned int *)(block - align);
+ slob_free(m, *m + align);
+ } else
+ put_page(&sp->page);
}
-
EXPORT_SYMBOL(kfree);
+/* can't use ksize for kmem_cache_alloc memory, only kmalloc */
size_t ksize(const void *block)
{
- bigblock_t *bb;
- unsigned long flags;
+ struct slob_page *sp;
- if (!block)
+ if (ZERO_OR_NULL_PTR(block))
return 0;
- if (!((unsigned long)block & (PAGE_SIZE-1))) {
- spin_lock_irqsave(&block_lock, flags);
- for (bb = bigblocks; bb; bb = bb->next)
- if (bb->pages == block) {
- spin_unlock_irqrestore(&slob_lock, flags);
- return PAGE_SIZE << bb->order;
- }
- spin_unlock_irqrestore(&block_lock, flags);
- }
-
- return ((slob_t *)block - 1)->units * SLOB_UNIT;
+ sp = (struct slob_page *)virt_to_page(block);
+ if (slob_page(sp))
+ return ((slob_t *)block - 1)->units + SLOB_UNIT;
+ else
+ return sp->page.private;
}
struct kmem_cache {
@@ -289,7 +497,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
{
struct kmem_cache *c;
- c = slob_alloc(sizeof(struct kmem_cache), flags, 0);
+ c = slob_alloc(sizeof(struct kmem_cache), flags, 0, -1);
if (c) {
c->name = name;
@@ -302,6 +510,8 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
c->ctor = ctor;
/* ignore alignment unless it's forced */
c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+ if (c->align < ARCH_SLAB_MINALIGN)
+ c->align = ARCH_SLAB_MINALIGN;
if (c->align < align)
c->align = align;
} else if (flags & SLAB_PANIC)
@@ -317,31 +527,21 @@ void kmem_cache_destroy(struct kmem_cache *c)
}
EXPORT_SYMBOL(kmem_cache_destroy);
-void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)
+void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
{
void *b;
if (c->size < PAGE_SIZE)
- b = slob_alloc(c->size, flags, c->align);
+ b = slob_alloc(c->size, flags, c->align, node);
else
- b = (void *)__get_free_pages(flags, get_order(c->size));
+ b = slob_new_page(flags, get_order(c->size), node);
if (c->ctor)
c->ctor(b, c, 0);
return b;
}
-EXPORT_SYMBOL(kmem_cache_alloc);
-
-void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t flags)
-{
- void *ret = kmem_cache_alloc(c, flags);
- if (ret)
- memset(ret, 0, c->size);
-
- return ret;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
+EXPORT_SYMBOL(kmem_cache_alloc_node);
static void __kmem_cache_free(void *b, int size)
{
@@ -385,9 +585,6 @@ const char *kmem_cache_name(struct kmem_cache *c)
}
EXPORT_SYMBOL(kmem_cache_name);
-static struct timer_list slob_timer = TIMER_INITIALIZER(
- (void (*)(unsigned long))slob_timer_cbk, 0, 0);
-
int kmem_cache_shrink(struct kmem_cache *d)
{
return 0;
@@ -399,17 +596,14 @@ int kmem_ptr_validate(struct kmem_cache *a, const void *b)
return 0;
}
-void __init kmem_cache_init(void)
+static unsigned int slob_ready __read_mostly;
+
+int slab_is_available(void)
{
- slob_timer_cbk();
+ return slob_ready;
}
-static void slob_timer_cbk(void)
+void __init kmem_cache_init(void)
{
- void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
-
- if (p)
- free_page((unsigned long)p);
-
- mod_timer(&slob_timer, jiffies + HZ);
+ slob_ready = 1;
}
diff --git a/mm/slub.c b/mm/slub.c
index e0cf6213abc0..52a4f44be394 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -205,6 +205,11 @@ static inline void ClearSlabDebug(struct page *page)
#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
#endif
+/*
+ * The page->inuse field is 16 bit thus we have this limitation
+ */
+#define MAX_OBJECTS_PER_SLAB 65535
+
/* Internal SLUB flags */
#define __OBJECT_POISON 0x80000000 /* Poison object */
@@ -228,7 +233,7 @@ static enum {
/* A list of all slab caches on the system */
static DECLARE_RWSEM(slub_lock);
-LIST_HEAD(slab_caches);
+static LIST_HEAD(slab_caches);
/*
* Tracking user of a slab.
@@ -247,9 +252,10 @@ static int sysfs_slab_add(struct kmem_cache *);
static int sysfs_slab_alias(struct kmem_cache *, const char *);
static void sysfs_slab_remove(struct kmem_cache *);
#else
-static int sysfs_slab_add(struct kmem_cache *s) { return 0; }
-static int sysfs_slab_alias(struct kmem_cache *s, const char *p) { return 0; }
-static void sysfs_slab_remove(struct kmem_cache *s) {}
+static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
+ { return 0; }
+static inline void sysfs_slab_remove(struct kmem_cache *s) {}
#endif
/********************************************************************
@@ -323,7 +329,11 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
/*
* Debug settings:
*/
+#ifdef CONFIG_SLUB_DEBUG_ON
+static int slub_debug = DEBUG_DEFAULT_FLAGS;
+#else
static int slub_debug;
+#endif
static char *slub_debug_slabs;
@@ -340,7 +350,7 @@ static void print_section(char *text, u8 *addr, unsigned int length)
for (i = 0; i < length; i++) {
if (newline) {
- printk(KERN_ERR "%10s 0x%p: ", text, addr + i);
+ printk(KERN_ERR "%8s 0x%p: ", text, addr + i);
newline = 0;
}
printk(" %02x", addr[i]);
@@ -397,10 +407,11 @@ static void set_track(struct kmem_cache *s, void *object,
static void init_tracking(struct kmem_cache *s, void *object)
{
- if (s->flags & SLAB_STORE_USER) {
- set_track(s, object, TRACK_FREE, NULL);
- set_track(s, object, TRACK_ALLOC, NULL);
- }
+ if (!(s->flags & SLAB_STORE_USER))
+ return;
+
+ set_track(s, object, TRACK_FREE, NULL);
+ set_track(s, object, TRACK_ALLOC, NULL);
}
static void print_track(const char *s, struct track *t)
@@ -408,65 +419,106 @@ static void print_track(const char *s, struct track *t)
if (!t->addr)
return;
- printk(KERN_ERR "%s: ", s);
+ printk(KERN_ERR "INFO: %s in ", s);
__print_symbol("%s", (unsigned long)t->addr);
- printk(" jiffies_ago=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+ printk(" age=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+}
+
+static void print_tracking(struct kmem_cache *s, void *object)
+{
+ if (!(s->flags & SLAB_STORE_USER))
+ return;
+
+ print_track("Allocated", get_track(s, object, TRACK_ALLOC));
+ print_track("Freed", get_track(s, object, TRACK_FREE));
+}
+
+static void print_page_info(struct page *page)
+{
+ printk(KERN_ERR "INFO: Slab 0x%p used=%u fp=0x%p flags=0x%04lx\n",
+ page, page->inuse, page->freelist, page->flags);
+
+}
+
+static void slab_bug(struct kmem_cache *s, char *fmt, ...)
+{
+ va_list args;
+ char buf[100];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ printk(KERN_ERR "========================================"
+ "=====================================\n");
+ printk(KERN_ERR "BUG %s: %s\n", s->name, buf);
+ printk(KERN_ERR "----------------------------------------"
+ "-------------------------------------\n\n");
}
-static void print_trailer(struct kmem_cache *s, u8 *p)
+static void slab_fix(struct kmem_cache *s, char *fmt, ...)
+{
+ va_list args;
+ char buf[100];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ printk(KERN_ERR "FIX %s: %s\n", s->name, buf);
+}
+
+static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
{
unsigned int off; /* Offset of last byte */
+ u8 *addr = page_address(page);
+
+ print_tracking(s, p);
+
+ print_page_info(page);
+
+ printk(KERN_ERR "INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
+ p, p - addr, get_freepointer(s, p));
+
+ if (p > addr + 16)
+ print_section("Bytes b4", p - 16, 16);
+
+ print_section("Object", p, min(s->objsize, 128));
if (s->flags & SLAB_RED_ZONE)
print_section("Redzone", p + s->objsize,
s->inuse - s->objsize);
- printk(KERN_ERR "FreePointer 0x%p -> 0x%p\n",
- p + s->offset,
- get_freepointer(s, p));
-
if (s->offset)
off = s->offset + sizeof(void *);
else
off = s->inuse;
- if (s->flags & SLAB_STORE_USER) {
- print_track("Last alloc", get_track(s, p, TRACK_ALLOC));
- print_track("Last free ", get_track(s, p, TRACK_FREE));
+ if (s->flags & SLAB_STORE_USER)
off += 2 * sizeof(struct track);
- }
if (off != s->size)
/* Beginning of the filler is the free pointer */
- print_section("Filler", p + off, s->size - off);
+ print_section("Padding", p + off, s->size - off);
+
+ dump_stack();
}
static void object_err(struct kmem_cache *s, struct page *page,
u8 *object, char *reason)
{
- u8 *addr = page_address(page);
-
- printk(KERN_ERR "*** SLUB %s: %s@0x%p slab 0x%p\n",
- s->name, reason, object, page);
- printk(KERN_ERR " offset=%tu flags=0x%04lx inuse=%u freelist=0x%p\n",
- object - addr, page->flags, page->inuse, page->freelist);
- if (object > addr + 16)
- print_section("Bytes b4", object - 16, 16);
- print_section("Object", object, min(s->objsize, 128));
- print_trailer(s, object);
- dump_stack();
+ slab_bug(s, reason);
+ print_trailer(s, page, object);
}
-static void slab_err(struct kmem_cache *s, struct page *page, char *reason, ...)
+static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
{
va_list args;
char buf[100];
- va_start(args, reason);
- vsnprintf(buf, sizeof(buf), reason, args);
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- printk(KERN_ERR "*** SLUB %s: %s in slab @0x%p\n", s->name, buf,
- page);
+ slab_bug(s, fmt);
+ print_page_info(page);
dump_stack();
}
@@ -485,15 +537,46 @@ static void init_object(struct kmem_cache *s, void *object, int active)
s->inuse - s->objsize);
}
-static int check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
{
while (bytes) {
if (*start != (u8)value)
- return 0;
+ return start;
start++;
bytes--;
}
- return 1;
+ return NULL;
+}
+
+static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
+ void *from, void *to)
+{
+ slab_fix(s, "Restoring 0x%p-0x%p=0x%x\n", from, to - 1, data);
+ memset(from, data, to - from);
+}
+
+static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
+ u8 *object, char *what,
+ u8* start, unsigned int value, unsigned int bytes)
+{
+ u8 *fault;
+ u8 *end;
+
+ fault = check_bytes(start, value, bytes);
+ if (!fault)
+ return 1;
+
+ end = start + bytes;
+ while (end > fault && end[-1] == value)
+ end--;
+
+ slab_bug(s, "%s overwritten", what);
+ printk(KERN_ERR "INFO: 0x%p-0x%p. First byte 0x%x instead of 0x%x\n",
+ fault, end - 1, fault[0], value);
+ print_trailer(s, page, object);
+
+ restore_bytes(s, what, value, fault, end);
+ return 0;
}
/*
@@ -534,14 +617,6 @@ static int check_bytes(u8 *start, unsigned int value, unsigned int bytes)
* may be used with merged slabcaches.
*/
-static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
- void *from, void *to)
-{
- printk(KERN_ERR "@@@ SLUB %s: Restoring %s (0x%x) from 0x%p-0x%p\n",
- s->name, message, data, from, to - 1);
- memset(from, data, to - from);
-}
-
static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
{
unsigned long off = s->inuse; /* The end of info */
@@ -557,39 +632,39 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
if (s->size == off)
return 1;
- if (check_bytes(p + off, POISON_INUSE, s->size - off))
- return 1;
-
- object_err(s, page, p, "Object padding check fails");
-
- /*
- * Restore padding
- */
- restore_bytes(s, "object padding", POISON_INUSE, p + off, p + s->size);
- return 0;
+ return check_bytes_and_report(s, page, p, "Object padding",
+ p + off, POISON_INUSE, s->size - off);
}
static int slab_pad_check(struct kmem_cache *s, struct page *page)
{
- u8 *p;
- int length, remainder;
+ u8 *start;
+ u8 *fault;
+ u8 *end;
+ int length;
+ int remainder;
if (!(s->flags & SLAB_POISON))
return 1;
- p = page_address(page);
+ start = page_address(page);
+ end = start + (PAGE_SIZE << s->order);
length = s->objects * s->size;
- remainder = (PAGE_SIZE << s->order) - length;
+ remainder = end - (start + length);
if (!remainder)
return 1;
- if (!check_bytes(p + length, POISON_INUSE, remainder)) {
- slab_err(s, page, "Padding check failed");
- restore_bytes(s, "slab padding", POISON_INUSE, p + length,
- p + length + remainder);
- return 0;
- }
- return 1;
+ fault = check_bytes(start + length, POISON_INUSE, remainder);
+ if (!fault)
+ return 1;
+ while (end > fault && end[-1] == POISON_INUSE)
+ end--;
+
+ slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
+ print_section("Padding", start, length);
+
+ restore_bytes(s, "slab padding", POISON_INUSE, start, end);
+ return 0;
}
static int check_object(struct kmem_cache *s, struct page *page,
@@ -602,41 +677,22 @@ static int check_object(struct kmem_cache *s, struct page *page,
unsigned int red =
active ? SLUB_RED_ACTIVE : SLUB_RED_INACTIVE;
- if (!check_bytes(endobject, red, s->inuse - s->objsize)) {
- object_err(s, page, object,
- active ? "Redzone Active" : "Redzone Inactive");
- restore_bytes(s, "redzone", red,
- endobject, object + s->inuse);
+ if (!check_bytes_and_report(s, page, object, "Redzone",
+ endobject, red, s->inuse - s->objsize))
return 0;
- }
} else {
- if ((s->flags & SLAB_POISON) && s->objsize < s->inuse &&
- !check_bytes(endobject, POISON_INUSE,
- s->inuse - s->objsize)) {
- object_err(s, page, p, "Alignment padding check fails");
- /*
- * Fix it so that there will not be another report.
- *
- * Hmmm... We may be corrupting an object that now expects
- * to be longer than allowed.
- */
- restore_bytes(s, "alignment padding", POISON_INUSE,
- endobject, object + s->inuse);
- }
+ if ((s->flags & SLAB_POISON) && s->objsize < s->inuse)
+ check_bytes_and_report(s, page, p, "Alignment padding", endobject,
+ POISON_INUSE, s->inuse - s->objsize);
}
if (s->flags & SLAB_POISON) {
if (!active && (s->flags & __OBJECT_POISON) &&
- (!check_bytes(p, POISON_FREE, s->objsize - 1) ||
- p[s->objsize - 1] != POISON_END)) {
-
- object_err(s, page, p, "Poison check failed");
- restore_bytes(s, "Poison", POISON_FREE,
- p, p + s->objsize -1);
- restore_bytes(s, "Poison", POISON_END,
- p + s->objsize - 1, p + s->objsize);
+ (!check_bytes_and_report(s, page, p, "Poison", p,
+ POISON_FREE, s->objsize - 1) ||
+ !check_bytes_and_report(s, page, p, "Poison",
+ p + s->objsize -1, POISON_END, 1)))
return 0;
- }
/*
* check_pad_bytes cleans up on its own.
*/
@@ -669,25 +725,17 @@ static int check_slab(struct kmem_cache *s, struct page *page)
VM_BUG_ON(!irqs_disabled());
if (!PageSlab(page)) {
- slab_err(s, page, "Not a valid slab page flags=%lx "
- "mapping=0x%p count=%d", page->flags, page->mapping,
- page_count(page));
+ slab_err(s, page, "Not a valid slab page");
return 0;
}
if (page->offset * sizeof(void *) != s->offset) {
- slab_err(s, page, "Corrupted offset %lu flags=0x%lx "
- "mapping=0x%p count=%d",
- (unsigned long)(page->offset * sizeof(void *)),
- page->flags,
- page->mapping,
- page_count(page));
+ slab_err(s, page, "Corrupted offset %lu",
+ (unsigned long)(page->offset * sizeof(void *)));
return 0;
}
if (page->inuse > s->objects) {
- slab_err(s, page, "inuse %u > max %u @0x%p flags=%lx "
- "mapping=0x%p count=%d",
- s->name, page->inuse, s->objects, page->flags,
- page->mapping, page_count(page));
+ slab_err(s, page, "inuse %u > max %u",
+ s->name, page->inuse, s->objects);
return 0;
}
/* Slab_pad_check fixes things up after itself */
@@ -715,13 +763,10 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
set_freepointer(s, object, NULL);
break;
} else {
- slab_err(s, page, "Freepointer 0x%p corrupt",
- fp);
+ slab_err(s, page, "Freepointer corrupt");
page->freelist = NULL;
page->inuse = s->objects;
- printk(KERN_ERR "@@@ SLUB %s: Freelist "
- "cleared. Slab 0x%p\n",
- s->name, page);
+ slab_fix(s, "Freelist cleared");
return 0;
}
break;
@@ -733,11 +778,9 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
if (page->inuse != s->objects - nr) {
slab_err(s, page, "Wrong object count. Counter is %d but "
- "counted were %d", s, page, page->inuse,
- s->objects - nr);
+ "counted were %d", page->inuse, s->objects - nr);
page->inuse = s->objects - nr;
- printk(KERN_ERR "@@@ SLUB %s: Object count adjusted. "
- "Slab @0x%p\n", s->name, page);
+ slab_fix(s, "Object count adjusted.");
}
return search == NULL;
}
@@ -799,7 +842,7 @@ static int alloc_debug_processing(struct kmem_cache *s, struct page *page,
goto bad;
if (object && !on_freelist(s, page, object)) {
- slab_err(s, page, "Object 0x%p already allocated", object);
+ object_err(s, page, object, "Object already allocated");
goto bad;
}
@@ -825,8 +868,7 @@ bad:
* to avoid issues in the future. Marking all objects
* as used avoids touching the remaining objects.
*/
- printk(KERN_ERR "@@@ SLUB: %s slab 0x%p. Marking all objects used.\n",
- s->name, page);
+ slab_fix(s, "Marking all objects used");
page->inuse = s->objects;
page->freelist = NULL;
/* Fix up fields that may be corrupted */
@@ -847,7 +889,7 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
}
if (on_freelist(s, page, object)) {
- slab_err(s, page, "Object 0x%p already free", object);
+ object_err(s, page, object, "Object already free");
goto fail;
}
@@ -866,8 +908,8 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
dump_stack();
}
else
- slab_err(s, page, "object at 0x%p belongs "
- "to slab %s", object, page->slab->name);
+ object_err(s, page, object,
+ "page slab pointer corrupt.");
goto fail;
}
@@ -881,45 +923,63 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
return 1;
fail:
- printk(KERN_ERR "@@@ SLUB: %s slab 0x%p object at 0x%p not freed.\n",
- s->name, page, object);
+ slab_fix(s, "Object at 0x%p not freed", object);
return 0;
}
static int __init setup_slub_debug(char *str)
{
- if (!str || *str != '=')
- slub_debug = DEBUG_DEFAULT_FLAGS;
- else {
- str++;
- if (*str == 0 || *str == ',')
- slub_debug = DEBUG_DEFAULT_FLAGS;
- else
- for( ;*str && *str != ','; str++)
- switch (*str) {
- case 'f' : case 'F' :
- slub_debug |= SLAB_DEBUG_FREE;
- break;
- case 'z' : case 'Z' :
- slub_debug |= SLAB_RED_ZONE;
- break;
- case 'p' : case 'P' :
- slub_debug |= SLAB_POISON;
- break;
- case 'u' : case 'U' :
- slub_debug |= SLAB_STORE_USER;
- break;
- case 't' : case 'T' :
- slub_debug |= SLAB_TRACE;
- break;
- default:
- printk(KERN_ERR "slub_debug option '%c' "
- "unknown. skipped\n",*str);
- }
+ slub_debug = DEBUG_DEFAULT_FLAGS;
+ if (*str++ != '=' || !*str)
+ /*
+ * No options specified. Switch on full debugging.
+ */
+ goto out;
+
+ if (*str == ',')
+ /*
+ * No options but restriction on slabs. This means full
+ * debugging for slabs matching a pattern.
+ */
+ goto check_slabs;
+
+ slub_debug = 0;
+ if (*str == '-')
+ /*
+ * Switch off all debugging measures.
+ */
+ goto out;
+
+ /*
+ * Determine which debug features should be switched on
+ */
+ for ( ;*str && *str != ','; str++) {
+ switch (tolower(*str)) {
+ case 'f':
+ slub_debug |= SLAB_DEBUG_FREE;
+ break;
+ case 'z':
+ slub_debug |= SLAB_RED_ZONE;
+ break;
+ case 'p':
+ slub_debug |= SLAB_POISON;
+ break;
+ case 'u':
+ slub_debug |= SLAB_STORE_USER;
+ break;
+ case 't':
+ slub_debug |= SLAB_TRACE;
+ break;
+ default:
+ printk(KERN_ERR "slub_debug option '%c' "
+ "unknown. skipped\n",*str);
+ }
}
+check_slabs:
if (*str == ',')
slub_debug_slabs = str + 1;
+out:
return 1;
}
@@ -1018,7 +1078,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
void *last;
void *p;
- BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK));
+ BUG_ON(flags & ~(GFP_DMA | __GFP_ZERO | GFP_LEVEL_MASK));
if (flags & __GFP_WAIT)
local_irq_enable();
@@ -1336,7 +1396,7 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, int cpu)
unfreeze_slab(s, page);
}
-static void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
+static inline void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
{
slab_lock(page);
deactivate_slab(s, page, cpu);
@@ -1346,7 +1406,7 @@ static void flush_slab(struct kmem_cache *s, struct page *page, int cpu)
* Flush cpu slab.
* Called from IPI handler with interrupts disabled.
*/
-static void __flush_cpu_slab(struct kmem_cache *s, int cpu)
+static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu)
{
struct page *page = s->cpu_slab[cpu];
@@ -1481,7 +1541,7 @@ debug:
* Otherwise we can simply pick the next object from the lockless free list.
*/
static void __always_inline *slab_alloc(struct kmem_cache *s,
- gfp_t gfpflags, int node, void *addr)
+ gfp_t gfpflags, int node, void *addr)
{
struct page *page;
void **object;
@@ -1499,6 +1559,10 @@ static void __always_inline *slab_alloc(struct kmem_cache *s,
page->lockless_freelist = object[page->offset];
}
local_irq_restore(flags);
+
+ if (unlikely((gfpflags & __GFP_ZERO) && object))
+ memset(object, 0, s->objsize);
+
return object;
}
@@ -1682,8 +1746,17 @@ static inline int slab_order(int size, int min_objects,
{
int order;
int rem;
+ int min_order = slub_min_order;
+
+ /*
+ * If we would create too many object per slab then reduce
+ * the slab order even if it goes below slub_min_order.
+ */
+ while (min_order > 0 &&
+ (PAGE_SIZE << min_order) >= MAX_OBJECTS_PER_SLAB * size)
+ min_order--;
- for (order = max(slub_min_order,
+ for (order = max(min_order,
fls(min_objects * size - 1) - PAGE_SHIFT);
order <= max_order; order++) {
@@ -1697,6 +1770,9 @@ static inline int slab_order(int size, int min_objects,
if (rem <= slab_size / fract_leftover)
break;
+ /* If the next size is too high then exit now */
+ if (slab_size * 2 >= MAX_OBJECTS_PER_SLAB * size)
+ break;
}
return order;
@@ -1777,7 +1853,9 @@ static void init_kmem_cache_node(struct kmem_cache_node *n)
atomic_long_set(&n->nr_slabs, 0);
spin_lock_init(&n->list_lock);
INIT_LIST_HEAD(&n->partial);
+#ifdef CONFIG_SLUB_DEBUG
INIT_LIST_HEAD(&n->full);
+#endif
}
#ifdef CONFIG_NUMA
@@ -1805,7 +1883,10 @@ static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflag
page->freelist = get_freepointer(kmalloc_caches, n);
page->inuse++;
kmalloc_caches->node[node] = n;
- setup_object_debug(kmalloc_caches, page, n);
+#ifdef CONFIG_SLUB_DEBUG
+ init_object(kmalloc_caches, n, 1);
+ init_tracking(kmalloc_caches, n);
+#endif
init_kmem_cache_node(n);
atomic_long_inc(&n->nr_slabs);
add_partial(n, page);
@@ -1983,7 +2064,7 @@ static int calculate_sizes(struct kmem_cache *s)
* The page->inuse field is only 16 bit wide! So we cannot have
* more than 64k objects per slab.
*/
- if (!s->objects || s->objects > 65535)
+ if (!s->objects || s->objects > MAX_OBJECTS_PER_SLAB)
return 0;
return 1;
@@ -2087,7 +2168,7 @@ static int free_list(struct kmem_cache *s, struct kmem_cache_node *n,
/*
* Release all resources used by a slab cache.
*/
-static int kmem_cache_close(struct kmem_cache *s)
+static inline int kmem_cache_close(struct kmem_cache *s)
{
int node;
@@ -2115,12 +2196,13 @@ void kmem_cache_destroy(struct kmem_cache *s)
s->refcount--;
if (!s->refcount) {
list_del(&s->list);
+ up_write(&slub_lock);
if (kmem_cache_close(s))
WARN_ON(1);
sysfs_slab_remove(s);
kfree(s);
- }
- up_write(&slub_lock);
+ } else
+ up_write(&slub_lock);
}
EXPORT_SYMBOL(kmem_cache_destroy);
@@ -2193,47 +2275,92 @@ panic:
panic("Creation of kmalloc slab %s size=%d failed.\n", name, size);
}
-static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+#ifdef CONFIG_ZONE_DMA
+static noinline struct kmem_cache *dma_kmalloc_cache(int index, gfp_t flags)
{
- int index = kmalloc_index(size);
+ struct kmem_cache *s;
+ struct kmem_cache *x;
+ char *text;
+ size_t realsize;
- if (!index)
- return NULL;
+ s = kmalloc_caches_dma[index];
+ if (s)
+ return s;
- /* Allocation too large? */
- BUG_ON(index < 0);
+ /* Dynamically create dma cache */
+ x = kmalloc(kmem_size, flags & ~SLUB_DMA);
+ if (!x)
+ panic("Unable to allocate memory for dma cache\n");
-#ifdef CONFIG_ZONE_DMA
- if ((flags & SLUB_DMA)) {
- struct kmem_cache *s;
- struct kmem_cache *x;
- char *text;
- size_t realsize;
-
- s = kmalloc_caches_dma[index];
- if (s)
- return s;
+ realsize = kmalloc_caches[index].objsize;
+ text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
+ (unsigned int)realsize);
+ s = create_kmalloc_cache(x, text, realsize, flags);
+ down_write(&slub_lock);
+ if (!kmalloc_caches_dma[index]) {
+ kmalloc_caches_dma[index] = s;
+ up_write(&slub_lock);
+ return s;
+ }
+ up_write(&slub_lock);
+ kmem_cache_destroy(s);
+ return kmalloc_caches_dma[index];
+}
+#endif
- /* Dynamically create dma cache */
- x = kmalloc(kmem_size, flags & ~SLUB_DMA);
- if (!x)
- panic("Unable to allocate memory for dma cache\n");
+/*
+ * Conversion table for small slabs sizes / 8 to the index in the
+ * kmalloc array. This is necessary for slabs < 192 since we have non power
+ * of two cache sizes there. The size of larger slabs can be determined using
+ * fls.
+ */
+static s8 size_index[24] = {
+ 3, /* 8 */
+ 4, /* 16 */
+ 5, /* 24 */
+ 5, /* 32 */
+ 6, /* 40 */
+ 6, /* 48 */
+ 6, /* 56 */
+ 6, /* 64 */
+ 1, /* 72 */
+ 1, /* 80 */
+ 1, /* 88 */
+ 1, /* 96 */
+ 7, /* 104 */
+ 7, /* 112 */
+ 7, /* 120 */
+ 7, /* 128 */
+ 2, /* 136 */
+ 2, /* 144 */
+ 2, /* 152 */
+ 2, /* 160 */
+ 2, /* 168 */
+ 2, /* 176 */
+ 2, /* 184 */
+ 2 /* 192 */
+};
- if (index <= KMALLOC_SHIFT_HIGH)
- realsize = 1 << index;
- else {
- if (index == 1)
- realsize = 96;
- else
- realsize = 192;
- }
+static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+{
+ int index;
- text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
- (unsigned int)realsize);
- s = create_kmalloc_cache(x, text, realsize, flags);
- kmalloc_caches_dma[index] = s;
- return s;
+ if (size <= 192) {
+ if (!size)
+ return ZERO_SIZE_PTR;
+
+ index = size_index[(size - 1) / 8];
+ } else {
+ if (size > KMALLOC_MAX_SIZE)
+ return NULL;
+
+ index = fls(size - 1);
}
+
+#ifdef CONFIG_ZONE_DMA
+ if (unlikely((flags & SLUB_DMA)))
+ return dma_kmalloc_cache(index, flags);
+
#endif
return &kmalloc_caches[index];
}
@@ -2242,9 +2369,10 @@ void *__kmalloc(size_t size, gfp_t flags)
{
struct kmem_cache *s = get_slab(size, flags);
- if (s)
- return slab_alloc(s, flags, -1, __builtin_return_address(0));
- return ZERO_SIZE_PTR;
+ if (ZERO_OR_NULL_PTR(s))
+ return s;
+
+ return slab_alloc(s, flags, -1, __builtin_return_address(0));
}
EXPORT_SYMBOL(__kmalloc);
@@ -2253,9 +2381,10 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
{
struct kmem_cache *s = get_slab(size, flags);
- if (s)
- return slab_alloc(s, flags, node, __builtin_return_address(0));
- return ZERO_SIZE_PTR;
+ if (ZERO_OR_NULL_PTR(s))
+ return s;
+
+ return slab_alloc(s, flags, node, __builtin_return_address(0));
}
EXPORT_SYMBOL(__kmalloc_node);
#endif
@@ -2306,7 +2435,7 @@ void kfree(const void *x)
* this comparison would be true for all "negative" pointers
* (which would cover the whole upper half of the address space).
*/
- if ((unsigned long)x <= (unsigned long)ZERO_SIZE_PTR)
+ if (ZERO_OR_NULL_PTR(x))
return;
page = virt_to_head_page(x);
@@ -2395,43 +2524,6 @@ int kmem_cache_shrink(struct kmem_cache *s)
}
EXPORT_SYMBOL(kmem_cache_shrink);
-/**
- * krealloc - reallocate memory. The contents will remain unchanged.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes. If @p is %NULL, krealloc()
- * behaves exactly like kmalloc(). If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
- */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
-{
- void *ret;
- size_t ks;
-
- if (unlikely(!p || p == ZERO_SIZE_PTR))
- return kmalloc(new_size, flags);
-
- if (unlikely(!new_size)) {
- kfree(p);
- return ZERO_SIZE_PTR;
- }
-
- ks = ksize(p);
- if (ks >= new_size)
- return (void *)p;
-
- ret = kmalloc(new_size, flags);
- if (ret) {
- memcpy(ret, p, min(new_size, ks));
- kfree(p);
- }
- return ret;
-}
-EXPORT_SYMBOL(krealloc);
-
/********************************************************************
* Basic setup of slabs
*******************************************************************/
@@ -2474,6 +2566,24 @@ void __init kmem_cache_init(void)
caches++;
}
+
+ /*
+ * Patch up the size_index table if we have strange large alignment
+ * requirements for the kmalloc array. This is only the case for
+ * mips it seems. The standard arches will not generate any code here.
+ *
+ * Largest permitted alignment is 256 bytes due to the way we
+ * handle the index determination for the smaller caches.
+ *
+ * Make sure that nothing crazy happens if someone starts tinkering
+ * around with ARCH_KMALLOC_MINALIGN
+ */
+ BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
+ (KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
+
+ for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
+ size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
+
slab_state = UP;
/* Provide the correct kmalloc names now that the caches are up */
@@ -2519,7 +2629,7 @@ static struct kmem_cache *find_mergeable(size_t size,
size_t align, unsigned long flags,
void (*ctor)(void *, struct kmem_cache *, unsigned long))
{
- struct list_head *h;
+ struct kmem_cache *s;
if (slub_nomerge || (flags & SLUB_NEVER_MERGE))
return NULL;
@@ -2531,10 +2641,7 @@ static struct kmem_cache *find_mergeable(size_t size,
align = calculate_alignment(flags, align, size);
size = ALIGN(size, align);
- list_for_each(h, &slab_caches) {
- struct kmem_cache *s =
- container_of(h, struct kmem_cache, list);
-
+ list_for_each_entry(s, &slab_caches, list) {
if (slab_unmergeable(s))
continue;
@@ -2577,25 +2684,26 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
*/
s->objsize = max(s->objsize, (int)size);
s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
+ up_write(&slub_lock);
if (sysfs_slab_alias(s, name))
goto err;
- } else {
- s = kmalloc(kmem_size, GFP_KERNEL);
- if (s && kmem_cache_open(s, GFP_KERNEL, name,
+ return s;
+ }
+ s = kmalloc(kmem_size, GFP_KERNEL);
+ if (s) {
+ if (kmem_cache_open(s, GFP_KERNEL, name,
size, align, flags, ctor)) {
- if (sysfs_slab_add(s)) {
- kfree(s);
- goto err;
- }
list_add(&s->list, &slab_caches);
- } else
- kfree(s);
+ up_write(&slub_lock);
+ if (sysfs_slab_add(s))
+ goto err;
+ return s;
+ }
+ kfree(s);
}
up_write(&slub_lock);
- return s;
err:
- up_write(&slub_lock);
if (flags & SLAB_PANIC)
panic("Cannot create slabcache %s\n", name);
else
@@ -2604,45 +2712,7 @@ err:
}
EXPORT_SYMBOL(kmem_cache_create);
-void *kmem_cache_zalloc(struct kmem_cache *s, gfp_t flags)
-{
- void *x;
-
- x = slab_alloc(s, flags, -1, __builtin_return_address(0));
- if (x)
- memset(x, 0, s->objsize);
- return x;
-}
-EXPORT_SYMBOL(kmem_cache_zalloc);
-
#ifdef CONFIG_SMP
-static void for_all_slabs(void (*func)(struct kmem_cache *, int), int cpu)
-{
- struct list_head *h;
-
- down_read(&slub_lock);
- list_for_each(h, &slab_caches) {
- struct kmem_cache *s =
- container_of(h, struct kmem_cache, list);
-
- func(s, cpu);
- }
- up_read(&slub_lock);
-}
-
-/*
- * Version of __flush_cpu_slab for the case that interrupts
- * are enabled.
- */
-static void cpu_slab_flush(struct kmem_cache *s, int cpu)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- __flush_cpu_slab(s, cpu);
- local_irq_restore(flags);
-}
-
/*
* Use the cpu notifier to insure that the cpu slabs are flushed when
* necessary.
@@ -2651,13 +2721,21 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
+ struct kmem_cache *s;
+ unsigned long flags;
switch (action) {
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- for_all_slabs(cpu_slab_flush, cpu);
+ down_read(&slub_lock);
+ list_for_each_entry(s, &slab_caches, list) {
+ local_irq_save(flags);
+ __flush_cpu_slab(s, cpu);
+ local_irq_restore(flags);
+ }
+ up_read(&slub_lock);
break;
default:
break;
@@ -2674,8 +2752,8 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
{
struct kmem_cache *s = get_slab(size, gfpflags);
- if (!s)
- return ZERO_SIZE_PTR;
+ if (ZERO_OR_NULL_PTR(s))
+ return s;
return slab_alloc(s, gfpflags, -1, caller);
}
@@ -2685,18 +2763,18 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
{
struct kmem_cache *s = get_slab(size, gfpflags);
- if (!s)
- return ZERO_SIZE_PTR;
+ if (ZERO_OR_NULL_PTR(s))
+ return s;
return slab_alloc(s, gfpflags, node, caller);
}
#if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
-static int validate_slab(struct kmem_cache *s, struct page *page)
+static int validate_slab(struct kmem_cache *s, struct page *page,
+ unsigned long *map)
{
void *p;
void *addr = page_address(page);
- DECLARE_BITMAP(map, s->objects);
if (!check_slab(s, page) ||
!on_freelist(s, page, NULL))
@@ -2718,10 +2796,11 @@ static int validate_slab(struct kmem_cache *s, struct page *page)
return 1;
}
-static void validate_slab_slab(struct kmem_cache *s, struct page *page)
+static void validate_slab_slab(struct kmem_cache *s, struct page *page,
+ unsigned long *map)
{
if (slab_trylock(page)) {
- validate_slab(s, page);
+ validate_slab(s, page, map);
slab_unlock(page);
} else
printk(KERN_INFO "SLUB %s: Skipped busy slab 0x%p\n",
@@ -2738,7 +2817,8 @@ static void validate_slab_slab(struct kmem_cache *s, struct page *page)
}
}
-static int validate_slab_node(struct kmem_cache *s, struct kmem_cache_node *n)
+static int validate_slab_node(struct kmem_cache *s,
+ struct kmem_cache_node *n, unsigned long *map)
{
unsigned long count = 0;
struct page *page;
@@ -2747,7 +2827,7 @@ static int validate_slab_node(struct kmem_cache *s, struct kmem_cache_node *n)
spin_lock_irqsave(&n->list_lock, flags);
list_for_each_entry(page, &n->partial, lru) {
- validate_slab_slab(s, page);
+ validate_slab_slab(s, page, map);
count++;
}
if (count != n->nr_partial)
@@ -2758,7 +2838,7 @@ static int validate_slab_node(struct kmem_cache *s, struct kmem_cache_node *n)
goto out;
list_for_each_entry(page, &n->full, lru) {
- validate_slab_slab(s, page);
+ validate_slab_slab(s, page, map);
count++;
}
if (count != atomic_long_read(&n->nr_slabs))
@@ -2771,17 +2851,23 @@ out:
return count;
}
-static unsigned long validate_slab_cache(struct kmem_cache *s)
+static long validate_slab_cache(struct kmem_cache *s)
{
int node;
unsigned long count = 0;
+ unsigned long *map = kmalloc(BITS_TO_LONGS(s->objects) *
+ sizeof(unsigned long), GFP_KERNEL);
+
+ if (!map)
+ return -ENOMEM;
flush_all(s);
for_each_online_node(node) {
struct kmem_cache_node *n = get_node(s, node);
- count += validate_slab_node(s, n);
+ count += validate_slab_node(s, n, map);
}
+ kfree(map);
return count;
}
@@ -2870,18 +2956,14 @@ static void free_loc_track(struct loc_track *t)
get_order(sizeof(struct location) * t->max));
}
-static int alloc_loc_track(struct loc_track *t, unsigned long max)
+static int alloc_loc_track(struct loc_track *t, unsigned long max, gfp_t flags)
{
struct location *l;
int order;
- if (!max)
- max = PAGE_SIZE / sizeof(struct location);
-
order = get_order(sizeof(struct location) * max);
- l = (void *)__get_free_pages(GFP_ATOMIC, order);
-
+ l = (void *)__get_free_pages(flags, order);
if (!l)
return 0;
@@ -2947,7 +3029,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
/*
* Not found. Insert new tracking element.
*/
- if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max))
+ if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max, GFP_ATOMIC))
return 0;
l = t->loc + pos;
@@ -2990,11 +3072,12 @@ static int list_locations(struct kmem_cache *s, char *buf,
{
int n = 0;
unsigned long i;
- struct loc_track t;
+ struct loc_track t = { 0, 0, NULL };
int node;
- t.count = 0;
- t.max = 0;
+ if (!alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location),
+ GFP_KERNEL))
+ return sprintf(buf, "Out of memory\n");
/* Push back cpu slabs */
flush_all(s);
@@ -3398,11 +3481,14 @@ static ssize_t validate_show(struct kmem_cache *s, char *buf)
static ssize_t validate_store(struct kmem_cache *s,
const char *buf, size_t length)
{
- if (buf[0] == '1')
- validate_slab_cache(s);
- else
- return -EINVAL;
- return length;
+ int ret = -EINVAL;
+
+ if (buf[0] == '1') {
+ ret = validate_slab_cache(s);
+ if (ret >= 0)
+ ret = length;
+ }
+ return ret;
}
SLAB_ATTR(validate);
@@ -3556,7 +3642,7 @@ static struct kset_uevent_ops slab_uevent_ops = {
.filter = uevent_filter,
};
-decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
+static decl_subsys(slab, &slab_ktype, &slab_uevent_ops);
#define ID_STR_LENGTH 64
@@ -3654,7 +3740,7 @@ struct saved_alias {
struct saved_alias *next;
};
-struct saved_alias *alias_list;
+static struct saved_alias *alias_list;
static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
{
@@ -3682,7 +3768,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
static int __init slab_sysfs_init(void)
{
- struct list_head *h;
+ struct kmem_cache *s;
int err;
err = subsystem_register(&slab_subsys);
@@ -3693,10 +3779,7 @@ static int __init slab_sysfs_init(void)
slab_state = SYSFS;
- list_for_each(h, &slab_caches) {
- struct kmem_cache *s =
- container_of(h, struct kmem_cache, list);
-
+ list_for_each_entry(s, &slab_caches, list) {
err = sysfs_slab_add(s);
BUG_ON(err);
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 5f7cf2a4cb55..67daecb6031a 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -21,7 +21,7 @@
/*
* swapper_space is a fiction, retained to simplify the path through
- * vmscan's shrink_list, to make sync_page look nicer, and to allow
+ * vmscan's shrink_page_list, to make sync_page look nicer, and to allow
* future use of radix_tree tags in the swap cache.
*/
static const struct address_space_operations swap_aops = {
@@ -334,7 +334,8 @@ struct page *read_swap_cache_async(swp_entry_t entry,
* Get a new page to read into from swap.
*/
if (!new_page) {
- new_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+ new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+ vma, addr);
if (!new_page)
break; /* Out of memory */
}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index acc172cbe3aa..7ff0a81c7b01 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -885,7 +885,7 @@ static int try_to_unuse(unsigned int type)
/*
* So we could skip searching mms once swap count went
* to 1, we did not mark any present ptes as dirty: must
- * mark page dirty so shrink_list will preserve it.
+ * mark page dirty so shrink_page_list will preserve it.
*/
SetPageDirty(page);
unlock_page(page);
diff --git a/mm/truncate.c b/mm/truncate.c
index 4fbe1a2da5fb..f47e46d1be3b 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -100,9 +100,9 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
if (PagePrivate(page))
do_invalidatepage(page, 0);
+ remove_from_page_cache(page);
ClearPageUptodate(page);
ClearPageMappedToDisk(page);
- remove_from_page_cache(page);
page_cache_release(page); /* pagecache ref */
}
@@ -253,21 +253,8 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
}
EXPORT_SYMBOL(truncate_inode_pages);
-/**
- * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
- * @mapping: the address_space which holds the pages to invalidate
- * @start: the offset 'from' which to invalidate
- * @end: the offset 'to' which to invalidate (inclusive)
- *
- * This function only removes the unlocked pages, if you want to
- * remove all the pages of one inode, you must call truncate_inode_pages.
- *
- * invalidate_mapping_pages() will not block on IO activity. It will not
- * invalidate pages which are dirty, locked, under writeback or mapped into
- * pagetables.
- */
-unsigned long invalidate_mapping_pages(struct address_space *mapping,
- pgoff_t start, pgoff_t end)
+unsigned long __invalidate_mapping_pages(struct address_space *mapping,
+ pgoff_t start, pgoff_t end, bool be_atomic)
{
struct pagevec pvec;
pgoff_t next = start;
@@ -308,17 +295,38 @@ unlock:
break;
}
pagevec_release(&pvec);
+ if (likely(!be_atomic))
+ cond_resched();
}
return ret;
}
+
+/**
+ * invalidate_mapping_pages - Invalidate all the unlocked pages of one inode
+ * @mapping: the address_space which holds the pages to invalidate
+ * @start: the offset 'from' which to invalidate
+ * @end: the offset 'to' which to invalidate (inclusive)
+ *
+ * This function only removes the unlocked pages, if you want to
+ * remove all the pages of one inode, you must call truncate_inode_pages.
+ *
+ * invalidate_mapping_pages() will not block on IO activity. It will not
+ * invalidate pages which are dirty, locked, under writeback or mapped into
+ * pagetables.
+ */
+unsigned long invalidate_mapping_pages(struct address_space *mapping,
+ pgoff_t start, pgoff_t end)
+{
+ return __invalidate_mapping_pages(mapping, start, end, false);
+}
EXPORT_SYMBOL(invalidate_mapping_pages);
/*
* This is like invalidate_complete_page(), except it ignores the page's
* refcount. We do this because invalidate_inode_pages2() needs stronger
* invalidation guarantees, and cannot afford to leave pages behind because
- * shrink_list() has a temp ref on them, or because they're transiently sitting
- * in the lru_cache_add() pagevecs.
+ * shrink_page_list() has a temp ref on them, or because they're transiently
+ * sitting in the lru_cache_add() pagevecs.
*/
static int
invalidate_complete_page2(struct address_space *mapping, struct page *page)
diff --git a/mm/util.c b/mm/util.c
index ace2aea69f1a..78f3783bdcc8 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -5,20 +5,6 @@
#include <asm/uaccess.h>
/**
- * __kzalloc - allocate memory. The memory is set to zero.
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- */
-void *__kzalloc(size_t size, gfp_t flags)
-{
- void *ret = kmalloc_track_caller(size, flags);
- if (ret)
- memset(ret, 0, size);
- return ret;
-}
-EXPORT_SYMBOL(__kzalloc);
-
-/*
* kstrdup - allocate space for and copy an existing string
*
* @s: the string to duplicate
@@ -58,6 +44,40 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
}
EXPORT_SYMBOL(kmemdup);
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes. If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc(). If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+ void *ret;
+ size_t ks;
+
+ if (unlikely(!new_size)) {
+ kfree(p);
+ return ZERO_SIZE_PTR;
+ }
+
+ ks = ksize(p);
+ if (ks >= new_size)
+ return (void *)p;
+
+ ret = kmalloc_track_caller(new_size, flags);
+ if (ret) {
+ memcpy(ret, p, min(new_size, ks));
+ kfree(p);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(krealloc);
+
/*
* strndup_user - duplicate an existing string from user space
*
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d3a9c5368257..8e05a11155c9 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -68,12 +68,12 @@ static inline void vunmap_pud_range(pgd_t *pgd, unsigned long addr,
} while (pud++, addr = next, addr != end);
}
-void unmap_vm_area(struct vm_struct *area)
+void unmap_kernel_range(unsigned long addr, unsigned long size)
{
pgd_t *pgd;
unsigned long next;
- unsigned long addr = (unsigned long) area->addr;
- unsigned long end = addr + area->size;
+ unsigned long start = addr;
+ unsigned long end = addr + size;
BUG_ON(addr >= end);
pgd = pgd_offset_k(addr);
@@ -84,7 +84,12 @@ void unmap_vm_area(struct vm_struct *area)
continue;
vunmap_pud_range(pgd, addr, next);
} while (pgd++, addr = next, addr != end);
- flush_tlb_kernel_range((unsigned long) area->addr, end);
+ flush_tlb_kernel_range(start, end);
+}
+
+static void unmap_vm_area(struct vm_struct *area)
+{
+ unmap_kernel_range((unsigned long)area->addr, area->size);
}
static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
@@ -427,11 +432,12 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
area->nr_pages = nr_pages;
/* Please note that the recursion is strictly bounded. */
if (array_size > PAGE_SIZE) {
- pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node);
+ pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
+ PAGE_KERNEL, node);
area->flags |= VM_VPAGES;
} else {
pages = kmalloc_node(array_size,
- (gfp_mask & GFP_LEVEL_MASK),
+ (gfp_mask & GFP_LEVEL_MASK) | __GFP_ZERO,
node);
}
area->pages = pages;
@@ -440,7 +446,6 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
kfree(area);
return NULL;
}
- memset(area->pages, 0, array_size);
for (i = 0; i < area->nr_pages; i++) {
if (node < 0)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 1be5a6376ef0..d419e10e3daa 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -66,17 +66,8 @@ struct scan_control {
int swappiness;
int all_unreclaimable;
-};
-/*
- * The list of shrinker callbacks used by to apply pressure to
- * ageable caches.
- */
-struct shrinker {
- shrinker_t shrinker;
- struct list_head list;
- int seeks; /* seeks to recreate an obj */
- long nr; /* objs pending delete */
+ int order;
};
#define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
@@ -121,34 +112,25 @@ static DECLARE_RWSEM(shrinker_rwsem);
/*
* Add a shrinker callback to be called from the vm
*/
-struct shrinker *set_shrinker(int seeks, shrinker_t theshrinker)
+void register_shrinker(struct shrinker *shrinker)
{
- struct shrinker *shrinker;
-
- shrinker = kmalloc(sizeof(*shrinker), GFP_KERNEL);
- if (shrinker) {
- shrinker->shrinker = theshrinker;
- shrinker->seeks = seeks;
- shrinker->nr = 0;
- down_write(&shrinker_rwsem);
- list_add_tail(&shrinker->list, &shrinker_list);
- up_write(&shrinker_rwsem);
- }
- return shrinker;
+ shrinker->nr = 0;
+ down_write(&shrinker_rwsem);
+ list_add_tail(&shrinker->list, &shrinker_list);
+ up_write(&shrinker_rwsem);
}
-EXPORT_SYMBOL(set_shrinker);
+EXPORT_SYMBOL(register_shrinker);
/*
* Remove one
*/
-void remove_shrinker(struct shrinker *shrinker)
+void unregister_shrinker(struct shrinker *shrinker)
{
down_write(&shrinker_rwsem);
list_del(&shrinker->list);
up_write(&shrinker_rwsem);
- kfree(shrinker);
}
-EXPORT_SYMBOL(remove_shrinker);
+EXPORT_SYMBOL(unregister_shrinker);
#define SHRINK_BATCH 128
/*
@@ -185,7 +167,7 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
list_for_each_entry(shrinker, &shrinker_list, list) {
unsigned long long delta;
unsigned long total_scan;
- unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask);
+ unsigned long max_pass = (*shrinker->shrink)(0, gfp_mask);
delta = (4 * scanned) / shrinker->seeks;
delta *= max_pass;
@@ -213,8 +195,8 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
int shrink_ret;
int nr_before;
- nr_before = (*shrinker->shrinker)(0, gfp_mask);
- shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
+ nr_before = (*shrinker->shrink)(0, gfp_mask);
+ shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask);
if (shrink_ret == -1)
break;
if (shrink_ret < nr_before)
@@ -481,7 +463,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
referenced = page_referenced(page, 1);
/* In active use or really unfreeable? Activate it. */
- if (referenced && page_mapping_inuse(page))
+ if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
+ referenced && page_mapping_inuse(page))
goto activate_locked;
#ifdef CONFIG_SWAP
@@ -514,7 +497,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
}
if (PageDirty(page)) {
- if (referenced)
+ if (sc->order <= PAGE_ALLOC_COSTLY_ORDER && referenced)
goto keep_locked;
if (!may_enter_fs)
goto keep_locked;
@@ -598,6 +581,51 @@ keep:
return nr_reclaimed;
}
+/* LRU Isolation modes. */
+#define ISOLATE_INACTIVE 0 /* Isolate inactive pages. */
+#define ISOLATE_ACTIVE 1 /* Isolate active pages. */
+#define ISOLATE_BOTH 2 /* Isolate both active and inactive pages. */
+
+/*
+ * Attempt to remove the specified page from its LRU. Only take this page
+ * if it is of the appropriate PageActive status. Pages which are being
+ * freed elsewhere are also ignored.
+ *
+ * page: page to consider
+ * mode: one of the LRU isolation modes defined above
+ *
+ * returns 0 on success, -ve errno on failure.
+ */
+static int __isolate_lru_page(struct page *page, int mode)
+{
+ int ret = -EINVAL;
+
+ /* Only take pages on the LRU. */
+ if (!PageLRU(page))
+ return ret;
+
+ /*
+ * When checking the active state, we need to be sure we are
+ * dealing with comparible boolean values. Take the logical not
+ * of each.
+ */
+ if (mode != ISOLATE_BOTH && (!PageActive(page) != !mode))
+ return ret;
+
+ ret = -EBUSY;
+ if (likely(get_page_unless_zero(page))) {
+ /*
+ * Be careful not to clear PageLRU until after we're
+ * sure the page is not being freed elsewhere -- the
+ * page release code relies on it.
+ */
+ ClearPageLRU(page);
+ ret = 0;
+ }
+
+ return ret;
+}
+
/*
* zone->lru_lock is heavily contended. Some of the functions that
* shrink the lists perform better by taking out a batch of pages
@@ -612,38 +640,90 @@ keep:
* @src: The LRU list to pull pages off.
* @dst: The temp list to put pages on to.
* @scanned: The number of pages that were scanned.
+ * @order: The caller's attempted allocation order
+ * @mode: One of the LRU isolation modes
*
* returns how many pages were moved onto *@dst.
*/
static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
struct list_head *src, struct list_head *dst,
- unsigned long *scanned)
+ unsigned long *scanned, int order, int mode)
{
unsigned long nr_taken = 0;
- struct page *page;
unsigned long scan;
for (scan = 0; scan < nr_to_scan && !list_empty(src); scan++) {
- struct list_head *target;
+ struct page *page;
+ unsigned long pfn;
+ unsigned long end_pfn;
+ unsigned long page_pfn;
+ int zone_id;
+
page = lru_to_page(src);
prefetchw_prev_lru_page(page, src, flags);
VM_BUG_ON(!PageLRU(page));
- list_del(&page->lru);
- target = src;
- if (likely(get_page_unless_zero(page))) {
- /*
- * Be careful not to clear PageLRU until after we're
- * sure the page is not being freed elsewhere -- the
- * page release code relies on it.
- */
- ClearPageLRU(page);
- target = dst;
+ switch (__isolate_lru_page(page, mode)) {
+ case 0:
+ list_move(&page->lru, dst);
nr_taken++;
- } /* else it is being freed elsewhere */
+ break;
+
+ case -EBUSY:
+ /* else it is being freed elsewhere */
+ list_move(&page->lru, src);
+ continue;
+
+ default:
+ BUG();
+ }
+
+ if (!order)
+ continue;
- list_add(&page->lru, target);
+ /*
+ * Attempt to take all pages in the order aligned region
+ * surrounding the tag page. Only take those pages of
+ * the same active state as that tag page. We may safely
+ * round the target page pfn down to the requested order
+ * as the mem_map is guarenteed valid out to MAX_ORDER,
+ * where that page is in a different zone we will detect
+ * it from its zone id and abort this block scan.
+ */
+ zone_id = page_zone_id(page);
+ page_pfn = page_to_pfn(page);
+ pfn = page_pfn & ~((1 << order) - 1);
+ end_pfn = pfn + (1 << order);
+ for (; pfn < end_pfn; pfn++) {
+ struct page *cursor_page;
+
+ /* The target page is in the block, ignore it. */
+ if (unlikely(pfn == page_pfn))
+ continue;
+
+ /* Avoid holes within the zone. */
+ if (unlikely(!pfn_valid_within(pfn)))
+ break;
+
+ cursor_page = pfn_to_page(pfn);
+ /* Check that we have not crossed a zone boundary. */
+ if (unlikely(page_zone_id(cursor_page) != zone_id))
+ continue;
+ switch (__isolate_lru_page(cursor_page, mode)) {
+ case 0:
+ list_move(&cursor_page->lru, dst);
+ nr_taken++;
+ scan++;
+ break;
+
+ case -EBUSY:
+ /* else it is being freed elsewhere */
+ list_move(&cursor_page->lru, src);
+ default:
+ break;
+ }
+ }
}
*scanned = scan;
@@ -651,6 +731,24 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
}
/*
+ * clear_active_flags() is a helper for shrink_active_list(), clearing
+ * any active bits from the pages in the list.
+ */
+static unsigned long clear_active_flags(struct list_head *page_list)
+{
+ int nr_active = 0;
+ struct page *page;
+
+ list_for_each_entry(page, page_list, lru)
+ if (PageActive(page)) {
+ ClearPageActive(page);
+ nr_active++;
+ }
+
+ return nr_active;
+}
+
+/*
* shrink_inactive_list() is a helper for shrink_zone(). It returns the number
* of reclaimed pages
*/
@@ -671,11 +769,18 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
unsigned long nr_taken;
unsigned long nr_scan;
unsigned long nr_freed;
+ unsigned long nr_active;
nr_taken = isolate_lru_pages(sc->swap_cluster_max,
- &zone->inactive_list,
- &page_list, &nr_scan);
- __mod_zone_page_state(zone, NR_INACTIVE, -nr_taken);
+ &zone->inactive_list,
+ &page_list, &nr_scan, sc->order,
+ (sc->order > PAGE_ALLOC_COSTLY_ORDER)?
+ ISOLATE_BOTH : ISOLATE_INACTIVE);
+ nr_active = clear_active_flags(&page_list);
+
+ __mod_zone_page_state(zone, NR_ACTIVE, -nr_active);
+ __mod_zone_page_state(zone, NR_INACTIVE,
+ -(nr_taken - nr_active));
zone->pages_scanned += nr_scan;
spin_unlock_irq(&zone->lru_lock);
@@ -820,7 +925,7 @@ force_reclaim_mapped:
lru_add_drain();
spin_lock_irq(&zone->lru_lock);
pgmoved = isolate_lru_pages(nr_pages, &zone->active_list,
- &l_hold, &pgscanned);
+ &l_hold, &pgscanned, sc->order, ISOLATE_ACTIVE);
zone->pages_scanned += pgscanned;
__mod_zone_page_state(zone, NR_ACTIVE, -pgmoved);
spin_unlock_irq(&zone->lru_lock);
@@ -1011,7 +1116,7 @@ static unsigned long shrink_zones(int priority, struct zone **zones,
* holds filesystem locks which prevent writeout this might not work, and the
* allocation attempt will fail.
*/
-unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
+unsigned long try_to_free_pages(struct zone **zones, int order, gfp_t gfp_mask)
{
int priority;
int ret = 0;
@@ -1026,6 +1131,7 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
.swap_cluster_max = SWAP_CLUSTER_MAX,
.may_swap = 1,
.swappiness = vm_swappiness,
+ .order = order,
};
count_vm_event(ALLOCSTALL);
@@ -1131,6 +1237,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
.may_swap = 1,
.swap_cluster_max = SWAP_CLUSTER_MAX,
.swappiness = vm_swappiness,
+ .order = order,
};
/*
* temp_priority is used to remember the scanning priority at which
@@ -1314,6 +1421,7 @@ static int kswapd(void *p)
* trying to free the first piece of memory in the first place).
*/
tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+ set_freezable();
order = 0;
for ( ; ; ) {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index eceaf496210f..fadf791cd7e6 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -472,7 +472,7 @@ const struct seq_operations fragmentation_op = {
#endif
#define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
- TEXT_FOR_HIGHMEM(xx)
+ TEXT_FOR_HIGHMEM(xx) xx "_movable",
static const char * const vmstat_text[] = {
/* Zoned VM counters */
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 1c8f4a0c5f43..1f78c3e336d8 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -36,6 +36,7 @@
#include <linux/signal.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/freezer.h>
#include <linux/errno.h>
#include <linux/net.h>
#include <net/sock.h>
@@ -474,7 +475,6 @@ static int bnep_session(void *arg)
daemonize("kbnepd %s", dev->name);
set_user_nice(current, -15);
- current->flags |= PF_NOFREEZE;
init_waitqueue_entry(&wait, current);
add_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 66bef1ccee2a..ca60a4517fd3 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/fcntl.h>
+#include <linux/freezer.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/ioctl.h>
@@ -287,7 +288,6 @@ static int cmtp_session(void *arg)
daemonize("kcmtpd_ctr_%d", session->num);
set_user_nice(current, -15);
- current->flags |= PF_NOFREEZE;
init_waitqueue_entry(&wait, current);
add_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 450eb0244bbf..64d89ca28847 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -28,6 +28,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
+#include <linux/freezer.h>
#include <linux/fcntl.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
@@ -547,7 +548,6 @@ static int hidp_session(void *arg)
daemonize("khidpd_%04x%04x", vendor, product);
set_user_nice(current, -15);
- current->flags |= PF_NOFREEZE;
init_waitqueue_entry(&ctrl_wait, current);
init_waitqueue_entry(&intr_wait, current);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 52e04df323ea..bb7220770f2c 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -33,6 +33,7 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/init.h>
+#include <linux/freezer.h>
#include <linux/wait.h>
#include <linux/device.h>
#include <linux/net.h>
@@ -1940,7 +1941,6 @@ static int rfcomm_run(void *unused)
daemonize("krfcommd");
set_user_nice(current, -10);
- current->flags |= PF_NOFREEZE;
BT_DBG("");
diff --git a/net/compat.c b/net/compat.c
index 9a0f5f2b90c8..d74d82155d78 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -276,7 +276,8 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
err = security_file_receive(fp[i]);
if (err)
break;
- err = get_unused_fd();
+ err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags
+ ? O_CLOEXEC : 0);
if (err < 0)
break;
new_fd = err;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index d1264e9a50a8..de1b26aa5720 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -124,13 +124,6 @@ static void poll_napi(struct netpoll *np)
if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
npinfo->poll_owner != smp_processor_id() &&
spin_trylock(&npinfo->poll_lock)) {
- /* When calling dev->poll from poll_napi, we may end up in
- * netif_rx_complete. However, only the CPU to which the
- * device was queued is allowed to remove it from poll_list.
- * Setting POLL_LIST_FROZEN tells netif_rx_complete
- * to leave the NAPI state alone.
- */
- set_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
@@ -138,7 +131,6 @@ static void poll_napi(struct netpoll *np)
atomic_dec(&trapped);
npinfo->rx_flags &= ~NETPOLL_RX_DROP;
- clear_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
spin_unlock(&npinfo->poll_lock);
}
}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 75215331b045..bca787fdbc51 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3465,6 +3465,8 @@ static int pktgen_thread_worker(void *arg)
set_current_state(TASK_INTERRUPTIBLE);
+ set_freezable();
+
while (!kthread_should_stop()) {
pkt_dev = next_to_run(t);
diff --git a/net/core/scm.c b/net/core/scm.c
index 292ad8d5ad76..44c4ec2c8769 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -228,7 +228,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
err = security_file_receive(fp[i]);
if (err)
break;
- err = get_unused_fd();
+ err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags
+ ? O_CLOEXEC : 0);
if (err < 0)
break;
new_fd = err;
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index cc8110bdd579..afb6c6698b27 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -271,8 +271,11 @@ ieee80211softmac_assoc_work(struct work_struct *work)
*/
dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
- if (ieee80211softmac_start_scan(mac))
+ if (ieee80211softmac_start_scan(mac)) {
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
+ mac->associnfo.associating = 0;
+ mac->associnfo.associated = 0;
+ }
goto out;
} else {
mac->associnfo.associating = 0;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 42f12bd65964..89dcc485653b 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -46,10 +46,6 @@
#include "netlabel_cipso_v4.h"
#include "netlabel_user.h"
-/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for
- * details */
-extern int audit_enabled;
-
/*
* NetLabel NETLINK Setup Functions
*/
diff --git a/net/socket.c b/net/socket.c
index f4530196a70a..b71114250046 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1939,9 +1939,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
total_len = err;
cmsg_ptr = (unsigned long)msg_sys.msg_control;
- msg_sys.msg_flags = 0;
- if (MSG_CMSG_COMPAT & flags)
- msg_sys.msg_flags = MSG_CMSG_COMPAT;
+ msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index aa55d0a03e6f..29a8ecc60928 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -543,17 +543,18 @@ rpcauth_uptodatecred(struct rpc_task *task)
test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
}
-
-static struct shrinker *rpc_cred_shrinker;
+static struct shrinker rpc_cred_shrinker = {
+ .shrink = rpcauth_cache_shrinker,
+ .seeks = DEFAULT_SEEKS,
+};
void __init rpcauth_init_module(void)
{
rpc_init_authunix();
- rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker);
+ register_shrinker(&rpc_cred_shrinker);
}
void __exit rpcauth_remove_module(void)
{
- if (rpc_cred_shrinker != NULL)
- remove_shrinker(rpc_cred_shrinker);
+ unregister_shrinker(&rpc_cred_shrinker);
}
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index baf4096d52d4..abfda33bac64 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -43,6 +43,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/pagemap.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/auth.h>
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 71b9daefdff3..9843eacef11d 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -231,6 +231,7 @@ static struct pf_desc gss_kerberos_pfs[] = {
static struct gss_api_mech gss_kerberos_mech = {
.gm_name = "krb5",
.gm_owner = THIS_MODULE,
+ .gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
.gm_ops = &gss_kerberos_ops,
.gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
.gm_pfs = gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 26872517ccf3..61801a069ff0 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -194,6 +194,20 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
EXPORT_SYMBOL(gss_mech_get_by_pseudoflavor);
u32
+gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
+{
+ int i;
+
+ for (i = 0; i < gm->gm_pf_num; i++) {
+ if (gm->gm_pfs[i].service == service) {
+ return gm->gm_pfs[i].pseudoflavor;
+ }
+ }
+ return RPC_AUTH_MAXFLAVOR; /* illegal value */
+}
+EXPORT_SYMBOL(gss_svc_to_pseudoflavor);
+
+u32
gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
{
int i;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 577d590e755f..5deb4b6e4514 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -217,6 +217,7 @@ static struct pf_desc gss_spkm3_pfs[] = {
static struct gss_api_mech gss_spkm3_mech = {
.gm_name = "spkm3",
.gm_owner = THIS_MODULE,
+ .gm_oid = {7, "\053\006\001\005\005\001\003"},
.gm_ops = &gss_spkm3_ops,
.gm_pf_num = ARRAY_SIZE(gss_spkm3_pfs),
.gm_pfs = gss_spkm3_pfs,
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index c094583386fd..490697542fc2 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -743,6 +743,15 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc)
static struct auth_ops svcauthops_gss;
+u32 svcauth_gss_flavor(struct auth_domain *dom)
+{
+ struct gss_domain *gd = container_of(dom, struct gss_domain, h);
+
+ return gd->pseudoflavor;
+}
+
+EXPORT_SYMBOL(svcauth_gss_flavor);
+
int
svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
{
@@ -913,10 +922,23 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
struct gss_svc_data *svcdata = rqstp->rq_auth_data;
struct rsc *rsci = svcdata->rsci;
struct rpc_gss_wire_cred *gc = &svcdata->clcred;
+ int stat;
- rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
- if (rqstp->rq_client == NULL)
+ /*
+ * A gss export can be specified either by:
+ * export *(sec=krb5,rw)
+ * or by
+ * export gss/krb5(rw)
+ * The latter is deprecated; but for backwards compatibility reasons
+ * the nfsd code will still fall back on trying it if the former
+ * doesn't work; so we try to make both available to nfsd, below.
+ */
+ rqstp->rq_gssclient = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
+ if (rqstp->rq_gssclient == NULL)
return SVC_DENIED;
+ stat = svcauth_unix_set_client(rqstp);
+ if (stat == SVC_DROP)
+ return stat;
return SVC_OK;
}
@@ -1088,7 +1110,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
svc_putnl(resv, GSS_SEQ_WIN);
if (svc_safe_putnetobj(resv, &rsip->out_token))
goto drop;
- rqstp->rq_client = NULL;
}
goto complete;
case RPC_GSS_PROC_DESTROY:
@@ -1131,6 +1152,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
}
svcdata->rsci = rsci;
cache_get(&rsci->h);
+ rqstp->rq_flavor = gss_svc_to_pseudoflavor(
+ rsci->mechctx->mech_type, gc->gc_svc);
ret = SVC_OK;
goto out;
}
@@ -1317,6 +1340,9 @@ out_err:
if (rqstp->rq_client)
auth_domain_put(rqstp->rq_client);
rqstp->rq_client = NULL;
+ if (rqstp->rq_gssclient)
+ auth_domain_put(rqstp->rq_gssclient);
+ rqstp->rq_gssclient = NULL;
if (rqstp->rq_cred.cr_group_info)
put_group_info(rqstp->rq_cred.cr_group_info);
rqstp->rq_cred.cr_group_info = NULL;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 07dcd20cbee4..411479411b21 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -5,6 +5,7 @@
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/svcauth.h>
+#include <linux/sunrpc/gss_api.h>
#include <linux/err.h>
#include <linux/seq_file.h>
#include <linux/hash.h>
@@ -637,7 +638,7 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
}
}
-static int
+int
svcauth_unix_set_client(struct svc_rqst *rqstp)
{
struct sockaddr_in *sin = svc_addr_in(rqstp);
@@ -672,6 +673,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
return SVC_OK;
}
+EXPORT_SYMBOL(svcauth_unix_set_client);
+
static int
svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
{
@@ -707,6 +710,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
svc_putnl(resv, RPC_AUTH_NULL);
svc_putnl(resv, 0);
+ rqstp->rq_flavor = RPC_AUTH_NULL;
return SVC_OK;
}
@@ -784,6 +788,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
svc_putnl(resv, RPC_AUTH_NULL);
svc_putnl(resv, 0);
+ rqstp->rq_flavor = RPC_AUTH_UNIX;
return SVC_OK;
badcred:
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 277c32647f36..25e20a27fc59 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,7 @@ use strict;
my $P = $0;
$P =~ s@.*/@@g;
-my $V = '0.06';
+my $V = '0.07';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -246,6 +246,19 @@ sub cat_vet {
return $vet;
}
+sub ERROR {
+ print "ERROR: $_[0]\n";
+ our $clean = 0;
+}
+sub WARN {
+ print "WARNING: $_[0]\n";
+ our $clean = 0;
+}
+sub CHK {
+ print "CHECK: $_[0]\n";
+ our $clean = 0;
+}
+
sub process {
my $filename = shift;
my @lines = @_;
@@ -259,7 +272,7 @@ sub process {
my $previndent=0;
my $stashindent=0;
- my $clean = 1;
+ our $clean = 1;
my $signoff = 0;
my $is_patch = 0;
@@ -290,8 +303,11 @@ sub process {
long\s+int|
long\s+long|
long\s+long\s+int|
+ u8|u16|u32|u64|
+ s8|s16|s32|s64|
struct\s+$Ident|
union\s+$Ident|
+ enum\s+$Ident|
${Ident}_t
)
(?:\s+$Sparse)*
@@ -304,6 +320,23 @@ sub process {
my $Declare = qr{(?:$Storage\s+)?$Type};
my $Attribute = qr{__read_mostly|__init|__initdata};
+ # Pre-scan the patch looking for any __setup documentation.
+ my @setup_docs = ();
+ my $setup_docs = 0;
+ foreach my $line (@lines) {
+ if ($line=~/^\+\+\+\s+(\S+)/) {
+ $setup_docs = 0;
+ if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
+ $setup_docs = 1;
+ }
+ next;
+ }
+
+ if ($setup_docs && $line =~ /^\+/) {
+ push(@setup_docs, $line);
+ }
+ }
+
foreach my $line (@lines) {
$linenr++;
@@ -369,30 +402,42 @@ sub process {
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
my $hereline = "$here\n$line\n";
- my $herecurr = "$here\n$line\n\n";
- my $hereprev = "$here\n$prevline\n$line\n\n";
+ my $herecurr = "$here\n$line\n";
+ my $hereprev = "$here\n$prevline\n$line\n";
#check the patch for a signoff:
if ($line =~ /^\s*signed-off-by:/i) {
# This is a signoff, if ugly, so do not double report.
$signoff++;
if (!($line =~ /^\s*Signed-off-by:/)) {
- print "Signed-off-by: is the preferred form\n";
- print "$herecurr";
- $clean = 0;
+ WARN("Signed-off-by: is the preferred form\n" .
+ $herecurr);
}
if ($line =~ /^\s*signed-off-by:\S/i) {
- print "need space after Signed-off-by:\n";
- print "$herecurr";
- $clean = 0;
+ WARN("need space after Signed-off-by:\n" .
+ $herecurr);
}
}
# Check for wrappage within a valid hunk of the file
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
- print "patch seems to be corrupt (line wrapped?) [$realcnt]\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("patch seems to be corrupt (line wrapped?)\n" .
+ $herecurr);
+ }
+
+# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
+ if (($realfile =~ /^$/ || $line =~ /^\+/) &&
+ !($line =~ m/^(
+ [\x09\x0A\x0D\x20-\x7E] # ASCII
+ | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
+ | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
+ | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
+ | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
+ | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
+ | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
+ | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
+ )*$/x )) {
+ ERROR("Invalid UTF-8\n" . $herecurr);
}
#ignore lines being removed
@@ -403,16 +448,12 @@ sub process {
#trailing whitespace
if ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
- my $herevet = "$here\n" . cat_vet($line) . "\n\n";
- print "trailing whitespace\n";
- print "$herevet";
- $clean = 0;
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("trailing whitespace\n" . $herevet);
}
#80 column limit
if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
- print "line over 80 characters\n";
- print "$herecurr";
- $clean = 0;
+ WARN("line over 80 characters\n" . $herecurr);
}
# check we are in a valid source file *.[hc] if not then ignore this hunk
@@ -421,10 +462,8 @@ sub process {
# at the beginning of a line any tabs must come first and anything
# more than 8 must use tabs.
if ($line=~/^\+\s* \t\s*\S/ or $line=~/^\+\s* \s*/) {
- my $herevet = "$here\n" . cat_vet($line) . "\n\n";
- print "use tabs not spaces\n";
- print "$herevet";
- $clean = 0;
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("use tabs not spaces\n" . $herevet);
}
#
@@ -463,9 +502,27 @@ sub process {
}
}
if ($err ne '') {
- print "switch and case should be at the same indent\n";
- print "$here\n$line\n$err\n";
- $clean = 0;
+ ERROR("switch and case should be at the same indent\n$hereline\n$err\n");
+ }
+ }
+
+# if/while/etc brace do not go on next line, unless defining a do while loop,
+# or if that brace on the next line is for something else
+ if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
+ my @ctx = ctx_statement($linenr, $realcnt);
+ my $ctx_ln = $linenr + $#ctx + 1;
+ my $ctx_cnt = $realcnt - $#ctx - 1;
+ my $ctx = join("\n", @ctx);
+
+ while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
+ $ctx_ln++;
+ $ctx_cnt--;
+ }
+ ##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
+
+ if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+ ERROR("That { should be on the previous line\n" .
+ "$here\n$ctx\n$lines[$ctx_ln - 1]");
}
}
@@ -474,9 +531,7 @@ sub process {
# TEST: allow direct testing of the type matcher.
if ($tst_type && $line =~ /^.$Declare$/) {
- print "TEST: is type $Declare\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("TEST: is type $Declare\n" . $herecurr);
next;
}
@@ -488,9 +543,8 @@ sub process {
if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) {
my $path = $1;
if ($path =~ m{//}) {
- print "malformed #include filename\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("malformed #include filename\n" .
+ $herecurr);
}
# Sanitise this special form of string.
$path = 'X' x length($path);
@@ -499,9 +553,7 @@ sub process {
# no C99 // comments
if ($line =~ m{//}) {
- print "do not use C99 // comments\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("do not use C99 // comments\n" . $herecurr);
}
# Remove C99 comments.
$line =~ s@//.*@@;
@@ -514,49 +566,40 @@ sub process {
($prevline !~ /^\+}/) &&
($prevline !~ /^ }/) &&
($prevline !~ /\s$name(?:\s+$Attribute)?\s*(?:;|=)/)) {
- print "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n";
- print "$herecurr";
- $clean = 0;
+ WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
}
}
# check for static initialisers.
if ($line=~/\s*static\s.*=\s+(0|NULL);/) {
- print "do not initialise statics to 0 or NULL\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("do not initialise statics to 0 or NULL\n" .
+ $herecurr);
}
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
- $line !~ /\btypedef\s+$Type\s+\(\s*$Ident\s*\)\s*\(/ &&
+ $line !~ /\btypedef\s+$Type\s+\(\s*\*$Ident\s*\)\s*\(/ &&
$line !~ /\b__bitwise(?:__|)\b/) {
- print "do not add new typedefs\n";
- print "$herecurr";
- $clean = 0;
+ WARN("do not add new typedefs\n" . $herecurr);
}
# * goes on variable not on type
if ($line =~ m{\($NonptrType(\*+)(?:\s+const)?\)}) {
- print "\"(foo$1)\" should be \"(foo $1)\"\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("\"(foo$1)\" should be \"(foo $1)\"\n" .
+ $herecurr);
} elsif ($line =~ m{\($NonptrType\s+(\*+)(?!\s+const)\s+\)}) {
- print "\"(foo $1 )\" should be \"(foo $1)\"\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
+ $herecurr);
} elsif ($line =~ m{$NonptrType(\*+)(?:\s+const)?\s+[A-Za-z\d_]+}) {
- print "\"foo$1 bar\" should be \"foo $1bar\"\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
+ $herecurr);
} elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+const)\s+[A-Za-z\d_]+}) {
- print "\"foo $1 bar\" should be \"foo $1bar\"\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
+ $herecurr);
}
# # no BUG() or BUG_ON()
@@ -585,9 +628,7 @@ sub process {
}
}
if ($ok == 0) {
- print "printk() should include KERN_ facility level\n";
- print "$herecurr";
- $clean = 0;
+ WARN("printk() should include KERN_ facility level\n" . $herecurr);
}
}
@@ -595,9 +636,7 @@ sub process {
# or if closed on same line
if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).* {/) and
!($line=~/\#define.*do\s{/) and !($line=~/}/)) {
- print "braces following function declarations go on the next line\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
}
# Check operator spacing.
@@ -633,27 +672,27 @@ sub process {
}
# Pick up the preceeding and succeeding characters.
- my $ca = substr($opline, $off - 1, 1);
+ my $ca = substr($opline, 0, $off);
my $cc = '';
if (length($opline) >= ($off + length($elements[$n + 1]))) {
$cc = substr($opline, $off + length($elements[$n + 1]));
}
+ my $cb = "$ca$;$cc";
my $ctx = "${a}x${c}";
my $at = "(ctx:$ctx)";
my $ptr = (" " x $off) . "^";
- my $hereptr = "$hereline$ptr\n\n";
+ my $hereptr = "$hereline$ptr\n";
##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
# ; should have either the end of line or a space or \ after it
if ($op eq ';') {
- if ($ctx !~ /.x[WE]/ && $cc !~ /^\\/) {
- print "need space after that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ &&
+ $cc !~ /^;/) {
+ ERROR("need space after that '$op' $at\n" . $hereptr);
}
# // is a comment
@@ -662,43 +701,31 @@ sub process {
# -> should have no spaces
} elsif ($op eq '->') {
if ($ctx =~ /Wx.|.xW/) {
- print "no spaces around that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("no spaces around that '$op' $at\n" . $hereptr);
}
# , must have a space on the right.
} elsif ($op eq ',') {
if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
- print "need space after that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("need space after that '$op' $at\n" . $hereptr);
}
# unary ! and unary ~ are allowed no space on the right
} elsif ($op eq '!' or $op eq '~') {
if ($ctx !~ /[WOEB]x./) {
- print "need space before that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("need space before that '$op' $at\n" . $hereptr);
}
if ($ctx =~ /.xW/) {
- print "no space after that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("no space after that '$op' $at\n" . $hereptr);
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ($op eq '++' or $op eq '--') {
if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
- print "need space one side of that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("need space one side of that '$op' $at\n" . $hereptr);
}
if ($ctx =~ /Wx./ && $cc =~ /^;/) {
- print "no space before that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("no space before that '$op' $at\n" . $hereptr);
}
# & is both unary and binary
@@ -715,9 +742,7 @@ sub process {
#
} elsif ($op eq '&' or $op eq '-') {
if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
- print "need space before that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("need space before that '$op' $at\n" . $hereptr);
}
# * is the same as & only adding:
@@ -726,16 +751,9 @@ sub process {
# (foo **)
#
} elsif ($op eq '*') {
- if ($ca eq '*') {
- if ($cc =~ /^\s(?!\s*const)/) {
- print "no space after that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
- }
- } elsif ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
- print "need space before that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ if ($ca !~ /$Type$/ && $cb !~ /(\*$;|$;\*)/ &&
+ $ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
+ ERROR("need space before that '$op' $at\n" . $hereptr);
}
# << and >> may either have or not have spaces both sides
@@ -743,58 +761,51 @@ sub process {
$op eq '^' or $op eq '|')
{
if ($ctx !~ /VxV|WxW|VxE|WxE/) {
- print "need consistent spacing around '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("need consistent spacing around '$op' $at\n" .
+ $hereptr);
}
# All the others need spaces both sides.
} elsif ($ctx !~ /[EW]x[WE]/) {
- print "need spaces around that '$op' $at\n";
- print "$hereptr";
- $clean = 0;
+ ERROR("need spaces around that '$op' $at\n" . $hereptr);
}
$off += length($elements[$n + 1]);
}
}
#need space before brace following if, while, etc
- if ($line=~/\(.*\){/) {
- print "need a space before the brace\n";
- print "$herecurr";
- $clean = 0;
+ if ($line =~ /\(.*\){/ || $line =~ /do{/) {
+ ERROR("need a space before the open brace '{'\n" . $herecurr);
+ }
+
+# closing brace should have a space following it when it has anything
+# on the line
+ if ($line =~ /}(?!(?:,|;|\)))\S/) {
+ ERROR("need a space after that close brace '}'\n" . $herecurr);
}
#goto labels aren't indented, allow a single space however
if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
!($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
- print "labels should not be indented\n";
- print "$herecurr";
- $clean = 0;
+ WARN("labels should not be indented\n" . $herecurr);
}
# Need a space before open parenthesis after if, while etc
if ($line=~/\b(if|while|for|switch)\(/) {
- print "need a space before the open parenthesis\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("need a space before the open parenthesis '('\n" . $herecurr);
}
# Check for illegal assignment in if conditional.
if ($line=~/\bif\s*\(.*[^<>!=]=[^=].*\)/) {
#next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
- print "do not use assignment in if condition\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("do not use assignment in if condition\n" . $herecurr);
}
# Check for }<nl>else {, these must be at the same
# indent level to be relevant to each other.
if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
$previndent == $indent) {
- print "else should follow close brace\n";
- print "$hereprev";
- $clean = 0;
+ ERROR("else should follow close brace '}'\n" . $hereprev);
}
#studly caps, commented out until figure out how to distinguish between use of existing and adding new
@@ -806,57 +817,22 @@ sub process {
#no spaces allowed after \ in define
if ($line=~/\#define.*\\\s$/) {
- print("Whitepspace after \\ makes next lines useless\n");
- print "$herecurr";
- $clean = 0;
+ WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
}
#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
my $checkfile = "include/linux/$1.h";
if (-f $checkfile) {
- print "Use #include <linux/$1.h> instead of <asm/$1.h>\n";
- print $herecurr;
- $clean = 0;
- }
- }
-
-# if/while/etc brace do not go on next line, unless defining a do while loop,
-# or if that brace on the next line is for something else
- if ($prevline=~/\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/) {
- my @opened = $prevline=~/\(/g;
- my @closed = $prevline=~/\)/g;
- my $nr_line = $linenr;
- my $remaining = $realcnt - 1;
- my $next_line = $line;
- my $extra_lines = 0;
- my $display_segment = $prevline;
-
- while ($remaining > 0 && scalar @opened > scalar @closed) {
- $prevline .= $next_line;
- $display_segment .= "\n" . $next_line;
- $next_line = $lines[$nr_line];
- $nr_line++;
- $remaining--;
-
- @opened = $prevline=~/\(/g;
- @closed = $prevline=~/\)/g;
- }
-
- if (($prevline=~/\b(?:(if|while|for|switch)\s*\(.*\)|do|else)\s*$/) and ($next_line=~/{/) and
- !($next_line=~/\b(?:if|while|for|switch|do|else)\b/) and !($next_line=~/\#define.*do.*while/)) {
- print "That { should be on the previous line\n";
- print "$here\n$display_segment\n$next_line\n\n";
- $clean = 0;
+ CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
+ $herecurr);
}
}
# if and else should not have general statements after it
if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ &&
- $1 !~ /^\s*(?:\sif|{|$)/) {
- print "trailing statements should be on next line\n";
- print "$herecurr";
- $clean = 0;
+ $1 !~ /^\s*(?:\sif|{|\\|$)/) {
+ ERROR("trailing statements should be on next line\n" . $herecurr);
}
# multi-statement macros should be enclosed in a do while loop, grab the
@@ -877,49 +853,49 @@ sub process {
$ln--;
$cnt++;
}
- my $ctx = join('', ctx_statement($ln, $cnt));
+ my @ctx = ctx_statement($ln, $cnt);
+ my $ctx_ln = $ln + $#ctx + 1;
+ my $ctx = join("\n", @ctx);
+
+ # Pull in any empty extension lines.
+ while ($ctx =~ /\\$/ &&
+ $lines[$ctx_ln - 1] =~ /^.\s*(?:\\)?$/) {
+ $ctx .= $lines[$ctx_ln - 1];
+ $ctx_ln++;
+ }
if ($ctx =~ /\\$/) {
if ($ctx =~ /;/) {
- print "Macros with multiple statements should be enclosed in a do - while loop\n";
+ ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
} else {
- print "Macros with complex values should be enclosed in parenthesis\n";
+ ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
}
- print "$hereprev";
- $clean = 0;
}
}
# don't include deprecated include files (uses RAW line)
for my $inc (@dep_includes) {
if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
- print "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
}
}
# don't use deprecated functions
for my $func (@dep_functions) {
if ($line =~ /\b$func\b/) {
- print "Don't use $func(): see Documentation/feature-removal-schedule.txt\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
}
}
# no volatiles please
if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
- print "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n";
- print "$herecurr";
- $clean = 0;
+ WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
}
# warn about #if 0
if ($line =~ /^.#\s*if\s+0\b/) {
- print "#if 0 -- if this code redundant remove it\n";
- print "$herecurr";
- $clean = 0;
+ CHK("if this code is redundant consider removing it\n" .
+ $herecurr);
}
# warn about #ifdefs in C files
@@ -933,41 +909,47 @@ sub process {
if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
my $which = $1;
if (!ctx_has_comment($first_line, $linenr)) {
- print "$1 definition without comment\n";
- print "$herecurr";
- $clean = 0;
+ CHK("$1 definition without comment\n" . $herecurr);
}
}
# check for memory barriers without a comment.
if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
if (!ctx_has_comment($first_line, $linenr)) {
- print "memory barrier without comment\n";
- print "$herecurr";
- $clean = 0;
+ CHK("memory barrier without comment\n" . $herecurr);
}
}
# check of hardware specific defines
if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@) {
- print "architecture specific defines should be avoided\n";
- print "$herecurr";
- $clean = 0;
+ CHK("architecture specific defines should be avoided\n" . $herecurr);
}
+# check the location of the inline attribute, that it is between
+# storage class and type.
if ($line =~ /$Type\s+(?:inline|__always_inline)\b/ ||
$line =~ /\b(?:inline|always_inline)\s+$Storage/) {
- print "inline keyword should sit between storage class and type\n";
- print "$herecurr";
- $clean = 0;
+ ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
+ }
+
+# check for new externs in .c files.
+ if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
+ WARN("externs should be avoided in .c files\n" . $herecurr);
+ }
+
+# checks for new __setup's
+ if ($rawline =~ /\b__setup\("([^"]*)"/) {
+ my $name = $1;
+
+ if (!grep(/$name/, @setup_docs)) {
+ CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+ }
}
}
if ($chk_patch && !$is_patch) {
- $clean = 0;
- print "Does not appear to be a unified-diff format patch\n";
+ ERROR("Does not appear to be a unified-diff format patch\n");
}
if ($is_patch && $chk_signoff && $signoff == 0) {
- $clean = 0;
- print "Missing Signed-off-by: line(s)\n";
+ ERROR("Missing Signed-off-by: line(s)\n");
}
if ($clean == 1 && $quiet == 0) {
diff --git a/scripts/decodecode b/scripts/decodecode
new file mode 100644
index 000000000000..1e1a8f620c47
--- /dev/null
+++ b/scripts/decodecode
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Disassemble the Code: line in Linux oopses
+# usage: decodecode < oops.file
+#
+# options: set env. variable AFLAGS=options to pass options to "as";
+# e.g., to decode an i386 oops on an x86_64 system, use:
+# AFLAGS=--32 decodecode < 386.oops
+
+T=`mktemp`
+code=
+
+while read i ; do
+
+case "$i" in
+*Code:*)
+ code=$i
+ ;;
+esac
+
+done
+
+if [ -z "$code" ]; then
+ exit
+fi
+
+echo $code
+code=`echo $code | sed -e 's/.*Code: //'`
+
+marker=`expr index "$code" "\<"`
+if [ $marker -eq 0 ]; then
+ marker=`expr index "$code" "\("`
+fi
+
+if [ $marker -ne 0 ]; then
+ beforemark=`echo "$code" | cut -c-$((${marker} - 1))`
+ echo -n " .byte 0x" > $T.s
+ echo $beforemark | sed -e 's/ /,0x/g' >> $T.s
+ as $AFLAGS -o $T.o $T.s
+ objdump -S $T.o
+ rm $T.o $T.s
+
+# and fix code at-and-after marker
+ code=`echo "$code" | cut -c$((${marker} + 1))-`
+fi
+
+code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'`
+echo -n " .byte 0x" > $T.s
+echo $code >> $T.s
+as $AFLAGS -o $T.o $T.s
+objdump -S $T.o
+rm $T.o $T.s
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 8b809b264d18..10b006694e5d 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -31,7 +31,7 @@
#include <string.h>
#include <ctype.h>
-#define KSYM_NAME_LEN 127
+#define KSYM_NAME_LEN 128
struct sym_entry {
@@ -254,7 +254,7 @@ static void write_src(void)
unsigned int i, k, off;
unsigned int best_idx[256];
unsigned int *markers;
- char buf[KSYM_NAME_LEN+1];
+ char buf[KSYM_NAME_LEN];
printf("#include <asm/types.h>\n");
printf("#if BITS_PER_LONG == 64\n");
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 78c3f98fcdcf..520b9998123e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2318,7 +2318,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
return -EOPNOTSUPP;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ if (!is_owner_or_cap(inode))
return -EPERM;
AVC_AUDIT_DATA_INIT(&ad,FS);
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index ccfe8755735e..eddc7b420109 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -110,6 +110,8 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
{ AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
{ AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
+ { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
+ { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
};
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 4b30ae6d8ba5..866d4de8d4ab 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,35 +5,6 @@
#
# Prompt user for primary drivers.
-config OSS_OBSOLETE
- bool "Obsolete OSS drivers"
- depends on SOUND_PRIME
- help
- This option enables support for obsolete OSS drivers that
- are scheduled for removal in the near future.
-
- Please contact Adrian Bunk <bunk@stusta.de> if you had to
- say Y here because your hardware is not properly supported
- by ALSA.
-
- If unsure, say N.
-
-config SOUND_BT878
- tristate "BT878 audio dma"
- depends on SOUND_PRIME && PCI && OSS_OBSOLETE
- ---help---
- Audio DMA support for bt878 based grabber boards. As you might have
- already noticed, bt878 is listed with two functions in /proc/pci.
- Function 0 does the video stuff (bt848 compatible), function 1 does
- the same for audio data. This is a driver for the audio part of
- the chip. If you say 'Y' here you get a oss-compatible dsp device
- where you can record from. If you want just watch TV you probably
- don't need this driver as most TV cards handle sound with a short
- cable from the TV card to your sound card's line-in.
-
- To compile this driver as a module, choose M here: the module will
- be called btaudio.
-
config SOUND_BCM_CS4297A
tristate "Crystal Sound CS4297a (for Swarm)"
depends on SOUND_PRIME && SIBYTE_SWARM
@@ -44,13 +15,6 @@ config SOUND_BCM_CS4297A
note that CONFIG_KGDB should not be enabled at the same
time, since it also attempts to use this UART port.
-config SOUND_ICH
- tristate "Intel ICH (i8xx) audio support"
- depends on SOUND_PRIME && PCI && OSS_OBSOLETE
- help
- Support for integral audio in Intel's I/O Controller Hub (ICH)
- chipset, as used on the 810/820/840 motherboards.
-
config SOUND_VWSND
tristate "SGI Visual Workstation Sound"
depends on SOUND_PRIME && X86_VISWS
@@ -346,29 +310,9 @@ config MSND_FIFOSIZE
and Pinnacle). Larger values reduce the chance of data overruns at
the expense of overall latency. If unsure, use the default.
-config SOUND_VIA82CXXX
- tristate "VIA 82C686 Audio Codec"
- depends on SOUND_PRIME && PCI && OSS_OBSOLETE
- help
- Say Y here to include support for the audio codec found on VIA
- 82Cxxx-based chips. Typically these are built into a motherboard.
-
- DO NOT select Sound Blaster or Adlib with this driver, unless
- you have a Sound Blaster or Adlib card in addition to your VIA
- audio chip.
-
-config MIDI_VIA82CXXX
- bool "VIA 82C686 MIDI"
- depends on SOUND_VIA82CXXX && ISA_DMA_API
- help
- Answer Y to use the MIDI interface of the Via686. You may need to
- enable this in the BIOS before it will work. This is for connection
- to external MIDI hardware, and is not required for software playback
- of MIDI files.
-
config SOUND_OSS
tristate "OSS sound modules"
- depends on SOUND_PRIME && ISA_DMA_API
+ depends on SOUND_PRIME && ISA_DMA_API && VIRT_TO_BUS
help
OSS is the Open Sound System suite of sound card drivers. They make
sound programming easier since they provide a common API. Say Y or
@@ -400,23 +344,10 @@ config SOUND_DMAP
Say Y unless you have 16MB or more RAM or a PCI sound card.
-config SOUND_CS4232
- tristate "Crystal CS4232 based (PnP) cards"
- depends on SOUND_OSS && OSS_OBSOLETE
- help
- Say Y here if you have a card based on the Crystal CS4232 chip set,
- which uses its own Plug and Play protocol.
-
- If you compile the driver into the kernel, you have to add
- "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
- command line.
-
- See <file:Documentation/sound/oss/CS4232> for more information on
- configuring this card.
-
config SOUND_SSCAPE
tristate "Ensoniq SoundScape support"
depends on SOUND_OSS
+ depends on VIRT_TO_BUS
help
Answer Y if you have a sound card based on the Ensoniq SoundScape
chipset. Such cards are being manufactured at least by Ensoniq, Spea
@@ -719,13 +650,6 @@ config SOUND_WAVEARTIST
Say Y here to include support for the Rockwell WaveArtist sound
system. This driver is mainly for the NetWinder.
-config SOUND_TVMIXER
- tristate "TV card (bt848) mixer support"
- depends on SOUND_PRIME && I2C && VIDEO_V4L1 && OSS_OBSOLETE
- help
- Support for audio mixer facilities on the BT848 TV frame-grabber
- card.
-
config SOUND_KAHLUA
tristate "XpressAudio Sound Blaster emulation"
depends on SOUND_SB
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 2489bd6bb085..7a2f9ae7b7c5 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -18,20 +18,15 @@ obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_CS4232) += cs4232.o uart401.o
obj-$(CONFIG_SOUND_MSS) += ad1848.o
-obj-$(CONFIG_SOUND_OPL3SA2) += opl3sa2.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_KAHLUA) += kahlua.o
obj-$(CONFIG_SOUND_MPU401) += mpu401.o
obj-$(CONFIG_SOUND_UART6850) += uart6850.o
-obj-$(CONFIG_SOUND_ADLIB) += adlib_card.o opl3.o
obj-$(CONFIG_SOUND_YM3812) += opl3.o
obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o
obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
-obj-$(CONFIG_SOUND_AD1816) += ad1816.o
-obj-$(CONFIG_SOUND_AD1889) += ad1889.o ac97_codec.o
-obj-$(CONFIG_SOUND_ACI_MIXER) += aci.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o
ifeq ($(CONFIG_MIDI_VIA82CXXX),y)
@@ -40,24 +35,16 @@ endif
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
-obj-$(CONFIG_SOUND_NM256) += nm256_audio.o ac97.o
obj-$(CONFIG_SOUND_ICH) += i810_audio.o ac97_codec.o
obj-$(CONFIG_SOUND_ES1371) += es1371.o ac97_codec.o
obj-$(CONFIG_SOUND_VRC5477) += nec_vrc5477.o ac97_codec.o
obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o
-obj-$(CONFIG_SOUND_FUSION) += cs46xx.o ac97_codec.o
obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
-obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
obj-$(CONFIG_SOUND_BT878) += btaudio.o
obj-$(CONFIG_SOUND_WM97XX) += ac97_plugin_wm97xx.o
-ifeq ($(CONFIG_MIDI_EMU10K1),y)
- obj-$(CONFIG_SOUND_EMU10K1) += sound.o
-endif
-
-obj-$(CONFIG_SOUND_EMU10K1) += emu10k1/
obj-$(CONFIG_DMASOUND) += dmasound/
# Declare multi-part drivers.
diff --git a/sound/oss/ac97.c b/sound/oss/ac97.c
deleted file mode 100644
index 72cf4ed77937..000000000000
--- a/sound/oss/ac97.c
+++ /dev/null
@@ -1,432 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include "ac97.h"
-
-/* Flag for mono controls. */
-#define MO 0
-/* And for stereo. */
-#define ST 1
-
-/* Whether or not the bits in the channel are inverted. */
-#define INV 1
-#define NINV 0
-
-static struct ac97_chn_desc {
- int ac97_regnum;
- int oss_channel;
- int maxval;
- int is_stereo;
- int oss_mask;
- int recordNum;
- u16 regmask;
- int is_inverted;
-} mixerRegs[] = {
- { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME, 0x3f, ST, SOUND_MASK_VOLUME, 5, 0x0000, INV },
- { AC97_MASTER_VOL_MONO, SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000, INV },
- { AC97_MASTER_TONE, SOUND_MIXER_TREBLE, 0x0f, MO, SOUND_MASK_TREBLE, -1, 0x00ff, INV },
- { AC97_MASTER_TONE, SOUND_MIXER_BASS, 0x0f, MO, SOUND_MASK_BASS, -1, 0xff00, INV },
- { AC97_PCBEEP_VOL, SOUND_MIXER_SPEAKER, 0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e, INV },
- { AC97_PHONE_VOL, SOUND_MIXER_PHONEIN, 0x1f, MO, SOUND_MASK_PHONEIN, 7, 0x0000, INV },
- { AC97_MIC_VOL, SOUND_MIXER_MIC, 0x1f, MO, SOUND_MASK_MIC, 0, 0x0000, INV },
- { AC97_LINEIN_VOL, SOUND_MIXER_LINE, 0x1f, ST, SOUND_MASK_LINE, 4, 0x0000, INV },
- { AC97_CD_VOL, SOUND_MIXER_CD, 0x1f, ST, SOUND_MASK_CD, 1, 0x0000, INV },
- { AC97_VIDEO_VOL, SOUND_MIXER_VIDEO, 0x1f, ST, SOUND_MASK_VIDEO, 2, 0x0000, INV },
- { AC97_AUX_VOL, SOUND_MIXER_LINE1, 0x1f, ST, SOUND_MASK_LINE1, 3, 0x0000, INV },
- { AC97_PCMOUT_VOL, SOUND_MIXER_PCM, 0x1f, ST, SOUND_MASK_PCM, -1, 0x0000, INV },
- { AC97_RECORD_GAIN, SOUND_MIXER_IGAIN, 0x0f, ST, SOUND_MASK_IGAIN, -1, 0x0000, NINV },
- { -1, -1, 0xff, 0, 0, -1, 0x0000, 0 },
-};
-
-static struct ac97_chn_desc *
-ac97_find_chndesc (struct ac97_hwint *dev, int oss_channel)
-{
- int x;
-
- for (x = 0; mixerRegs[x].oss_channel != -1; x++) {
- if (mixerRegs[x].oss_channel == oss_channel)
- return mixerRegs + x;
- }
-
- return NULL;
-}
-
-static inline int
-ac97_is_valid_channel (struct ac97_hwint *dev, struct ac97_chn_desc *chn)
-{
- return (dev->last_written_mixer_values[chn->ac97_regnum / 2]
- != AC97_REG_UNSUPPORTED);
-}
-
-int
-ac97_init (struct ac97_hwint *dev)
-{
- int x;
- int reg0;
-
- /* Clear out the arrays of cached values. */
- for (x = 0; x < AC97_REG_CNT; x++)
- dev->last_written_mixer_values[x] = AC97_REGVAL_UNKNOWN;
-
- for (x = 0; x < SOUND_MIXER_NRDEVICES; x++)
- dev->last_written_OSS_values[x] = AC97_REGVAL_UNKNOWN;
-
- /* Clear the device masks. */
- dev->mixer_devmask = 0;
- dev->mixer_stereomask = 0;
- dev->mixer_recmask = 0;
-
- /* ??? Do a "standard reset" via register 0? */
-
- /* Hardware-dependent reset. */
- if (dev->reset_device (dev))
- return -1;
-
- /* Check the mixer device capabilities. */
- reg0 = dev->read_reg (dev, AC97_RESET);
-
- if (reg0 < 0)
- return -1;
-
- /* Check for support for treble/bass controls. */
- if (! (reg0 & 4)) {
- dev->last_written_mixer_values[AC97_MASTER_TONE / 2]
- = AC97_REG_UNSUPPORTED;
- }
-
- /* ??? There may be other tests here? */
-
- /* Fill in the device masks. */
- for (x = 0; mixerRegs[x].ac97_regnum != -1; x++) {
- if (ac97_is_valid_channel (dev, mixerRegs + x)) {
- dev->mixer_devmask |= mixerRegs[x].oss_mask;
-
- if (mixerRegs[x].is_stereo)
- dev->mixer_stereomask |= mixerRegs[x].oss_mask;
-
- if (mixerRegs[x].recordNum != -1)
- dev->mixer_recmask |= mixerRegs[x].oss_mask;
- }
- }
-
- return 0;
-}
-
-/* Return the contents of register REG; use the cache if the value in it
- is valid. Returns a negative error code on failure. */
-static int
-ac97_get_register (struct ac97_hwint *dev, u8 reg)
-{
- if (reg > 127 || (reg & 1))
- return -EINVAL;
-
- /* See if it's in the cache, or if it's just plain invalid. */
- switch (dev->last_written_mixer_values[reg / 2]) {
- case AC97_REG_UNSUPPORTED:
- return -EINVAL;
- break;
- case AC97_REGVAL_UNKNOWN:
- dev->last_written_mixer_values[reg / 2] = dev->read_reg (dev, reg);
- break;
- default:
- break;
- }
- return dev->last_written_mixer_values[reg / 2];
-}
-
-/* Write VALUE to AC97 register REG, and cache its value in the last-written
- cache. Returns a negative error code on failure, or 0 on success. */
-int
-ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value)
-{
- if (reg > 127 || (reg & 1))
- return -EINVAL;
-
- if (dev->last_written_mixer_values[reg / 2] == AC97_REG_UNSUPPORTED)
- return -EINVAL;
- else {
- int res = dev->write_reg (dev, reg, value);
- if (res >= 0) {
- dev->last_written_mixer_values[reg / 2] = value;
- return 0;
- }
- else
- return res;
- }
-}
-
-/* Scale VALUE (a value fro 0 to MAXVAL) to a value from 0-100. If
- IS_STEREO is set, VALUE is a stereo value; the left channel value
- is in the lower 8 bits, and the right channel value is in the upper
- 8 bits.
-
- A negative error code is returned on failure, or the unsigned
- scaled value on success. */
-
-static int
-ac97_scale_to_oss_val (int value, int maxval, int is_stereo, int inv)
-{
- /* Muted? */
- if (value & AC97_MUTE)
- return 0;
-
- if (is_stereo)
- return (ac97_scale_to_oss_val (value & 255, maxval, 0, inv) << 8)
- | (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
- else {
- int i;
-
- /* Inverted. */
- if (inv)
- value = maxval - value;
-
- i = (value * 100 + (maxval / 2)) / maxval;
- if (i > 100)
- i = 100;
- if (i < 0)
- i = 0;
- return i;
- }
-}
-
-static int
-ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv)
-{
- if (is_stereo)
- return (ac97_scale_from_oss_val (value & 255, maxval, 0, inv) << 8)
- | (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
- else {
- int i = ((value & 255) * maxval + 50) / 100;
- if (inv)
- i = maxval - i;
- if (i < 0)
- i = 0;
- if (i > maxval)
- i = maxval;
- return i;
- }
-}
-
-static int
-ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value)
-{
- int scaled_value;
- struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel);
- int result;
-
- if (channel == NULL)
- return -ENODEV;
- if (! ac97_is_valid_channel (dev, channel))
- return -ENODEV;
- scaled_value = ac97_scale_from_oss_val (oss_value, channel->maxval,
- channel->is_stereo,
- channel->is_inverted);
- if (scaled_value < 0)
- return scaled_value;
-
- if (channel->regmask != 0) {
- int mv;
-
- int oldval = ac97_get_register (dev, channel->ac97_regnum);
- if (oldval < 0)
- return oldval;
-
- for (mv = channel->regmask; ! (mv & 1); mv >>= 1)
- scaled_value <<= 1;
-
- scaled_value &= channel->regmask;
- scaled_value |= (oldval & ~channel->regmask);
- }
- result = ac97_put_register (dev, channel->ac97_regnum, scaled_value);
- if (result == 0)
- dev->last_written_OSS_values[oss_channel] = oss_value;
- return result;
-}
-
-static int
-ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel)
-{
- struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel);
- int regval;
-
- if (channel == NULL)
- return -ENODEV;
-
- if (! ac97_is_valid_channel (dev, channel))
- return -ENODEV;
-
- regval = ac97_get_register (dev, channel->ac97_regnum);
-
- if (regval < 0)
- return regval;
-
- if (channel->regmask != 0) {
- int mv;
-
- regval &= channel->regmask;
-
- for (mv = channel->regmask; ! (mv & 1); mv >>= 1)
- regval >>= 1;
- }
- return ac97_scale_to_oss_val (regval, channel->maxval,
- channel->is_stereo,
- channel->is_inverted);
-}
-
-static int
-ac97_get_recmask (struct ac97_hwint *dev)
-{
- int recReg = ac97_get_register (dev, AC97_RECORD_SELECT);
-
- if (recReg < 0)
- return recReg;
- else {
- int x;
- for (x = 0; mixerRegs[x].ac97_regnum >= 0; x++) {
- if (mixerRegs[x].recordNum == (recReg & 7))
- return mixerRegs[x].oss_mask;
- }
- return -ENODEV;
- }
-}
-
-static int
-ac97_set_recmask (struct ac97_hwint *dev, int oss_recmask)
-{
- int x;
-
- if (oss_recmask == 0)
- oss_recmask = SOUND_MIXER_MIC;
-
- for (x = 0; mixerRegs[x].ac97_regnum >= 0; x++) {
- if ((mixerRegs[x].recordNum >= 0)
- && (oss_recmask & mixerRegs[x].oss_mask))
- break;
- }
- if (mixerRegs[x].ac97_regnum < 0)
- return -ENODEV;
- else {
- int regval = (mixerRegs[x].recordNum << 8) | mixerRegs[x].recordNum;
- int res = ac97_put_register (dev, AC97_RECORD_SELECT, regval);
- if (res == 0)
- return ac97_get_recmask (dev);
- else
- return res;
- }
-}
-
-/* Set the mixer DEV to the list of values in VALUE_LIST. Return 0 on
- success, or a negative error code. */
-int
-ac97_set_values (struct ac97_hwint *dev,
- struct ac97_mixer_value_list *value_list)
-{
- int x;
-
- for (x = 0; value_list[x].oss_channel != -1; x++) {
- int chnum = value_list[x].oss_channel;
- struct ac97_chn_desc *chent = ac97_find_chndesc (dev, chnum);
- if (chent != NULL) {
- u16 val;
- int res;
-
- if (chent->is_stereo)
- val = (value_list[x].value.stereo.right << 8)
- | value_list[x].value.stereo.left;
- else {
- /* We do this so the returned value looks OK in the
- mixer app. It's not necessary otherwise. */
- val = (value_list[x].value.mono << 8)
- | value_list[x].value.mono;
- }
- res = ac97_set_mixer (dev, chnum, val);
- if (res < 0)
- return res;
- }
- else
- return -ENODEV;
- }
- return 0;
-}
-
-int
-ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, void __user *arg)
-{
- int ret;
-
- switch (cmd) {
- case SOUND_MIXER_READ_RECSRC:
- ret = ac97_get_recmask (dev);
- break;
-
- case SOUND_MIXER_WRITE_RECSRC:
- {
- if (get_user (ret, (int __user *) arg))
- ret = -EFAULT;
- else
- ret = ac97_set_recmask (dev, ret);
- }
- break;
-
- case SOUND_MIXER_READ_CAPS:
- ret = SOUND_CAP_EXCL_INPUT;
- break;
-
- case SOUND_MIXER_READ_DEVMASK:
- ret = dev->mixer_devmask;
- break;
-
- case SOUND_MIXER_READ_RECMASK:
- ret = dev->mixer_recmask;
- break;
-
- case SOUND_MIXER_READ_STEREODEVS:
- ret = dev->mixer_stereomask;
- break;
-
- default:
- /* Read or write request. */
- ret = -EINVAL;
- if (_IOC_TYPE (cmd) == 'M') {
- int dir = _SIOC_DIR (cmd);
- int channel = _IOC_NR (cmd);
-
- if (channel >= 0 && channel < SOUND_MIXER_NRDEVICES) {
- ret = 0;
- if (dir & _SIOC_WRITE) {
- int val;
- if (get_user (val, (int __user *) arg) == 0)
- ret = ac97_set_mixer (dev, channel, val);
- else
- ret = -EFAULT;
- }
- if (ret >= 0 && (dir & _SIOC_READ)) {
- if (dev->last_written_OSS_values[channel]
- == AC97_REGVAL_UNKNOWN)
- dev->last_written_OSS_values[channel]
- = ac97_get_mixer_scaled (dev, channel);
- ret = dev->last_written_OSS_values[channel];
- }
- }
- }
- break;
- }
-
- if (ret < 0)
- return ret;
- else
- return put_user(ret, (int __user *) arg);
-}
-
-EXPORT_SYMBOL(ac97_init);
-EXPORT_SYMBOL(ac97_set_values);
-EXPORT_SYMBOL(ac97_put_register);
-EXPORT_SYMBOL(ac97_mixer_ioctl);
-MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/ac97.h b/sound/oss/ac97.h
deleted file mode 100644
index 01837a9d7d6e..000000000000
--- a/sound/oss/ac97.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * ac97.h
- *
- * definitions for the AC97, Intel's Audio Codec 97 Spec
- * also includes support for a generic AC97 interface
- */
-
-#ifndef _AC97_H_
-#define _AC97_H_
-#include "sound_config.h"
-#include "sound_calls.h"
-
-#define AC97_RESET 0x0000 //
-#define AC97_MASTER_VOL_STEREO 0x0002 // Line Out
-#define AC97_HEADPHONE_VOL 0x0004 //
-#define AC97_MASTER_VOL_MONO 0x0006 // TAD Output
-#define AC97_MASTER_TONE 0x0008 //
-#define AC97_PCBEEP_VOL 0x000a // none
-#define AC97_PHONE_VOL 0x000c // TAD Input (mono)
-#define AC97_MIC_VOL 0x000e // MIC Input (mono)
-#define AC97_LINEIN_VOL 0x0010 // Line Input (stereo)
-#define AC97_CD_VOL 0x0012 // CD Input (stereo)
-#define AC97_VIDEO_VOL 0x0014 // none
-#define AC97_AUX_VOL 0x0016 // Aux Input (stereo)
-#define AC97_PCMOUT_VOL 0x0018 // Wave Output (stereo)
-#define AC97_RECORD_SELECT 0x001a //
-#define AC97_RECORD_GAIN 0x001c
-#define AC97_RECORD_GAIN_MIC 0x001e
-#define AC97_GENERAL_PURPOSE 0x0020
-#define AC97_3D_CONTROL 0x0022
-#define AC97_MODEM_RATE 0x0024
-#define AC97_POWER_CONTROL 0x0026
-
-/* registers 0x0028 - 0x0058 are reserved */
-
-/* AC'97 2.0 */
-#define AC97_EXTENDED_ID 0x0028 /* Extended Audio ID */
-#define AC97_EXTENDED_STATUS 0x002A /* Extended Audio Status */
-#define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */
-#define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */
-#define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */
-#define AC97_PCM_LR_ADC_RATE 0x0032 /* PCM LR DAC Rate */
-#define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */
-#define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */
-#define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */
-#define AC97_RESERVED_3A 0x003A /* Reserved */
-/* range 0x3c-0x58 - MODEM */
-
-/* registers 0x005a - 0x007a are vendor reserved */
-
-#define AC97_VENDOR_ID1 0x007c
-#define AC97_VENDOR_ID2 0x007e
-
-/* volume control bit defines */
-
-#define AC97_MUTE 0x8000
-#define AC97_MICBOOST 0x0040
-#define AC97_LEFTVOL 0x3f00
-#define AC97_RIGHTVOL 0x003f
-
-/* record mux defines */
-
-#define AC97_RECMUX_MIC 0x0000
-#define AC97_RECMUX_CD 0x0101
-#define AC97_RECMUX_VIDEO 0x0202 /* not used */
-#define AC97_RECMUX_AUX 0x0303
-#define AC97_RECMUX_LINE 0x0404
-#define AC97_RECMUX_STEREO_MIX 0x0505
-#define AC97_RECMUX_MONO_MIX 0x0606
-#define AC97_RECMUX_PHONE 0x0707
-
-
-/* general purpose register bit defines */
-
-#define AC97_GP_LPBK 0x0080 /* Loopback mode */
-#define AC97_GP_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 */
-#define AC97_GP_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic */
-#define AC97_GP_RLBK 0x0400 /* Remote Loopback - Modem line codec */
-#define AC97_GP_LLBK 0x0800 /* Local Loopback - Modem Line codec */
-#define AC97_GP_LD 0x1000 /* Loudness 1=on */
-#define AC97_GP_3D 0x2000 /* 3D Enhancement 1=on */
-#define AC97_GP_ST 0x4000 /* Stereo Enhancement 1=on */
-#define AC97_GP_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */
-
-
-/* powerdown control and status bit defines */
-
-/* status */
-#define AC97_PWR_MDM 0x0010 /* Modem section ready */
-#define AC97_PWR_REF 0x0008 /* Vref nominal */
-#define AC97_PWR_ANL 0x0004 /* Analog section ready */
-#define AC97_PWR_DAC 0x0002 /* DAC section ready */
-#define AC97_PWR_ADC 0x0001 /* ADC section ready */
-
-/* control */
-#define AC97_PWR_PR0 0x0100 /* ADC and Mux powerdown */
-#define AC97_PWR_PR1 0x0200 /* DAC powerdown */
-#define AC97_PWR_PR2 0x0400 /* Output mixer powerdown (Vref on) */
-#define AC97_PWR_PR3 0x0800 /* Output mixer powerdown (Vref off) */
-#define AC97_PWR_PR4 0x1000 /* AC-link powerdown */
-#define AC97_PWR_PR5 0x2000 /* Internal Clk disable */
-#define AC97_PWR_PR6 0x4000 /* HP amp powerdown */
-#define AC97_PWR_PR7 0x8000 /* Modem off - if supported */
-
-/* useful power states */
-#define AC97_PWR_D0 0x0000 /* everything on */
-#define AC97_PWR_D1 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4
-#define AC97_PWR_D2 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
-#define AC97_PWR_D3 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
-#define AC97_PWR_ANLOFF AC97_PWR_PR2|AC97_PWR_PR3 /* analog section off */
-
-/* Total number of defined registers. */
-#define AC97_REG_CNT 64
-
-/* Generic AC97 mixer interface. */
-
-/* Structure describing access to the hardware. */
-struct ac97_hwint
-{
- /* Perform any hardware-specific reset and initialization. Returns
- 0 on success, or a negative error code. */
- int (*reset_device) (struct ac97_hwint *dev);
-
- /* Returns the contents of the specified register REG. The caller
- should check to see if the desired contents are available in
- the cache first, if applicable. Returns a positive unsigned value
- representing the contents of the register, or a negative error
- code. */
- int (*read_reg) (struct ac97_hwint *dev, u8 reg);
-
- /* Writes VALUE to register REG. Returns 0 on success, or a
- negative error code. */
- int (*write_reg) (struct ac97_hwint *dev, u8 reg, u16 value);
-
- /* Hardware-specific information. */
- void *driver_private;
-
- /* Three OSS masks. */
- int mixer_devmask;
- int mixer_stereomask;
- int mixer_recmask;
-
- /* The mixer cache. The indices correspond to the AC97 hardware register
- number / 2, since the register numbers are always an even number.
-
- Unknown values are set to -1; unsupported registers contain a
- -2. */
- int last_written_mixer_values[AC97_REG_CNT];
-
- /* A cache of values written via OSS; we need these so we can return
- the values originally written by the user.
-
- Why the original user values? Because the real-world hardware
- has less precision, and some existing applications assume that
- they will get back the exact value that they wrote (aumix).
-
- A -1 value indicates that no value has been written to this mixer
- channel via OSS. */
- int last_written_OSS_values[SOUND_MIXER_NRDEVICES];
-};
-
-/* Values stored in the register cache. */
-#define AC97_REGVAL_UNKNOWN -1
-#define AC97_REG_UNSUPPORTED -2
-
-struct ac97_mixer_value_list
-{
- /* Mixer channel to set. List is terminated by a value of -1. */
- int oss_channel;
- /* The scaled value to set it to; values generally range from 0-100. */
- union {
- struct {
- u8 left, right;
- } stereo;
- u8 mono;
- } value;
-};
-
-/* Initialize the ac97 mixer by resetting it. */
-extern int ac97_init (struct ac97_hwint *dev);
-
-/* Sets the mixer DEV to the values in VALUE_LIST. Returns 0 on success,
- or a negative error code. */
-extern int ac97_set_values (struct ac97_hwint *dev,
- struct ac97_mixer_value_list *value_list);
-
-/* Writes the specified VALUE to the AC97 register REG in the mixer.
- Takes care of setting the last-written cache as well. */
-extern int ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value);
-
-/* Default ioctl. */
-extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd,
- void __user * arg);
-
-#endif
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/aci.c b/sound/oss/aci.c
deleted file mode 100644
index 3bfac375dbdb..000000000000
--- a/sound/oss/aci.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Audio Command Interface (ACI) driver (sound/aci.c)
- *
- * ACI is a protocol used to communicate with the microcontroller on
- * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
- * PCM20. The ACI has been developed for miro by Norberto Pellicci
- * <pellicci@home.com>. Special thanks to both him and miro for
- * providing the ACI specification.
- *
- * The main function of the ACI is to control the mixer and to get a
- * product identification. On the PCM20, ACI also controls the radio
- * tuner on this card, this is supported in the Video for Linux
- * miropcm20 driver.
- * -
- * This is a fullfeatured implementation. Unsupported features
- * are bugs... (:
- *
- * It is not longer necessary to load the mad16 module first. The
- * user is currently responsible to set the mad16 mixer correctly.
- *
- * To toggle the solo mode for full duplex operation just use the OSS
- * record switch for the pcm ('wave') controller. Robert
- * -
- *
- * Revision history:
- *
- * 1995-11-10 Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
- * First version written.
- * 1995-12-31 Markus Kuhn
- * Second revision, general code cleanup.
- * 1996-05-16 Hannu Savolainen
- * Integrated with other parts of the driver.
- * 1996-05-28 Markus Kuhn
- * Initialize CS4231A mixer, make ACI first mixer,
- * use new private mixer API for solo mode.
- * 1998-08-18 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- * Small modification to export ACI functions and
- * complete modularisation.
- * 2000-06-20 Robert Siemer <Robert.Siemer@gmx.de>
- * Don't initialize the CS4231A mixer anymore, so the code is
- * working again, and other small changes to fit in todays
- * kernels.
- * 2000-08-26 Robert Siemer
- * Clean up and rewrite for 2.4.x. Maybe it's SMP safe now... (:
- * ioctl bugfix, and integration of solo-mode into OSS-API,
- * added (OSS-limited) equalizer support, return value bugfix,
- * changed param aci_reset to reset, new params: ide, wss.
- * 2001-04-20 Robert Siemer
- * even more cleanups...
- * 2001-10-08 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * Get rid of check_region, .bss optimizations, use set_current_state
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include "sound_config.h"
-
-int aci_port; /* as determined by bit 4 in the OPTi 929 MC4 register */
-static int aci_idcode[2]; /* manufacturer and product ID */
-int aci_version; /* ACI firmware version */
-
-EXPORT_SYMBOL(aci_port);
-EXPORT_SYMBOL(aci_version);
-
-#include "aci.h"
-
-
-static int aci_solo; /* status bit of the card that can't be *
- * checked with ACI versions prior to 0xb0 */
-static int aci_amp; /* status bit for power-amp/line-out level
- but I have no docs about what is what... */
-static int aci_micpreamp=3; /* microphone preamp-level that can't be *
- * checked with ACI versions prior to 0xb0 */
-
-static int mixer_device;
-static struct mutex aci_mutex;
-
-#ifdef MODULE
-static int reset;
-module_param(reset, bool, 0);
-MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer.");
-#else
-static int reset = 1;
-#endif
-
-static int ide=-1;
-module_param(ide, int, 0);
-MODULE_PARM_DESC(ide,"1 enable, 0 disable ide-port - untested"
- " default: do nothing");
-static int wss=-1;
-module_param(wss, int, 0);
-MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested"
- " default: do nothing; for PCM1-pro only");
-
-#ifdef DEBUG
-static void print_bits(unsigned char c)
-{
- int j;
- printk(KERN_DEBUG "aci: ");
-
- for (j=7; j>=0; j--) {
- printk("%d", (c >> j) & 0x1);
- }
-
- printk("\n");
-}
-#endif
-
-/*
- * This busy wait code normally requires less than 15 loops and
- * practically always less than 100 loops on my i486/DX2 66 MHz.
- *
- * Warning: Waiting on the general status flag after reseting the MUTE
- * function can take a VERY long time, because the PCM12 does some kind
- * of fade-in effect. For this reason, access to the MUTE function has
- * not been implemented at all.
- *
- * - The OSS interface has no mute option. It takes about 3 seconds to
- * fade-in on my PCM20. busy_wait() handles it great now... Robert
- */
-
-static int busy_wait(void)
-{
- #define MINTIME 500
- long timeout;
- unsigned char byte;
-
- for (timeout = 1; timeout <= MINTIME+30; timeout++) {
- if (((byte=inb(BUSY_REGISTER)) & 1) == 0) {
- if (timeout >= MINTIME)
- printk(KERN_DEBUG "aci: Got READYFLAG in round %ld.\n", timeout-MINTIME);
- return byte;
- }
- if (timeout >= MINTIME) {
- long out=10*HZ;
- switch (timeout-MINTIME) {
- case 0 ... 9:
- out /= 10;
- case 10 ... 19:
- out /= 10;
- case 20 ... 30:
- out /= 10;
- default:
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(out);
- break;
- }
- }
- }
- printk(KERN_WARNING "aci: busy_wait() time out.\n");
- return -EBUSY;
-}
-
-/* The four ACI command types are fucked up. [-:
- * implied is: 1w - special case for INIT
- * write is: 2w1r
- * read is: x(1w1r) where x is 1 or 2 (1 CHECK_SIG, 1 CHECK_STER,
- * 1 VERSION, 2 IDCODE)
- * the command is only in the first write, rest is protocol overhead
- *
- * indexed is technically a write and used for STATUS
- * and the special case for TUNE is: 3w1r
- *
- * Here the new general sheme: TUNE --> aci_rw_cmd(x, y, z)
- * indexed and write --> aci_rw_cmd(x, y, -1)
- * implied and read (x=1) --> aci_rw_cmd(x, -1, -1)
- *
- * Read (x>=2) is not implemented (only used during initialization).
- * Use aci_idcode[2] and aci_version... Robert
- */
-
-/* Some notes for error detection: theoretically it is possible.
- * But it doubles the I/O-traffic from ww(r) to wwwrw(r) in the normal
- * case and doesn't seem to be designed for that... Robert
- */
-
-static inline int aci_rawwrite(unsigned char byte)
-{
- if (busy_wait() >= 0) {
-#ifdef DEBUG
- printk(KERN_DEBUG "aci_rawwrite(%d)\n", byte);
-#endif
- outb(byte, COMMAND_REGISTER);
- return 0;
- } else
- return -EBUSY;
-}
-
-static inline int aci_rawread(void)
-{
- unsigned char byte;
-
- if (busy_wait() >= 0) {
- byte=inb(STATUS_REGISTER);
-#ifdef DEBUG
- printk(KERN_DEBUG "%d = aci_rawread()\n", byte);
-#endif
- return byte;
- } else
- return -EBUSY;
-}
-
-
-int aci_rw_cmd(int write1, int write2, int write3)
-{
- int write[] = {write1, write2, write3};
- int read = -EINTR, i;
-
- if (mutex_lock_interruptible(&aci_mutex))
- goto out;
-
- for (i=0; i<3; i++) {
- if (write[i]< 0 || write[i] > 255)
- break;
- else {
- read = aci_rawwrite(write[i]);
- if (read < 0)
- goto out_up;
- }
-
- }
-
- read = aci_rawread();
-out_up: mutex_unlock(&aci_mutex);
-out: return read;
-}
-
-EXPORT_SYMBOL(aci_rw_cmd);
-
-static int setvolume(int __user *arg,
- unsigned char left_index, unsigned char right_index)
-{
- int vol, ret, uservol, buf;
-
- __get_user(uservol, arg);
-
- /* left channel */
- vol = uservol & 0xff;
- if (vol > 100)
- vol = 100;
- vol = SCALE(100, 0x20, vol);
- if ((buf=aci_write_cmd(left_index, 0x20 - vol))<0)
- return buf;
- ret = SCALE(0x20, 100, vol);
-
-
- /* right channel */
- vol = (uservol >> 8) & 0xff;
- if (vol > 100)
- vol = 100;
- vol = SCALE(100, 0x20, vol);
- if ((buf=aci_write_cmd(right_index, 0x20 - vol))<0)
- return buf;
- ret |= SCALE(0x20, 100, vol) << 8;
-
- __put_user(ret, arg);
-
- return 0;
-}
-
-static int getvolume(int __user *arg,
- unsigned char left_index, unsigned char right_index)
-{
- int vol;
- int buf;
-
- /* left channel */
- if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
- return buf;
- vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
-
- /* right channel */
- if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
- return buf;
- vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
-
- __put_user(vol, arg);
-
- return 0;
-}
-
-
-/* The equalizer is somewhat strange on the ACI. From -12dB to +12dB
- * write: 0xff..down.to..0x80==0x00..up.to..0x7f
- */
-
-static inline unsigned int eq_oss2aci(unsigned int vol)
-{
- int boost=0;
- unsigned int ret;
-
- if (vol > 100)
- vol = 100;
- if (vol > 50) {
- vol -= 51;
- boost=1;
- }
- if (boost)
- ret=SCALE(49, 0x7e, vol)+1;
- else
- ret=0xff - SCALE(50, 0x7f, vol);
- return ret;
-}
-
-static inline unsigned int eq_aci2oss(unsigned int vol)
-{
- if (vol < 0x80)
- return SCALE(0x7f, 50, vol) + 50;
- else
- return SCALE(0x7f, 50, 0xff-vol);
-}
-
-
-static int setequalizer(int __user *arg,
- unsigned char left_index, unsigned char right_index)
-{
- int buf;
- unsigned int vol;
-
- __get_user(vol, arg);
-
- /* left channel */
- if ((buf=aci_write_cmd(left_index, eq_oss2aci(vol & 0xff)))<0)
- return buf;
-
- /* right channel */
- if ((buf=aci_write_cmd(right_index, eq_oss2aci((vol>>8) & 0xff)))<0)
- return buf;
-
- /* the ACI equalizer is more precise */
- return 0;
-}
-
-static int getequalizer(int __user *arg,
- unsigned char left_index, unsigned char right_index)
-{
- int buf;
- unsigned int vol;
-
- /* left channel */
- if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
- return buf;
- vol = eq_aci2oss(buf);
-
- /* right channel */
- if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
- return buf;
- vol |= eq_aci2oss(buf) << 8;
-
- __put_user(vol, arg);
-
- return 0;
-}
-
-static int aci_mixer_ioctl (int dev, unsigned int cmd, void __user * arg)
-{
- int vol, buf;
- int __user *p = arg;
-
- switch (cmd) {
- case SOUND_MIXER_WRITE_VOLUME:
- return setvolume(p, 0x01, 0x00);
- case SOUND_MIXER_WRITE_CD:
- return setvolume(p, 0x3c, 0x34);
- case SOUND_MIXER_WRITE_MIC:
- return setvolume(p, 0x38, 0x30);
- case SOUND_MIXER_WRITE_LINE:
- return setvolume(p, 0x39, 0x31);
- case SOUND_MIXER_WRITE_SYNTH:
- return setvolume(p, 0x3b, 0x33);
- case SOUND_MIXER_WRITE_PCM:
- return setvolume(p, 0x3a, 0x32);
- case MIXER_WRITE(SOUND_MIXER_RADIO): /* fall through */
- case SOUND_MIXER_WRITE_LINE1: /* AUX1 or radio */
- return setvolume(p, 0x3d, 0x35);
- case SOUND_MIXER_WRITE_LINE2: /* AUX2 */
- return setvolume(p, 0x3e, 0x36);
- case SOUND_MIXER_WRITE_BASS: /* set band one and two */
- if (aci_idcode[1]=='C') {
- if ((buf=setequalizer(p, 0x48, 0x40)) ||
- (buf=setequalizer(p, 0x49, 0x41)));
- return buf;
- }
- break;
- case SOUND_MIXER_WRITE_TREBLE: /* set band six and seven */
- if (aci_idcode[1]=='C') {
- if ((buf=setequalizer(p, 0x4d, 0x45)) ||
- (buf=setequalizer(p, 0x4e, 0x46)));
- return buf;
- }
- break;
- case SOUND_MIXER_WRITE_IGAIN: /* MIC pre-amp */
- if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
- __get_user(vol, p);
- vol = vol & 0xff;
- if (vol > 100)
- vol = 100;
- vol = SCALE(100, 3, vol);
- if ((buf=aci_write_cmd(ACI_WRITE_IGAIN, vol))<0)
- return buf;
- aci_micpreamp = vol;
- vol = SCALE(3, 100, vol);
- vol |= (vol << 8);
- __put_user(vol, p);
- return 0;
- }
- break;
- case SOUND_MIXER_WRITE_OGAIN: /* Power-amp/line-out level */
- if (aci_idcode[1]=='A' || aci_idcode[1]=='B') {
- __get_user(buf, p);
- buf = buf & 0xff;
- if (buf > 50)
- vol = 1;
- else
- vol = 0;
- if ((buf=aci_write_cmd(ACI_SET_POWERAMP, vol))<0)
- return buf;
- aci_amp = vol;
- if (aci_amp)
- buf = (100 || 100<<8);
- else
- buf = 0;
- __put_user(buf, p);
- return 0;
- }
- break;
- case SOUND_MIXER_WRITE_RECSRC:
- /* handle solo mode control */
- __get_user(buf, p);
- /* unset solo when RECSRC for PCM is requested */
- if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
- vol = !(buf & SOUND_MASK_PCM);
- if ((buf=aci_write_cmd(ACI_SET_SOLOMODE, vol))<0)
- return buf;
- aci_solo = vol;
- }
- buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
- SOUND_MASK_SYNTH| SOUND_MASK_LINE2);
- if (aci_idcode[1] == 'C') /* PCM20 radio */
- buf |= SOUND_MASK_RADIO;
- else
- buf |= SOUND_MASK_LINE1;
- if (!aci_solo)
- buf |= SOUND_MASK_PCM;
- __put_user(buf, p);
- return 0;
- case SOUND_MIXER_READ_DEVMASK:
- buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD |
- SOUND_MASK_MIC | SOUND_MASK_LINE |
- SOUND_MASK_SYNTH | SOUND_MASK_PCM |
- SOUND_MASK_LINE2);
- switch (aci_idcode[1]) {
- case 'C': /* PCM20 radio */
- buf |= (SOUND_MASK_RADIO | SOUND_MASK_IGAIN |
- SOUND_MASK_BASS | SOUND_MASK_TREBLE);
- break;
- case 'B': /* PCM12 */
- buf |= (SOUND_MASK_LINE1 | SOUND_MASK_IGAIN |
- SOUND_MASK_OGAIN);
- break;
- case 'A': /* PCM1-pro */
- buf |= (SOUND_MASK_LINE1 | SOUND_MASK_OGAIN);
- break;
- default:
- buf |= SOUND_MASK_LINE1;
- }
- __put_user(buf, p);
- return 0;
- case SOUND_MIXER_READ_STEREODEVS:
- buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD |
- SOUND_MASK_MIC | SOUND_MASK_LINE |
- SOUND_MASK_SYNTH | SOUND_MASK_PCM |
- SOUND_MASK_LINE2);
- switch (aci_idcode[1]) {
- case 'C': /* PCM20 radio */
- buf |= (SOUND_MASK_RADIO |
- SOUND_MASK_BASS | SOUND_MASK_TREBLE);
- break;
- default:
- buf |= SOUND_MASK_LINE1;
- }
- __put_user(buf, p);
- return 0;
- case SOUND_MIXER_READ_RECMASK:
- buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
- SOUND_MASK_SYNTH| SOUND_MASK_LINE2| SOUND_MASK_PCM);
- if (aci_idcode[1] == 'C') /* PCM20 radio */
- buf |= SOUND_MASK_RADIO;
- else
- buf |= SOUND_MASK_LINE1;
-
- __put_user(buf, p);
- return 0;
- case SOUND_MIXER_READ_RECSRC:
- buf = (SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE |
- SOUND_MASK_SYNTH | SOUND_MASK_LINE2);
- /* do we need aci_solo or can I get it from the ACI? */
- switch (aci_idcode[1]) {
- case 'B': /* PCM12 */
- case 'C': /* PCM20 radio */
- if (aci_version >= 0xb0) {
- if ((vol=aci_rw_cmd(ACI_STATUS,
- ACI_S_GENERAL, -1))<0)
- return vol;
- if (vol & 0x20)
- buf |= SOUND_MASK_PCM;
- }
- else
- if (!aci_solo)
- buf |= SOUND_MASK_PCM;
- break;
- default:
- buf |= SOUND_MASK_PCM;
- }
- if (aci_idcode[1] == 'C') /* PCM20 radio */
- buf |= SOUND_MASK_RADIO;
- else
- buf |= SOUND_MASK_LINE1;
-
- __put_user(buf, p);
- return 0;
- case SOUND_MIXER_READ_CAPS:
- __put_user(0, p);
- return 0;
- case SOUND_MIXER_READ_VOLUME:
- return getvolume(p, 0x04, 0x03);
- case SOUND_MIXER_READ_CD:
- return getvolume(p, 0x0a, 0x09);
- case SOUND_MIXER_READ_MIC:
- return getvolume(p, 0x06, 0x05);
- case SOUND_MIXER_READ_LINE:
- return getvolume(p, 0x08, 0x07);
- case SOUND_MIXER_READ_SYNTH:
- return getvolume(p, 0x0c, 0x0b);
- case SOUND_MIXER_READ_PCM:
- return getvolume(p, 0x0e, 0x0d);
- case MIXER_READ(SOUND_MIXER_RADIO): /* fall through */
- case SOUND_MIXER_READ_LINE1: /* AUX1 */
- return getvolume(p, 0x11, 0x10);
- case SOUND_MIXER_READ_LINE2: /* AUX2 */
- return getvolume(p, 0x13, 0x12);
- case SOUND_MIXER_READ_BASS: /* get band one */
- if (aci_idcode[1]=='C') {
- return getequalizer(p, 0x23, 0x22);
- }
- break;
- case SOUND_MIXER_READ_TREBLE: /* get band seven */
- if (aci_idcode[1]=='C') {
- return getequalizer(p, 0x2f, 0x2e);
- }
- break;
- case SOUND_MIXER_READ_IGAIN: /* MIC pre-amp */
- if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
- /* aci_micpreamp or ACI? */
- if (aci_version >= 0xb0) {
- if ((buf=aci_indexed_cmd(ACI_STATUS,
- ACI_S_READ_IGAIN))<0)
- return buf;
- }
- else
- buf=aci_micpreamp;
- vol = SCALE(3, 100, buf <= 3 ? buf : 3);
- vol |= vol << 8;
- __put_user(vol, p);
- return 0;
- }
- break;
- case SOUND_MIXER_READ_OGAIN:
- if (aci_amp)
- buf = (100 || 100<<8);
- else
- buf = 0;
- __put_user(buf, p);
- return 0;
- }
- return -EINVAL;
-}
-
-static struct mixer_operations aci_mixer_operations =
-{
- .owner = THIS_MODULE,
- .id = "ACI",
- .ioctl = aci_mixer_ioctl
-};
-
-/*
- * There is also an internal mixer in the codec (CS4231A or AD1845),
- * that deserves no purpose in an ACI based system which uses an
- * external ACI controlled stereo mixer. Make sure that this codec
- * mixer has the AUX1 input selected as the recording source, that the
- * input gain is set near maximum and that the other channels going
- * from the inputs to the codec output are muted.
- */
-
-static int __init attach_aci(void)
-{
- char *boardname;
- int i, rc = -EBUSY;
-
- mutex_init(&aci_mutex);
-
- outb(0xE3, 0xf8f); /* Write MAD16 password */
- aci_port = (inb(0xf90) & 0x10) ?
- 0x344: 0x354; /* Get aci_port from MC4_PORT */
-
- if (!request_region(aci_port, 3, "sound mixer (ACI)")) {
- printk(KERN_NOTICE
- "aci: I/O area 0x%03x-0x%03x already used.\n",
- aci_port, aci_port+2);
- goto out;
- }
-
- /* force ACI into a known state */
- rc = -EFAULT;
- for (i=0; i<3; i++)
- if (aci_rw_cmd(ACI_ERROR_OP, -1, -1)<0)
- goto out_release_region;
-
- /* official this is one aci read call: */
- rc = -EFAULT;
- if ((aci_idcode[0]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0 ||
- (aci_idcode[1]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0) {
- printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n",
- aci_port);
- goto out_release_region;
- }
-
- if ((aci_version=aci_rw_cmd(ACI_READ_VERSION, -1, -1))<0) {
- printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n",
- aci_port);
- goto out_release_region;
- }
-
- if (aci_idcode[0] == 'm') {
- /* It looks like a miro sound card. */
- switch (aci_idcode[1]) {
- case 'A':
- boardname = "PCM1 pro / early PCM12";
- break;
- case 'B':
- boardname = "PCM12";
- break;
- case 'C':
- boardname = "PCM20 radio";
- break;
- default:
- boardname = "unknown miro";
- }
- } else {
- printk(KERN_WARNING "aci: Warning: unsupported card! - "
- "no hardware, no specs...\n");
- boardname = "unknown Cardinal Technologies";
- }
-
- printk(KERN_INFO "<ACI 0x%02x, id %02x/%02x \"%c/%c\", (%s)> at 0x%03x\n",
- aci_version,
- aci_idcode[0], aci_idcode[1],
- aci_idcode[0], aci_idcode[1],
- boardname, aci_port);
-
- rc = -EBUSY;
- if (reset) {
- /* first write()s after reset fail with my PCM20 */
- if (aci_rw_cmd(ACI_INIT, -1, -1)<0 ||
- aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0 ||
- aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0)
- goto out_release_region;
- }
-
- /* the PCM20 is muted after reset (and reboot) */
- if (aci_rw_cmd(ACI_SET_MUTE, 0x00, -1)<0)
- goto out_release_region;
-
- if (ide>=0)
- if (aci_rw_cmd(ACI_SET_IDE, !ide, -1)<0)
- goto out_release_region;
-
- if (wss>=0 && aci_idcode[1]=='A')
- if (aci_rw_cmd(ACI_SET_WSS, !!wss, -1)<0)
- goto out_release_region;
-
- mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION, boardname,
- &aci_mixer_operations,
- sizeof(aci_mixer_operations), NULL);
- rc = 0;
- if (mixer_device < 0) {
- printk(KERN_ERR "aci: Failed to install mixer.\n");
- rc = mixer_device;
- goto out_release_region;
- } /* else Maybe initialize the CS4231A mixer here... */
-out: return rc;
-out_release_region:
- release_region(aci_port, 3);
- goto out;
-}
-
-static void __exit unload_aci(void)
-{
- sound_unload_mixerdev(mixer_device);
- release_region(aci_port, 3);
-}
-
-module_init(attach_aci);
-module_exit(unload_aci);
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/aci.h b/sound/oss/aci.h
deleted file mode 100644
index 20102ee088eb..000000000000
--- a/sound/oss/aci.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _ACI_H_
-#define _ACI_H_
-
-extern int aci_port;
-extern int aci_version; /* ACI firmware version */
-extern int aci_rw_cmd(int write1, int write2, int write3);
-
-#define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1)
-#define aci_write_cmd(a, b) aci_rw_cmd(a, b, -1)
-#define aci_read_cmd(a) aci_rw_cmd(a,-1, -1)
-
-#define COMMAND_REGISTER (aci_port) /* write register */
-#define STATUS_REGISTER (aci_port + 1) /* read register */
-#define BUSY_REGISTER (aci_port + 2) /* also used for rds */
-
-#define RDS_REGISTER BUSY_REGISTER
-
-#define ACI_SET_MUTE 0x0d
-#define ACI_SET_POWERAMP 0x0f
-#define ACI_SET_TUNERMUTE 0xa3
-#define ACI_SET_TUNERMONO 0xa4
-#define ACI_SET_IDE 0xd0
-#define ACI_SET_WSS 0xd1
-#define ACI_SET_SOLOMODE 0xd2
-#define ACI_WRITE_IGAIN 0x03
-#define ACI_WRITE_TUNE 0xa7
-#define ACI_READ_TUNERSTEREO 0xa8
-#define ACI_READ_TUNERSTATION 0xa9
-#define ACI_READ_VERSION 0xf1
-#define ACI_READ_IDCODE 0xf2
-#define ACI_INIT 0xff
-#define ACI_STATUS 0xf0
-#define ACI_S_GENERAL 0x00
-#define ACI_S_READ_IGAIN 0x21
-#define ACI_ERROR_OP 0xdf
-
-/*
- * The following macro SCALE can be used to scale one integer volume
- * value into another one using only integer arithmetic. If the input
- * value x is in the range 0 <= x <= xmax, then the result will be in
- * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
- *
- * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
- * following nice properties:
- *
- * - SCALE(xmax,ymax,xmax) = ymax
- * - SCALE(xmax,ymax,0) = 0
- * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
- *
- * In addition, the rounding error is minimal and nicely distributed.
- * The proofs are left as an exercise to the reader.
- */
-
-#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
-
-
-#endif /* _ACI_H_ */
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c
deleted file mode 100644
index caabf31193f7..000000000000
--- a/sound/oss/ad1816.c
+++ /dev/null
@@ -1,1368 +0,0 @@
-/*
- *
- * AD1816 lowlevel sound driver for Linux 2.6.0 and above
- *
- * Copyright (C) 1998-2003 by Thorsten Knabe <linux@thorsten-knabe.de>
- *
- * Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
- *
- *
- * version: 1.5
- * status: beta
- * date: 2003/07/15
- *
- * Changes:
- * Oleg Drokin: Some cleanup of load/unload functions. 1998/11/24
- *
- * Thorsten Knabe: attach and unload rewritten,
- * some argument checks added 1998/11/30
- *
- * Thorsten Knabe: Buggy isa bridge workaround added 1999/01/16
- *
- * David Moews/Thorsten Knabe: Introduced options
- * parameter. Added slightly modified patch from
- * David Moews to disable dsp audio sources by setting
- * bit 0 of options parameter. This seems to be
- * required by some Aztech/Newcom SC-16 cards. 1999/04/18
- *
- * Christoph Hellwig: Adapted to module_init/module_exit. 2000/03/03
- *
- * Christoph Hellwig: Added isapnp support 2000/03/15
- *
- * Arnaldo Carvalho de Melo: get rid of check_region 2001/10/07
- *
- * Thorsten Knabe: Compiling with CONFIG_PNP enabled
- * works again. It is now possible to use more than one
- * AD1816 sound card. Sample rate now may be changed during
- * playback/capture. printk() uses log levels everywhere.
- * SMP fixes. DMA handling fixes.
- * Other minor code cleanup. 2003/07/15
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/isapnp.h>
-#include <linux/stddef.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-#define DEBUGNOISE(x)
-
-#define CHECK_FOR_POWER { int timeout=100; \
- while (timeout > 0 && (inb(devc->base)&0x80)!= 0x80) {\
- timeout--; \
- } \
- if (timeout==0) {\
- printk(KERN_WARNING "ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
- } \
-}
-
-/* structure to hold device specific information */
-typedef struct
-{
- int base; /* set in attach */
- int irq;
- int dma_playback;
- int dma_capture;
-
- int opened; /* open */
- int speed;
- int channels;
- int audio_format;
- int audio_mode;
-
- int recmask; /* setup */
- unsigned char format_bits;
- int supported_devices;
- int supported_rec_devices;
- unsigned short levels[SOUND_MIXER_NRDEVICES];
- /* misc */
- struct pnp_dev *pnpdev; /* configured via pnp */
- int dev_no; /* this is the # in audio_devs and NOT
- in ad1816_info */
- spinlock_t lock;
-} ad1816_info;
-
-static int nr_ad1816_devs;
-static int ad1816_clockfreq = 33000;
-static int options;
-
-/* supported audio formats */
-static int ad_format_mask =
-AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW;
-
-/* array of device info structures */
-static ad1816_info dev_info[MAX_AUDIO_DEV];
-
-
-/* ------------------------------------------------------------------- */
-
-/* functions for easier access to inderect registers */
-
-static int ad_read (ad1816_info * devc, int reg)
-{
- int result;
-
- CHECK_FOR_POWER;
- outb ((unsigned char) (reg & 0x3f), devc->base+0);
- result = inb(devc->base+2);
- result+= inb(devc->base+3)<<8;
- return (result);
-}
-
-
-static void ad_write (ad1816_info * devc, int reg, int data)
-{
- CHECK_FOR_POWER;
- outb ((unsigned char) (reg & 0xff), devc->base+0);
- outb ((unsigned char) (data & 0xff),devc->base+2);
- outb ((unsigned char) ((data>>8)&0xff),devc->base+3);
-}
-
-/* ------------------------------------------------------------------- */
-
-/* function interface required by struct audio_driver */
-
-static void ad1816_halt_input (int dev)
-{
- unsigned long flags;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
- unsigned char buffer;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_input called\n"));
-
- spin_lock_irqsave(&devc->lock,flags);
-
- if(!isa_dma_bridge_buggy) {
- disable_dma(audio_devs[dev]->dmap_in->dma);
- }
-
- buffer=inb(devc->base+9);
- if (buffer & 0x01) {
- /* disable capture */
- outb(buffer & ~0x01,devc->base+9);
- }
-
- if(!isa_dma_bridge_buggy) {
- enable_dma(audio_devs[dev]->dmap_in->dma);
- }
-
- /* Clear interrupt status */
- outb (~0x40, devc->base+1);
-
- devc->audio_mode &= ~PCM_ENABLE_INPUT;
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void ad1816_halt_output (int dev)
-{
- unsigned long flags;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- unsigned char buffer;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_output called!\n"));
-
- spin_lock_irqsave(&devc->lock,flags);
- /* Mute pcm output */
- ad_write(devc, 4, ad_read(devc,4)|0x8080);
-
- if(!isa_dma_bridge_buggy) {
- disable_dma(audio_devs[dev]->dmap_out->dma);
- }
-
- buffer=inb(devc->base+8);
- if (buffer & 0x01) {
- /* disable capture */
- outb(buffer & ~0x01,devc->base+8);
- }
-
- if(!isa_dma_bridge_buggy) {
- enable_dma(audio_devs[dev]->dmap_out->dma);
- }
-
- /* Clear interrupt status */
- outb ((unsigned char)~0x80, devc->base+1);
-
- devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void ad1816_output_block (int dev, unsigned long buf,
- int count, int intrflag)
-{
- unsigned long flags;
- unsigned long cnt;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
-
- cnt = count/4 - 1;
-
- spin_lock_irqsave(&devc->lock,flags);
-
- /* set transfer count */
- ad_write (devc, 8, cnt & 0xffff);
-
- devc->audio_mode |= PCM_ENABLE_OUTPUT;
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-static void ad1816_start_input (int dev, unsigned long buf, int count,
- int intrflag)
-{
- unsigned long flags;
- unsigned long cnt;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
-
- cnt = count/4 - 1;
-
- spin_lock_irqsave(&devc->lock,flags);
-
- /* set transfer count */
- ad_write (devc, 10, cnt & 0xffff);
- devc->audio_mode |= PCM_ENABLE_INPUT;
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static int ad1816_prepare_for_input (int dev, int bsize, int bcount)
-{
- unsigned long flags;
- unsigned int freq;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
- unsigned char fmt_bits;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
-
- spin_lock_irqsave(&devc->lock,flags);
- fmt_bits= (devc->format_bits&0x7)<<3;
-
- /* set mono/stereo mode */
- if (devc->channels > 1) {
- fmt_bits |=0x4;
- }
- /* set Mono/Stereo in playback/capture register */
- outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8);
- outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-
- freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq;
-
- /* write playback/capture speeds */
- ad_write (devc, 2, freq & 0xffff);
- ad_write (devc, 3, freq & 0xffff);
-
- spin_unlock_irqrestore(&devc->lock,flags);
-
- ad1816_halt_input(dev);
- return 0;
-}
-
-static int ad1816_prepare_for_output (int dev, int bsize, int bcount)
-{
- unsigned long flags;
- unsigned int freq;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
- unsigned char fmt_bits;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
-
- spin_lock_irqsave(&devc->lock,flags);
-
- fmt_bits= (devc->format_bits&0x7)<<3;
- /* set mono/stereo mode */
- if (devc->channels > 1) {
- fmt_bits |=0x4;
- }
-
- /* write format bits to playback/capture registers */
- outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8);
- outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-
- freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq;
-
- /* write playback/capture speeds */
- ad_write (devc, 2, freq & 0xffff);
- ad_write (devc, 3, freq & 0xffff);
-
- spin_unlock_irqrestore(&devc->lock,flags);
-
- ad1816_halt_output(dev);
- return 0;
-
-}
-
-static void ad1816_trigger (int dev, int state)
-{
- unsigned long flags;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: trigger called! (devc=%d,devc->base=%d\n", devc, devc->base));
-
- /* mode may have changed */
-
- spin_lock_irqsave(&devc->lock,flags);
-
- /* mask out modes not specified on open call */
- state &= devc->audio_mode;
-
- /* setup soundchip to new io-mode */
- if (state & PCM_ENABLE_INPUT) {
- /* enable capture */
- outb(inb(devc->base+9)|0x01, devc->base+9);
- } else {
- /* disable capture */
- outb(inb(devc->base+9)&~0x01, devc->base+9);
- }
-
- if (state & PCM_ENABLE_OUTPUT) {
- /* enable playback */
- outb(inb(devc->base+8)|0x01, devc->base+8);
- /* unmute pcm output */
- ad_write(devc, 4, ad_read(devc,4)&~0x8080);
- } else {
- /* mute pcm output */
- ad_write(devc, 4, ad_read(devc,4)|0x8080);
- /* disable capture */
- outb(inb(devc->base+8)&~0x01, devc->base+8);
- }
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-/* halt input & output */
-static void ad1816_halt (int dev)
-{
- ad1816_halt_input(dev);
- ad1816_halt_output(dev);
-}
-
-static void ad1816_reset (int dev)
-{
- ad1816_halt (dev);
-}
-
-/* set playback speed */
-static int ad1816_set_speed (int dev, int arg)
-{
- unsigned long flags;
- unsigned int freq;
- int ret;
-
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- spin_lock_irqsave(&devc->lock, flags);
- if (arg == 0) {
- ret = devc->speed;
- spin_unlock_irqrestore(&devc->lock, flags);
- return ret;
- }
- /* range checking */
- if (arg < 4000) {
- arg = 4000;
- }
- if (arg > 55000) {
- arg = 55000;
- }
- devc->speed = arg;
-
- /* change speed during playback */
- freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq;
- /* write playback/capture speeds */
- ad_write (devc, 2, freq & 0xffff);
- ad_write (devc, 3, freq & 0xffff);
-
- ret = devc->speed;
- spin_unlock_irqrestore(&devc->lock, flags);
- return ret;
-
-}
-
-static unsigned int ad1816_set_bits (int dev, unsigned int arg)
-{
- unsigned long flags;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- static struct format_tbl {
- int format;
- unsigned char bits;
- } format2bits[] = {
- { 0, 0 },
- { AFMT_MU_LAW, 1 },
- { AFMT_A_LAW, 3 },
- { AFMT_IMA_ADPCM, 0 },
- { AFMT_U8, 0 },
- { AFMT_S16_LE, 2 },
- { AFMT_S16_BE, 6 },
- { AFMT_S8, 0 },
- { AFMT_U16_LE, 0 },
- { AFMT_U16_BE, 0 }
- };
-
- int i, n = sizeof (format2bits) / sizeof (struct format_tbl);
-
- spin_lock_irqsave(&devc->lock, flags);
- /* return current format */
- if (arg == 0) {
- arg = devc->audio_format;
- spin_unlock_irqrestore(&devc->lock, flags);
- return arg;
- }
- devc->audio_format = arg;
-
- /* search matching format bits */
- for (i = 0; i < n; i++)
- if (format2bits[i].format == arg) {
- devc->format_bits = format2bits[i].bits;
- devc->audio_format = arg;
- spin_unlock_irqrestore(&devc->lock, flags);
- return arg;
- }
-
- /* Still hanging here. Something must be terribly wrong */
- devc->format_bits = 0;
- devc->audio_format = AFMT_U8;
- spin_unlock_irqrestore(&devc->lock, flags);
- return(AFMT_U8);
-}
-
-static short ad1816_set_channels (int dev, short arg)
-{
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- if (arg != 1 && arg != 2)
- return devc->channels;
-
- devc->channels = arg;
- return arg;
-}
-
-/* open device */
-static int ad1816_open (int dev, int mode)
-{
- ad1816_info *devc = NULL;
- unsigned long flags;
-
- /* is device number valid ? */
- if (dev < 0 || dev >= num_audiodevs)
- return -(ENXIO);
-
- /* get device info of this dev */
- devc = (ad1816_info *) audio_devs[dev]->devc;
-
- /* make check if device already open atomic */
- spin_lock_irqsave(&devc->lock,flags);
-
- if (devc->opened) {
- spin_unlock_irqrestore(&devc->lock,flags);
- return -(EBUSY);
- }
-
- /* mark device as open */
- devc->opened = 1;
-
- devc->audio_mode = 0;
- devc->speed = 8000;
- devc->audio_format=AFMT_U8;
- devc->channels=1;
- spin_unlock_irqrestore(&devc->lock,flags);
- ad1816_reset(devc->dev_no); /* halt all pending output */
- return 0;
-}
-
-static void ad1816_close (int dev) /* close device */
-{
- unsigned long flags;
- ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
-
- /* halt all pending output */
- ad1816_reset(devc->dev_no);
-
- spin_lock_irqsave(&devc->lock,flags);
- devc->opened = 0;
- devc->audio_mode = 0;
- devc->speed = 8000;
- devc->audio_format=AFMT_U8;
- devc->format_bits = 0;
- spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-
-/* ------------------------------------------------------------------- */
-
-/* Audio driver structure */
-
-static struct audio_driver ad1816_audio_driver =
-{
- .owner = THIS_MODULE,
- .open = ad1816_open,
- .close = ad1816_close,
- .output_block = ad1816_output_block,
- .start_input = ad1816_start_input,
- .prepare_for_input = ad1816_prepare_for_input,
- .prepare_for_output = ad1816_prepare_for_output,
- .halt_io = ad1816_halt,
- .halt_input = ad1816_halt_input,
- .halt_output = ad1816_halt_output,
- .trigger = ad1816_trigger,
- .set_speed = ad1816_set_speed,
- .set_bits = ad1816_set_bits,
- .set_channels = ad1816_set_channels,
-};
-
-
-/* ------------------------------------------------------------------- */
-
-/* Interrupt handler */
-
-
-static irqreturn_t ad1816_interrupt (int irq, void *dev_id)
-{
- unsigned char status;
- ad1816_info *devc = (ad1816_info *)dev_id;
-
- if (irq < 0 || irq > 15) {
- printk(KERN_WARNING "ad1816: Got bogus interrupt %d\n", irq);
- return IRQ_NONE;
- }
-
- spin_lock(&devc->lock);
-
- /* read interrupt register */
- status = inb (devc->base+1);
- /* Clear all interrupt */
- outb (~status, devc->base+1);
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: Got interrupt subclass %d\n",status));
-
- if (status == 0) {
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: interrupt: Got interrupt, but no source.\n"));
- spin_unlock(&devc->lock);
- return IRQ_NONE;
- }
-
- if (devc->opened && (devc->audio_mode & PCM_ENABLE_INPUT) && (status&64))
- DMAbuf_inputintr (devc->dev_no);
-
- if (devc->opened && (devc->audio_mode & PCM_ENABLE_OUTPUT) && (status & 128))
- DMAbuf_outputintr (devc->dev_no, 1);
-
- spin_unlock(&devc->lock);
- return IRQ_HANDLED;
-}
-
-/* ------------------------------------------------------------------- */
-
-/* Mixer stuff */
-
-struct mixer_def {
- unsigned int regno: 7;
- unsigned int polarity:1; /* 0=normal, 1=reversed */
- unsigned int bitpos:4;
- unsigned int nbits:4;
-};
-
-static char mix_cvt[101] = {
- 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
- 43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
- 65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
- 80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
- 91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
- 100
-};
-
-typedef struct mixer_def mixer_ent;
-
-/*
- * Most of the mixer entries work in backwards. Setting the polarity field
- * makes them to work correctly.
- *
- * The channel numbering used by individual soundcards is not fixed. Some
- * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
- * The current version doesn't try to compensate this.
- */
-
-#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \
- {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
-
-
-static mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 14, 1, 8, 5, 14, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 5, 1, 8, 6, 5, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_PCM, 4, 1, 8, 6, 4, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 8, 5, 18, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_MIC, 19, 1, 8, 5, 19, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_CD, 15, 1, 8, 5, 15, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 20, 0, 8, 4, 20, 0, 0, 4),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 17, 1, 8, 5, 17, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE2, 16, 1, 8, 5, 16, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE3, 39, 0, 9, 4, 39, 1, 0, 5)
-};
-
-
-static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
-{
- 0x4343, /* Master Volume */
- 0x3232, /* Bass */
- 0x3232, /* Treble */
- 0x0000, /* FM */
- 0x4343, /* PCM */
- 0x0000, /* PC Speaker */
- 0x0000, /* Ext Line */
- 0x0000, /* Mic */
- 0x0000, /* CD */
- 0x0000, /* Recording monitor */
- 0x0000, /* SB PCM */
- 0x0000, /* Recording level */
- 0x0000, /* Input gain */
- 0x0000, /* Output gain */
- 0x0000, /* Line1 */
- 0x0000, /* Line2 */
- 0x0000 /* Line3 (usually line in)*/
-};
-
-#define LEFT_CHN 0
-#define RIGHT_CHN 1
-
-
-
-static int
-ad1816_set_recmask (ad1816_info * devc, int mask)
-{
- unsigned long flags;
- unsigned char recdev;
- int i, n;
-
- spin_lock_irqsave(&devc->lock, flags);
- mask &= devc->supported_rec_devices;
-
- n = 0;
- /* Count selected device bits */
- for (i = 0; i < 32; i++)
- if (mask & (1 << i))
- n++;
-
- if (n == 0)
- mask = SOUND_MASK_MIC;
- else if (n != 1) { /* Too many devices selected */
- /* Filter out active settings */
- mask &= ~devc->recmask;
-
- n = 0;
- /* Count selected device bits */
- for (i = 0; i < 32; i++)
- if (mask & (1 << i))
- n++;
-
- if (n != 1)
- mask = SOUND_MASK_MIC;
- }
-
- switch (mask) {
- case SOUND_MASK_MIC:
- recdev = 5;
- break;
-
- case SOUND_MASK_LINE:
- recdev = 0;
- break;
-
- case SOUND_MASK_CD:
- recdev = 2;
- break;
-
- case SOUND_MASK_LINE1:
- recdev = 4;
- break;
-
- case SOUND_MASK_LINE2:
- recdev = 3;
- break;
-
- case SOUND_MASK_VOLUME:
- recdev = 1;
- break;
-
- default:
- mask = SOUND_MASK_MIC;
- recdev = 5;
- }
-
- recdev <<= 4;
- ad_write (devc, 20,
- (ad_read (devc, 20) & 0x8f8f) | recdev | (recdev<<8));
-
- devc->recmask = mask;
- spin_unlock_irqrestore(&devc->lock, flags);
- return mask;
-}
-
-static void
-change_bits (int *regval, int dev, int chn, int newval)
-{
- unsigned char mask;
- int shift;
-
- /* Reverse polarity*/
-
- if (mix_devices[dev][chn].polarity == 1)
- newval = 100 - newval;
-
- mask = (1 << mix_devices[dev][chn].nbits) - 1;
- shift = mix_devices[dev][chn].bitpos;
- /* Scale it */
- newval = (int) ((newval * mask) + 50) / 100;
- /* Clear bits */
- *regval &= ~(mask << shift);
- /* Set new value */
- *regval |= (newval & mask) << shift;
-}
-
-static int
-ad1816_mixer_get (ad1816_info * devc, int dev)
-{
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_get called!\n"));
-
- /* range check + supported mixer check */
- if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
- return (-(EINVAL));
- if (!((1 << dev) & devc->supported_devices))
- return -(EINVAL);
-
- return devc->levels[dev];
-}
-
-static int
-ad1816_mixer_set (ad1816_info * devc, int dev, int value)
-{
- int left = value & 0x000000ff;
- int right = (value & 0x0000ff00) >> 8;
- int retvol;
-
- int regoffs;
- int val;
- int valmute;
- unsigned long flags;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_set called!\n"));
-
- if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
- return -(EINVAL);
-
- if (left > 100)
- left = 100;
- if (left < 0)
- left = 0;
- if (right > 100)
- right = 100;
- if (right < 0)
- right = 0;
-
- /* Mono control */
- if (mix_devices[dev][RIGHT_CHN].nbits == 0)
- right = left;
- retvol = left | (right << 8);
-
- /* Scale it */
-
- left = mix_cvt[left];
- right = mix_cvt[right];
-
- /* reject all mixers that are not supported */
- if (!(devc->supported_devices & (1 << dev)))
- return -(EINVAL);
-
- /* sanity check */
- if (mix_devices[dev][LEFT_CHN].nbits == 0)
- return -(EINVAL);
- spin_lock_irqsave(&devc->lock, flags);
-
- /* keep precise volume internal */
- devc->levels[dev] = retvol;
-
- /* Set the left channel */
- regoffs = mix_devices[dev][LEFT_CHN].regno;
- val = ad_read (devc, regoffs);
- change_bits (&val, dev, LEFT_CHN, left);
-
- valmute=val;
-
- /* Mute bit masking on some registers */
- if ( regoffs==5 || regoffs==14 || regoffs==15 ||
- regoffs==16 || regoffs==17 || regoffs==18 ||
- regoffs==19 || regoffs==39) {
- if (left==0)
- valmute |= 0x8000;
- else
- valmute &= ~0x8000;
- }
- ad_write (devc, regoffs, valmute); /* mute */
-
- /*
- * Set the right channel
- */
-
- /* Was just a mono channel */
- if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
- spin_unlock_irqrestore(&devc->lock, flags);
- return retvol;
- }
-
- regoffs = mix_devices[dev][RIGHT_CHN].regno;
- val = ad_read (devc, regoffs);
- change_bits (&val, dev, RIGHT_CHN, right);
-
- valmute=val;
- if ( regoffs==5 || regoffs==14 || regoffs==15 ||
- regoffs==16 || regoffs==17 || regoffs==18 ||
- regoffs==19 || regoffs==39) {
- if (right==0)
- valmute |= 0x80;
- else
- valmute &= ~0x80;
- }
- ad_write (devc, regoffs, valmute); /* mute */
- spin_unlock_irqrestore(&devc->lock, flags);
- return retvol;
-}
-
-#define MIXER_DEVICES ( SOUND_MASK_VOLUME | \
- SOUND_MASK_SYNTH | \
- SOUND_MASK_PCM | \
- SOUND_MASK_LINE | \
- SOUND_MASK_LINE1 | \
- SOUND_MASK_LINE2 | \
- SOUND_MASK_LINE3 | \
- SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_RECLEV \
- )
-#define REC_DEVICES ( SOUND_MASK_LINE2 |\
- SOUND_MASK_LINE |\
- SOUND_MASK_LINE1 |\
- SOUND_MASK_MIC |\
- SOUND_MASK_CD |\
- SOUND_MASK_VOLUME \
- )
-
-static void
-ad1816_mixer_reset (ad1816_info * devc)
-{
- int i;
-
- devc->supported_devices = MIXER_DEVICES;
-
- devc->supported_rec_devices = REC_DEVICES;
-
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- if (devc->supported_devices & (1 << i))
- ad1816_mixer_set (devc, i, default_mixer_levels[i]);
- ad1816_set_recmask (devc, SOUND_MASK_MIC);
-}
-
-static int
-ad1816_mixer_ioctl (int dev, unsigned int cmd, void __user * arg)
-{
- ad1816_info *devc = mixer_devs[dev]->devc;
- int val;
- int __user *p = arg;
-
- DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_ioctl called!\n"));
-
- /* Mixer ioctl */
- if (((cmd >> 8) & 0xff) == 'M') {
-
- /* set ioctl */
- if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
- switch (cmd & 0xff){
- case SOUND_MIXER_RECSRC:
-
- if (get_user(val, p))
- return -EFAULT;
- val=ad1816_set_recmask (devc, val);
- return put_user(val, p);
- break;
-
- default:
- if (get_user(val, p))
- return -EFAULT;
- if ((val=ad1816_mixer_set (devc, cmd & 0xff, val))<0)
- return val;
- else
- return put_user(val, p);
- }
- } else {
- /* read ioctl */
- switch (cmd & 0xff) {
-
- case SOUND_MIXER_RECSRC:
- val=devc->recmask;
- return put_user(val, p);
- break;
-
- case SOUND_MIXER_DEVMASK:
- val=devc->supported_devices;
- return put_user(val, p);
- break;
-
- case SOUND_MIXER_STEREODEVS:
- val=devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
- return put_user(val, p);
- break;
-
- case SOUND_MIXER_RECMASK:
- val=devc->supported_rec_devices;
- return put_user(val, p);
- break;
-
- case SOUND_MIXER_CAPS:
- val=SOUND_CAP_EXCL_INPUT;
- return put_user(val, p);
- break;
-
- default:
- if ((val=ad1816_mixer_get (devc, cmd & 0xff))<0)
- return val;
- else
- return put_user(val, p);
- }
- }
- } else
- /* not for mixer */
- return -(EINVAL);
-}
-
-/* ------------------------------------------------------------------- */
-
-/* Mixer structure */
-
-static struct mixer_operations ad1816_mixer_operations = {
- .owner = THIS_MODULE,
- .id = "AD1816",
- .name = "AD1816 Mixer",
- .ioctl = ad1816_mixer_ioctl
-};
-
-
-/* ------------------------------------------------------------------- */
-
-/* stuff for card recognition, init and unloading PNP ...*/
-
-
-/* check if AD1816 present at specified hw_config and register device with OS
- * return 1 if initialization was successful, 0 otherwise
- */
-static int __init ad1816_init_card (struct address_info *hw_config,
- struct pnp_dev *pnp)
-{
- ad1816_info *devc = NULL;
- int tmp;
- int oss_devno = -1;
-
- printk(KERN_INFO "ad1816: initializing card: io=0x%x, irq=%d, dma=%d, "
- "dma2=%d, clockfreq=%d, options=%d isadmabug=%d "
- "%s\n",
- hw_config->io_base,
- hw_config->irq,
- hw_config->dma,
- hw_config->dma2,
- ad1816_clockfreq,
- options,
- isa_dma_bridge_buggy,
- pnp?"(PNP)":"");
-
- /* ad1816_info structure remaining ? */
- if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
- printk(KERN_WARNING "ad1816: no more ad1816_info structures "
- "left\n");
- goto out;
- }
-
- devc = &dev_info[nr_ad1816_devs];
- devc->base = hw_config->io_base;
- devc->irq = hw_config->irq;
- devc->dma_playback=hw_config->dma;
- devc->dma_capture=hw_config->dma2;
- devc->opened = 0;
- devc->pnpdev = pnp;
- spin_lock_init(&devc->lock);
-
- if (!request_region(devc->base, 16, "AD1816 Sound")) {
- printk(KERN_WARNING "ad1816: I/O port 0x%03x not free\n",
- devc->base);
- goto out;
- }
-
- printk(KERN_INFO "ad1816: Examining AD1816 at address 0x%03x.\n",
- devc->base);
-
-
- /* tests for ad1816 */
- /* base+0: bit 1 must be set but not 255 */
- tmp=inb(devc->base);
- if ( (tmp&0x80)==0 || tmp==255 ) {
- printk (KERN_INFO "ad1816: Chip is not an AD1816 or chip "
- "is not active (Test 0)\n");
- goto out_release_region;
- }
-
- /* writes to ireg 8 are copied to ireg 9 */
- ad_write(devc,8,12345);
- if (ad_read(devc,9)!=12345) {
- printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 1)\n");
- goto out_release_region;
- }
-
- /* writes to ireg 8 are copied to ireg 9 */
- ad_write(devc,8,54321);
- if (ad_read(devc,9)!=54321) {
- printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 2)\n");
- goto out_release_region;
- }
-
- /* writes to ireg 10 are copied to ireg 11 */
- ad_write(devc,10,54321);
- if (ad_read(devc,11)!=54321) {
- printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 3)\n");
- goto out_release_region;
- }
-
- /* writes to ireg 10 are copied to ireg 11 */
- ad_write(devc,10,12345);
- if (ad_read(devc,11)!=12345) {
- printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 4)\n");
- goto out_release_region;
- }
-
- /* bit in base +1 cannot be set to 1 */
- tmp=inb(devc->base+1);
- outb(0xff,devc->base+1);
- if (inb(devc->base+1)!=tmp) {
- printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 5)\n");
- goto out_release_region;
- }
-
- printk(KERN_INFO "ad1816: AD1816 (version %d) successfully detected!\n",
- ad_read(devc,45));
-
- /* disable all interrupts */
- ad_write(devc,1,0);
-
- /* Clear pending interrupts */
- outb (0, devc->base+1);
-
- /* allocate irq */
- if (devc->irq < 0 || devc->irq > 15)
- goto out_release_region;
- if (request_irq(devc->irq, ad1816_interrupt,0,
- "SoundPort", devc) < 0) {
- printk(KERN_WARNING "ad1816: IRQ in use\n");
- goto out_release_region;
- }
-
- /* DMA stuff */
- if (sound_alloc_dma (devc->dma_playback, "Sound System")) {
- printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
- devc->dma_playback);
- goto out_free_irq;
- }
-
- if ( devc->dma_capture >= 0 &&
- devc->dma_capture != devc->dma_playback) {
- if (sound_alloc_dma(devc->dma_capture,
- "Sound System (capture)")) {
- printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
- devc->dma_capture);
- goto out_free_dma;
- }
- devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
- } else {
- printk(KERN_WARNING "ad1816: Only one DMA channel "
- "available/configured. No duplex operation possible\n");
- devc->audio_mode=DMA_AUTOMODE;
- }
-
- conf_printf2 ("AD1816 audio driver",
- devc->base, devc->irq, devc->dma_playback,
- devc->dma_capture);
-
- /* register device */
- if ((oss_devno = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
- "AD1816 audio driver",
- &ad1816_audio_driver,
- sizeof (struct audio_driver),
- devc->audio_mode,
- ad_format_mask,
- devc,
- devc->dma_playback,
- devc->dma_capture)) < 0) {
- printk(KERN_WARNING "ad1816: Can't install sound driver\n");
- goto out_free_dma_2;
- }
-
-
- ad_write(devc,32,0x80f0); /* sound system mode */
- if (options&1) {
- ad_write(devc,33,0); /* disable all audiosources for dsp */
- } else {
- ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
- }
- ad_write(devc,4,0x8080); /* default values for volumes (muted)*/
- ad_write(devc,5,0x8080);
- ad_write(devc,6,0x8080);
- ad_write(devc,7,0x8080);
- ad_write(devc,15,0x8888);
- ad_write(devc,16,0x8888);
- ad_write(devc,17,0x8888);
- ad_write(devc,18,0x8888);
- ad_write(devc,19,0xc888); /* +20db mic active */
- ad_write(devc,14,0x0000); /* Master volume unmuted */
- ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
- ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
- outb(0x10,devc->base+8); /* set dma mode */
- outb(0x10,devc->base+9);
-
- /* enable capture + playback interrupt */
- ad_write(devc,1,0xc000);
-
- /* set mixer defaults */
- ad1816_mixer_reset (devc);
-
- /* register mixer */
- if ((audio_devs[oss_devno]->mixer_dev=sound_install_mixer(
- MIXER_DRIVER_VERSION,
- "AD1816 audio driver",
- &ad1816_mixer_operations,
- sizeof (struct mixer_operations),
- devc)) < 0) {
- printk(KERN_WARNING "Can't install mixer\n");
- }
- /* make ad1816_info active */
- nr_ad1816_devs++;
- printk(KERN_INFO "ad1816: card successfully installed!\n");
- return 1;
- /* error handling */
-out_free_dma_2:
- if (devc->dma_capture >= 0 && devc->dma_capture != devc->dma_playback)
- sound_free_dma(devc->dma_capture);
-out_free_dma:
- sound_free_dma(devc->dma_playback);
-out_free_irq:
- free_irq(devc->irq, devc);
-out_release_region:
- release_region(devc->base, 16);
-out:
- return 0;
-}
-
-static void __exit unload_card(ad1816_info *devc)
-{
- int mixer, dev = 0;
-
- if (devc != NULL) {
- printk("ad1816: Unloading card at address 0x%03x\n",devc->base);
-
- dev = devc->dev_no;
- mixer = audio_devs[dev]->mixer_dev;
-
- /* unreg mixer*/
- if(mixer>=0) {
- sound_unload_mixerdev(mixer);
- }
- /* unreg audiodev */
- sound_unload_audiodev(dev);
-
- /* free dma channels */
- if (devc->dma_capture>=0 &&
- devc->dma_capture != devc->dma_playback) {
- sound_free_dma(devc->dma_capture);
- }
- sound_free_dma (devc->dma_playback);
- /* free irq */
- free_irq(devc->irq, devc);
- /* free io */
- release_region (devc->base, 16);
-#ifdef __ISAPNP__
- if (devc->pnpdev) {
- pnp_disable_dev(devc->pnpdev);
- pnp_device_detach(devc->pnpdev);
- }
-#endif
-
- } else
- printk(KERN_WARNING "ad1816: no device/card specified\n");
-}
-
-static int __initdata io = -1;
-static int __initdata irq = -1;
-static int __initdata dma = -1;
-static int __initdata dma2 = -1;
-
-#ifdef __ISAPNP__
-/* use isapnp for configuration */
-static int isapnp = 1;
-static int isapnpjump;
-module_param(isapnp, bool, 0);
-module_param(isapnpjump, int, 0);
-#endif
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(dma, int, 0);
-module_param(dma2, int, 0);
-module_param(ad1816_clockfreq, int, 0);
-module_param(options, int, 0);
-
-#ifdef __ISAPNP__
-static struct {
- unsigned short card_vendor, card_device;
- unsigned short vendor;
- unsigned short function;
- struct ad1816_data *data;
-} isapnp_ad1816_list[] __initdata = {
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7150),
- NULL },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7180),
- NULL },
- {0}
-};
-
-MODULE_DEVICE_TABLE(isapnp, isapnp_ad1816_list);
-
-
-static void __init ad1816_config_pnp_card(struct pnp_card *card,
- unsigned short vendor,
- unsigned short function)
-{
- struct address_info cfg;
- struct pnp_dev *card_dev = pnp_find_dev(card, vendor, function, NULL);
- if (!card_dev) return;
- if (pnp_device_attach(card_dev) < 0) {
- printk(KERN_WARNING "ad1816: Failed to attach PnP device\n");
- return;
- }
- if (pnp_activate_dev(card_dev) < 0) {
- printk(KERN_WARNING "ad1816: Failed to activate PnP device\n");
- pnp_device_detach(card_dev);
- return;
- }
- cfg.io_base = pnp_port_start(card_dev, 2);
- cfg.irq = pnp_irq(card_dev, 0);
- cfg.dma = pnp_irq(card_dev, 0);
- cfg.dma2 = pnp_irq(card_dev, 1);
- if (!ad1816_init_card(&cfg, card_dev)) {
- pnp_disable_dev(card_dev);
- pnp_device_detach(card_dev);
- }
-}
-
-static void __init ad1816_config_pnp_cards(void)
-{
- int nr_pnp_cfg;
- int i;
-
- /* Count entries in isapnp_ad1816_list */
- for (nr_pnp_cfg = 0; isapnp_ad1816_list[nr_pnp_cfg].card_vendor != 0;
- nr_pnp_cfg++);
- /* Check and adjust isapnpjump */
- if( isapnpjump < 0 || isapnpjump >= nr_pnp_cfg) {
- printk(KERN_WARNING
- "ad1816: Valid range for isapnpjump is 0-%d. "
- "Adjusted to 0.\n", nr_pnp_cfg-1);
- isapnpjump = 0;
- }
- for (i = isapnpjump; isapnp_ad1816_list[i].card_vendor != 0; i++) {
- struct pnp_card *card = NULL;
- /* iterate over all pnp cards */
- while ((card = pnp_find_card(isapnp_ad1816_list[i].card_vendor,
- isapnp_ad1816_list[i].card_device, card)))
- ad1816_config_pnp_card(card,
- isapnp_ad1816_list[i].vendor,
- isapnp_ad1816_list[i].function);
- }
-}
-#endif
-
-/* module initialization */
-static int __init init_ad1816(void)
-{
- printk(KERN_INFO "ad1816: AD1816 sounddriver "
- "Copyright (C) 1998-2003 by Thorsten Knabe and "
- "others\n");
-#ifdef AD1816_CLOCK
- /* set ad1816_clockfreq if set during compilation */
- ad1816_clockfreq=AD1816_CLOCK;
-#endif
- if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
- ad1816_clockfreq=33000;
- }
-
-#ifdef __ISAPNP__
- /* configure PnP cards */
- if(isapnp) ad1816_config_pnp_cards();
-#endif
- /* configure card by module params */
- if (io != -1 && irq != -1 && dma != -1) {
- struct address_info cfg;
- cfg.io_base = io;
- cfg.irq = irq;
- cfg.dma = dma;
- cfg.dma2 = dma2;
- ad1816_init_card(&cfg, NULL);
- }
- if (nr_ad1816_devs <= 0)
- return -ENODEV;
- return 0;
-}
-
-/* module cleanup */
-static void __exit cleanup_ad1816 (void)
-{
- int i;
- ad1816_info *devc = NULL;
-
- /* remove any soundcard */
- for (i = 0; i < nr_ad1816_devs; i++) {
- devc = &dev_info[i];
- unload_card(devc);
- }
- nr_ad1816_devs=0;
- printk(KERN_INFO "ad1816: driver unloaded!\n");
-}
-
-module_init(init_ad1816);
-module_exit(cleanup_ad1816);
-
-#ifndef MODULE
-/* kernel command line parameter evaluation */
-static int __init setup_ad1816(char *str)
-{
- /* io, irq, dma, dma2 */
- int ints[5];
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
-
- io = ints[1];
- irq = ints[2];
- dma = ints[3];
- dma2 = ints[4];
- return 1;
-}
-
-__setup("ad1816=", setup_ad1816);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
deleted file mode 100644
index c0730a3563a2..000000000000
--- a/sound/oss/ad1889.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- * Copyright 2001-2004 Randolph Chung <tausq@debian.org>
- *
- * Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
- *
- * 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.
- *
- * Notes:
- * 1. Only flat DMA is supported; s-g is not supported right now
- *
- *
-<jsm> tausq: Anyway, to set up sample rates for D to A, you just use the sample rate on the codec. For A to D, you need to set the codec always to 48K (using the split sample rate feature on the codec) and then set the resampler on the AD1889 to the sample rate you want.
-<jsm> Also, when changing the sample rate on the codec you need to power it down and re power it up for the change to take effect!
- *
- * $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/sound.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include "ad1889.h"
-
-#define DBG(fmt, arg...) printk(fmt, ##arg)
-#define DEVNAME "ad1889"
-
-#define NR_HW_CH 4
-#define DAC_RUNNING 1
-#define ADC_RUNNING 2
-
-#define UNDERRUN(dev) (0)
-
-#define AD1889_READW(dev,reg) readw(dev->regbase + reg)
-#define AD1889_WRITEW(dev,reg,val) writew((val), dev->regbase + reg)
-#define AD1889_READL(dev,reg) readl(dev->regbase + reg)
-#define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
-
-//now 100ms
-/* #define WAIT_10MS() schedule_timeout(HZ/10) */
-#define WAIT_10MS() do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
-
-/* currently only support a single device */
-static ad1889_dev_t *ad1889_dev = NULL;
-
-/************************* helper routines ***************************** */
-static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
-{
- struct ac97_codec *ac97_codec = dev->ac97_codec;
-
- DBG("Setting WAV rate to %d\n", rate);
- dev->state[AD_WAV_STATE].dmabuf.rate = rate;
- AD1889_WRITEW(dev, AD_DS_WAS, rate);
-
- /* Cycle the DAC to enable the new rate */
- ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
- WAIT_10MS();
- ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
-}
-
-static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
-{
- u16 tmp;
-
- DBG("Setting WAV format to 0x%x\n", fmt);
-
- tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
- if (fmt & AFMT_S16_LE) {
- //tmp |= 0x0100; /* set WA16 */
- tmp |= 0x0300; /* set WA16 stereo */
- } else if (fmt & AFMT_U8) {
- tmp &= ~0x0100; /* clear WA16 */
- }
- AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
-}
-
-static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
-{
- u16 tmp;
-
- DBG("Setting ADC format to 0x%x\n", fmt);
-
- tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
- if (fmt & AFMT_S16_LE) {
- tmp |= 0x0100; /* set WA16 */
- } else if (fmt & AFMT_U8) {
- tmp &= ~0x0100; /* clear WA16 */
- }
- AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
-}
-
-static void ad1889_start_wav(ad1889_state_t *state)
-{
- unsigned long flags;
- struct dmabuf *dmabuf = &state->dmabuf;
- int cnt;
- u16 tmp;
-
- spin_lock_irqsave(&state->card->lock, flags);
-
- if (dmabuf->dma_len) /* DMA already in flight */
- goto skip_dma;
-
- /* setup dma */
- cnt = dmabuf->wr_ptr - dmabuf->rd_ptr;
- if (cnt == 0) /* done - don't need to do anything */
- goto skip_dma;
-
- /* If the wr_ptr has wrapped, only map to the end */
- if (cnt < 0)
- cnt = DMA_SIZE - dmabuf->rd_ptr;
-
- dmabuf->dma_handle = pci_map_single(ad1889_dev->pci,
- dmabuf->rawbuf + dmabuf->rd_ptr,
- cnt, PCI_DMA_TODEVICE);
- dmabuf->dma_len = cnt;
- dmabuf->ready = 1;
-
- DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
- dmabuf->rd_ptr, dmabuf->dma_len);
-
- /* load up the current register set */
- AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
-
- /* TODO: for now we load the base registers with the same thing */
- AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
-
- /* and we're off to the races... */
- AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
- tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
- tmp |= 0x0400; /* set WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
-
- dmabuf->enable |= DAC_RUNNING;
-
-skip_dma:
- spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-
-static void ad1889_stop_wav(ad1889_state_t *state)
-{
- unsigned long flags;
- struct dmabuf *dmabuf = &state->dmabuf;
-
- spin_lock_irqsave(&state->card->lock, flags);
-
- if (dmabuf->enable & DAC_RUNNING) {
- u16 tmp;
- unsigned long cnt = dmabuf->dma_len;
-
- tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
- tmp &= ~0x0400; /* clear WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
- pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle,
- cnt, PCI_DMA_TODEVICE);
-
- dmabuf->enable &= ~DAC_RUNNING;
-
- /* update dma pointers */
- dmabuf->rd_ptr += cnt;
- dmabuf->rd_ptr &= (DMA_SIZE - 1);
-
- dmabuf->dma_handle = 0;
- dmabuf->dma_len = 0;
- dmabuf->ready = 0;
-
- wake_up(&dmabuf->wait);
- }
-
- spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-
-#if 0
-static void ad1889_startstop_adc(ad1889_state_t *state, int start)
-{
- u16 tmp;
- unsigned long flags;
-
- spin_lock_irqsave(&state->card->lock, flags);
-
- tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
- if (start) {
- state->dmabuf.enable |= ADC_RUNNING;
- tmp |= 0x0004; /* set ADEN */
- } else {
- state->dmabuf.enable &= ~ADC_RUNNING;
- tmp &= ~0x0004; /* clear ADEN */
- }
- AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
-
- spin_unlock_irqrestore(&state->card->lock, flags);
-}
-#endif
-
-static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
-{
- ad1889_dev_t *dev;
- struct dmabuf *dmabuf;
- int i;
-
- if ((dev = kzalloc(sizeof(ad1889_dev_t), GFP_KERNEL)) == NULL)
- return NULL;
- spin_lock_init(&dev->lock);
- dev->pci = pci;
-
- for (i = 0; i < AD_MAX_STATES; i++) {
- dev->state[i].card = dev;
- mutex_init(&dev->state[i].mutex);
- init_waitqueue_head(&dev->state[i].dmabuf.wait);
- }
-
- /* allocate dma buffer */
-
- for (i = 0; i < AD_MAX_STATES; i++) {
- dmabuf = &dev->state[i].dmabuf;
- dmabuf->rawbuf = kmalloc(DMA_SIZE, GFP_KERNEL|GFP_DMA);
- if (!dmabuf->rawbuf)
- goto err_free_dmabuf;
- dmabuf->rawbuf_size = DMA_SIZE;
- dmabuf->dma_handle = 0;
- dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
- dmabuf->ready = 0;
- dmabuf->rate = 48000;
- }
- return dev;
-
-err_free_dmabuf:
- while (--i >= 0)
- kfree(dev->state[i].dmabuf.rawbuf);
- kfree(dev);
- return NULL;
-}
-
-static void ad1889_free_dev(ad1889_dev_t *dev)
-{
- int j;
- struct dmabuf *dmabuf;
-
- if (dev == NULL)
- return;
-
- if (dev->ac97_codec)
- ac97_release_codec(dev->ac97_codec);
-
- for (j = 0; j < AD_MAX_STATES; j++) {
- dmabuf = &dev->state[j].dmabuf;
- kfree(dmabuf->rawbuf);
- }
-
- kfree(dev);
-}
-
-static inline void ad1889_trigger_playback(ad1889_dev_t *dev)
-{
-#if 0
- u32 val;
- struct dmabuf *dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
-#endif
-
- ad1889_start_wav(&dev->state[AD_WAV_STATE]);
-}
-
-static int ad1889_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- char *out = page;
- int len, i;
- ad1889_dev_t *dev = data;
- ad1889_reg_t regs[] = {
- { "WSMC", AD_DS_WSMC, 16 },
- { "RAMC", AD_DS_RAMC, 16 },
- { "WADA", AD_DS_WADA, 16 },
- { "SYDA", AD_DS_SYDA, 16 },
- { "WAS", AD_DS_WAS, 16 },
- { "RES", AD_DS_RES, 16 },
- { "CCS", AD_DS_CCS, 16 },
- { "ADCBA", AD_DMA_ADCBA, 32 },
- { "ADCCA", AD_DMA_ADCCA, 32 },
- { "ADCBC", AD_DMA_ADCBC, 32 },
- { "ADCCC", AD_DMA_ADCCC, 32 },
- { "ADCIBC", AD_DMA_ADCIBC, 32 },
- { "ADCICC", AD_DMA_ADCICC, 32 },
- { "ADCCTRL", AD_DMA_ADCCTRL, 16 },
- { "WAVBA", AD_DMA_WAVBA, 32 },
- { "WAVCA", AD_DMA_WAVCA, 32 },
- { "WAVBC", AD_DMA_WAVBC, 32 },
- { "WAVCC", AD_DMA_WAVCC, 32 },
- { "WAVIBC", AD_DMA_WAVIBC, 32 },
- { "WAVICC", AD_DMA_WAVICC, 32 },
- { "WAVCTRL", AD_DMA_WAVCTRL, 16 },
- { "DISR", AD_DMA_DISR, 32 },
- { "CHSS", AD_DMA_CHSS, 32 },
- { "IPC", AD_GPIO_IPC, 16 },
- { "OP", AD_GPIO_OP, 16 },
- { "IP", AD_GPIO_IP, 16 },
- { "ACIC", AD_AC97_ACIC, 16 },
- { "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
- { "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
- { "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
- { "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
- { "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
- { "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
- { "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
- { "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
- { "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
- { "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
- { "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
- { "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
- { "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
- { "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
- { "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
- { "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
- { "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
- { "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
- { "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
- { "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
- { NULL }
- };
-
- if (dev == NULL)
- return -ENODEV;
-
- for (i = 0; regs[i].name != 0; i++)
- out += sprintf(out, "%s: 0x%0*x\n", regs[i].name,
- regs[i].width >> 2,
- (regs[i].width == 16
- ? AD1889_READW(dev, regs[i].offset)
- : AD1889_READL(dev, regs[i].offset)));
-
- for (i = 0; i < AD_MAX_STATES; i++) {
- out += sprintf(out, "DMA status for %s:\n",
- (i == AD_WAV_STATE ? "WAV" : "ADC"));
- out += sprintf(out, "\t\t0x%p (IOVA: 0x%llu)\n",
- dev->state[i].dmabuf.rawbuf,
- (unsigned long long)dev->state[i].dmabuf.dma_handle);
-
- out += sprintf(out, "\tread ptr: offset %u\n",
- (unsigned int)dev->state[i].dmabuf.rd_ptr);
- out += sprintf(out, "\twrite ptr: offset %u\n",
- (unsigned int)dev->state[i].dmabuf.wr_ptr);
- out += sprintf(out, "\tdma len: offset %u\n",
- (unsigned int)dev->state[i].dmabuf.dma_len);
- }
-
- len = out - page - off;
- if (len < count) {
- *eof = 1;
- if (len <= 0) return 0;
- } else {
- len = count;
- }
- *start = page + off;
- return len;
-}
-
-/***************************** DMA interfaces ************************** */
-#if 0
-static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- u32 offset;
-
- if (!(dmabuf->enable & (DAC_RUNNING | ADC_RUNNING))) {
- printk(KERN_ERR DEVNAME ": get_dma_addr called without dma enabled\n");
- return 0;
- }
-
- if (dmabuf->enable & DAC_RUNNING)
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
- else
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
-
- return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
-}
-
-static void ad1889_update_ptr(ad1889_dev_t *dev, int wake)
-{
- ad1889_state_t *state;
- struct dmabuf *dmabuf;
- unsigned long hwptr;
- int diff;
-
- /* check ADC first */
- state = &dev->adc_state;
- dmabuf = &state->dmabuf;
- if (dmabuf->enable & ADC_RUNNING) {
- hwptr = ad1889_get_dma_addr(state);
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-
- dmabuf->hwptr = hwptr;
- dmabuf->total_bytes += diff;
- dmabuf->count += diff;
- if (dmabuf->count > dmabuf->dmasize)
- dmabuf->count = dmabuf->dmasize;
-
- if (dmabuf->mapped) {
- if (wake & dmabuf->count >= dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- } else {
- if (wake & dmabuf->count > 0)
- wake_up(&dmabuf->wait);
- }
- }
-
- /* check DAC */
- state = &dev->wav_state;
- dmabuf = &state->dmabuf;
- if (dmabuf->enable & DAC_RUNNING) {
-XXX
-
-}
-#endif
-
-/************************* /dev/dsp interfaces ************************* */
-
-static ssize_t ad1889_read(struct file *file, char __user *buffer, size_t count,
- loff_t *ppos)
-{
- return 0;
-}
-
-static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t count,
- loff_t *ppos)
-{
- ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
- ad1889_state_t *state = &dev->state[AD_WAV_STATE];
- volatile struct dmabuf *dmabuf = &state->dmabuf;
- ssize_t ret = 0;
- DECLARE_WAITQUEUE(wait, current);
-
- mutex_lock(&state->mutex);
-#if 0
- if (dmabuf->mapped) {
- ret = -ENXIO;
- goto err1;
- }
-#endif
- if (!access_ok(VERIFY_READ, buffer, count)) {
- ret = -EFAULT;
- goto err1;
- }
-
- add_wait_queue(&state->dmabuf.wait, &wait);
-
- /* start filling dma buffer.... */
- while (count > 0) {
- long rem;
- long cnt = count;
- unsigned long flags;
-
- for (;;) {
- long used_bytes;
- long timeout; /* max time for DMA in jiffies */
-
- /* buffer is full if wr catches up to rd */
- spin_lock_irqsave(&state->card->lock, flags);
- used_bytes = dmabuf->wr_ptr - dmabuf->rd_ptr;
- timeout = (dmabuf->dma_len * HZ) / dmabuf->rate;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* adjust for buffer wrap around */
- used_bytes = (used_bytes + DMA_SIZE) & (DMA_SIZE - 1);
-
- /* If at least one page unused */
- if (used_bytes < (DMA_SIZE - 0x1000))
- break;
-
- /* dma buffer full */
-
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- goto err2;
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(timeout + 1);
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- goto err2;
- }
- }
-
- /* watch out for wrapping around static buffer */
- spin_lock_irqsave(&state->card->lock, flags);
- rem = DMA_SIZE - dmabuf->wr_ptr;
- if (cnt > rem)
- cnt = rem;
-
- rem = dmabuf->wr_ptr;
-
- /* update dma pointers */
- dmabuf->wr_ptr += cnt;
- dmabuf->wr_ptr &= DMA_SIZE - 1; /* wrap ptr if necessary */
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* transfer unwrapped chunk */
- if (copy_from_user(dmabuf->rawbuf + rem, buffer, cnt)) {
- ret = -EFAULT;
- goto err2;
- }
-
- DBG("Writing 0x%lx bytes to +0x%lx\n", cnt, rem);
-
- /* update counters */
- count -= cnt;
- buffer += cnt;
- ret += cnt;
-
- /* we have something to play - go play it! */
- ad1889_trigger_playback(dev);
- }
-
-err2:
- remove_wait_queue(&state->dmabuf.wait, &wait);
-err1:
- mutex_unlock(&state->mutex);
- return ret;
-}
-
-static unsigned int ad1889_poll(struct file *file, struct poll_table_struct *wait)
-{
- unsigned int mask = 0;
-#if 0
- ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
- ad1889_state_t *state = NULL;
- struct dmabuf *dmabuf;
- unsigned long flags;
-
- if (!(file->f_mode & (FMODE_READ | FMODE_WRITE)))
- return -EINVAL;
-
- if (file->f_mode & FMODE_WRITE) {
- state = &dev->state[AD_WAV_STATE];
- if (!state) return 0;
- dmabuf = &state->dmabuf;
- poll_wait(file, &dmabuf->wait, wait);
- }
-
- if (file->f_mode & FMODE_READ) {
- state = &dev->state[AD_ADC_STATE];
- if (!state) return 0;
- dmabuf = &state->dmabuf;
- poll_wait(file, &dmabuf->wait, wait);
- }
-
- spin_lock_irqsave(&dev->lock, flags);
- ad1889_update_ptr(dev, 0);
-
- if (file->f_mode & FMODE_WRITE) {
- state = &dev->state[WAV_STATE];
- dmabuf = &state->dmabuf;
- if (dmabuf->mapped) {
- if (dmabuf->count >= (int)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((int)dmabuf->dmasize >= dmabuf->count +
- (int)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
- }
-
- if (file ->f_mode & FMODE_READ) {
- state = &dev->state[AD_ADC_STATE];
- dmabuf = &state->dmabuf;
- if (dmabuf->count >= (int)dmabuf->fragsize)
- mask |= POLLIN | POLLRDNORM;
- }
- spin_unlock_irqrestore(&dev->lock, flags);
-
-#endif
- return mask;
-}
-
-static int ad1889_mmap(struct file *file, struct vm_area_struct *vma)
-{
- return 0;
-}
-
-static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int val = 0;
- ad1889_dev_t *dev = (ad1889_dev_t *)file->private_data;
- struct dmabuf *dmabuf;
- audio_buf_info abinfo;
- int __user *p = (int __user *)arg;
-
- DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
-
- switch (cmd)
- {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, p);
-
- case SNDCTL_DSP_RESET:
- break;
-
- case SNDCTL_DSP_SYNC:
- break;
-
- case SNDCTL_DSP_SPEED:
- /* set sampling rate */
- if (get_user(val, p))
- return -EFAULT;
- if (val > 5400 && val < 48000)
- {
- if (file->f_mode & FMODE_WRITE)
- AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
- if (file->f_mode & FMODE_READ)
- AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
- }
- return 0;
-
- case SNDCTL_DSP_STEREO: /* undocumented? */
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
- if (val) {
- val |= 0x0200; /* set WAST */
- } else {
- val &= ~0x0200; /* clear WAST */
- }
- AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
- }
- if (file->f_mode & FMODE_WRITE) {
- val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
- if (val) {
- val |= 0x0002; /* set ADST */
- } else {
- val &= ~0x0002; /* clear ADST */
- }
- AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
- }
-
- return 0;
-
- case SNDCTL_DSP_GETBLKSIZE:
- return put_user(DMA_SIZE, p);
-
- case SNDCTL_DSP_GETFMTS:
- return put_user(AFMT_S16_LE|AFMT_U8, p);
-
- case SNDCTL_DSP_SETFMT:
- if (get_user(val, p))
- return -EFAULT;
-
- if (val == 0) {
- if (file->f_mode & FMODE_READ)
- ad1889_set_adc_fmt(dev, val);
-
- if (file->f_mode & FMODE_WRITE)
- ad1889_set_wav_fmt(dev, val);
- } else {
- val = AFMT_S16_LE | AFMT_U8;
- }
-
- return put_user(val, p);
-
- case SNDCTL_DSP_CHANNELS:
- break;
-
- case SNDCTL_DSP_POST:
- /* send all data to device */
- break;
-
- case SNDCTL_DSP_SUBDIVIDE:
- break;
-
- case SNDCTL_DSP_SETFRAGMENT:
- /* not supported; uses fixed fragment sizes */
- return put_user(DMA_SIZE, p);
-
- case SNDCTL_DSP_GETOSPACE:
- case SNDCTL_DSP_GETISPACE:
- /* space left in dma buffers */
- if (cmd == SNDCTL_DSP_GETOSPACE)
- dmabuf = &dev->state[AD_WAV_STATE].dmabuf;
- else
- dmabuf = &dev->state[AD_ADC_STATE].dmabuf;
- abinfo.fragments = 1;
- abinfo.fragstotal = 1;
- abinfo.fragsize = DMA_SIZE;
- abinfo.bytes = DMA_SIZE;
- return copy_to_user(p, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- return 0;
-
- case SNDCTL_DSP_GETCAPS:
- return put_user(0, p);
-
- case SNDCTL_DSP_GETTRIGGER:
- case SNDCTL_DSP_SETTRIGGER:
- break;
-
- case SNDCTL_DSP_GETIPTR:
- case SNDCTL_DSP_GETOPTR:
- break;
-
- case SNDCTL_DSP_SETDUPLEX:
- break;
-
- case SNDCTL_DSP_GETODELAY:
- break;
-
- case SOUND_PCM_READ_RATE:
- return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
-
- case SOUND_PCM_READ_CHANNELS:
- case SOUND_PCM_READ_BITS:
- break;
-
- case SNDCTL_DSP_MAPINBUF:
- case SNDCTL_DSP_MAPOUTBUF:
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_WRITE_FILTER:
- case SOUND_PCM_READ_FILTER:
- break;
-
- default:
- break;
- }
-
- return -ENOTTY;
-}
-
-static int ad1889_open(struct inode *inode, struct file *file)
-{
- /* check minor; only support /dev/dsp atm */
- if (iminor(inode) != 3)
- return -ENXIO;
-
- file->private_data = ad1889_dev;
-
- ad1889_set_wav_rate(ad1889_dev, 48000);
- ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
- AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
- return nonseekable_open(inode, file);
-}
-
-static int ad1889_release(struct inode *inode, struct file *file)
-{
- /* if we have state free it here */
- return 0;
-}
-
-static const struct file_operations ad1889_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = ad1889_read,
- .write = ad1889_write,
- .poll = ad1889_poll,
- .ioctl = ad1889_ioctl,
- .mmap = ad1889_mmap,
- .open = ad1889_open,
- .release = ad1889_release,
-};
-
-/************************* /dev/mixer interfaces ************************ */
-static int ad1889_mixer_open(struct inode *inode, struct file *file)
-{
- if (ad1889_dev->ac97_codec->dev_mixer != iminor(inode))
- return -ENODEV;
-
- file->private_data = ad1889_dev->ac97_codec;
- return 0;
-}
-
-static int ad1889_mixer_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static int ad1889_mixer_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
- return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static const struct file_operations ad1889_mixer_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .ioctl = ad1889_mixer_ioctl,
- .open = ad1889_mixer_open,
- .release = ad1889_mixer_release,
-};
-
-/************************* AC97 interfaces ****************************** */
-static void ad1889_codec_write(struct ac97_codec *ac97, u8 reg, u16 val)
-{
- ad1889_dev_t *dev = ac97->private_data;
-
- //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
- AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
-}
-
-static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
-{
- ad1889_dev_t *dev = ac97->private_data;
- //DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
- return AD1889_READW(dev, AD_AC97_BASE + reg);
-}
-
-static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
-{
- struct ac97_codec *ac97;
- u16 eid;
-
- if ((ac97 = ac97_alloc_codec()) == NULL)
- return -ENOMEM;
-
- ac97->private_data = dev;
- ac97->id = id;
-
- ac97->codec_read = ad1889_codec_read;
- ac97->codec_write = ad1889_codec_write;
-
- if (ac97_probe_codec(ac97) == 0) {
- printk(DEVNAME ": ac97_probe_codec failed\n");
- goto out_free;
- }
-
- eid = ad1889_codec_read(ac97, AC97_EXTENDED_ID);
- if (eid == 0xffff) {
- printk(KERN_WARNING DEVNAME ": no codec attached?\n");
- goto out_free;
- }
-
- dev->ac97_features = eid;
-
- if ((ac97->dev_mixer = register_sound_mixer(&ad1889_mixer_fops, -1)) < 0) {
- printk(KERN_ERR DEVNAME ": cannot register mixer\n");
- goto out_free;
- }
-
- dev->ac97_codec = ac97;
- return 0;
-
-out_free:
- ac97_release_codec(ac97);
- return -ENODEV;
-}
-
-static int ad1889_aclink_reset(struct pci_dev * pcidev)
-{
- u16 stat;
- int retry = 200;
- ad1889_dev_t *dev = pci_get_drvdata(pcidev);
-
- AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
- AD1889_READW(dev, AD_DS_CCS);
-
- WAIT_10MS();
-
- stat = AD1889_READW(dev, AD_AC97_ACIC);
- stat |= 0x0002; /* Reset Disable */
- AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
- (void) AD1889_READW(dev, AD_AC97_ACIC); /* flush posted write */
-
- udelay(10);
-
- stat = AD1889_READW(dev, AD_AC97_ACIC);
- stat |= 0x0001; /* Interface Enable */
- AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
-
- do {
- if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000) /* Ready */
- break;
- WAIT_10MS();
- retry--;
- } while (retry > 0);
-
- if (!retry) {
- printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
- AD1889_READW(dev, AD_AC97_ACIC));
- return -EBUSY;
- }
-
- /* TODO reset AC97 codec */
- /* TODO set wave/adc pci ctrl status */
-
- stat = AD1889_READW(dev, AD_AC97_ACIC);
- stat |= 0x0004; /* Audio Stream Output Enable */
- AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
- return 0;
-}
-
-/************************* PCI interfaces ****************************** */
-/* PCI device table */
-static struct pci_device_id ad1889_id_tbl[] = {
- { PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS, PCI_ANY_ID,
- PCI_ANY_ID, 0, 0, (unsigned long)DEVNAME },
- { },
-};
-MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
-
-static irqreturn_t ad1889_interrupt(int irq, void *dev_id)
-{
- u32 stat;
- ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
-
- stat = AD1889_READL(dev, AD_DMA_DISR);
-
- /* clear ISR */
- AD1889_WRITEL(dev, AD_DMA_DISR, stat);
-
- if (stat & 0x8) { /* WAVI */
- DBG("WAV interrupt\n");
- dev->stats.wav_intrs++;
- if (dev->state[AD_WAV_STATE].dmabuf.ready) {
- ad1889_stop_wav(&dev->state[AD_WAV_STATE]); /* clean up */
- ad1889_start_wav(&dev->state[AD_WAV_STATE]); /* start new */
- }
- }
-
- if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
- DBG("ADC interrupt\n");
- dev->stats.adc_intrs++;
- }
- if(stat)
- return IRQ_HANDLED;
- return IRQ_NONE;
-}
-
-static void ad1889_initcfg(ad1889_dev_t *dev)
-{
- u16 tmp16;
- u32 tmp32;
-
- /* make sure the interrupt bits are setup the way we want */
- tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
- tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
- tmp32 |= 0x6; /* intr on count, loop */
- AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
-
- /* unmute... */
- tmp16 = AD1889_READW(dev, AD_DS_WADA);
- tmp16 &= ~0x8080;
- AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
-}
-
-static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
-{
- int err;
- ad1889_dev_t *dev;
- unsigned long bar;
- struct proc_dir_entry *proc_root = NULL;
-
- if ((err = pci_enable_device(pcidev)) != 0) {
- printk(KERN_ERR DEVNAME ": pci_enable_device failed\n");
- return err;
- }
-
- pci_set_master(pcidev);
- if ((dev = ad1889_alloc_dev(pcidev)) == NULL) {
- printk(KERN_ERR DEVNAME ": cannot allocate memory for device\n");
- return -ENOMEM;
- }
- pci_set_drvdata(pcidev, dev);
- bar = pci_resource_start(pcidev, 0);
-
- if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
- printk(KERN_ERR DEVNAME ": memory region not assigned\n");
- goto out1;
- }
-
- if (pci_request_region(pcidev, 0, DEVNAME)) {
- printk(KERN_ERR DEVNAME ": unable to request memory region\n");
- goto out1;
- }
-
- dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
- if (!dev->regbase) {
- printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
- goto out2;
- }
-
- if (request_irq(pcidev->irq, ad1889_interrupt, IRQF_SHARED, DEVNAME, dev) != 0) {
- printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
- goto out3;
- }
-
- printk(KERN_INFO DEVNAME ": %s at %p IRQ %d\n",
- (char *)ent->driver_data, dev->regbase, pcidev->irq);
-
- if (ad1889_aclink_reset(pcidev) != 0)
- goto out4;
-
- /* register /dev/dsp */
- if ((dev->dev_audio = register_sound_dsp(&ad1889_fops, -1)) < 0) {
- printk(KERN_ERR DEVNAME ": cannot register /dev/dsp\n");
- goto out4;
- }
-
- if ((err = ad1889_ac97_init(dev, 0)) != 0)
- goto out5;
-
- /* XXX: cleanups */
- if (((proc_root = proc_mkdir("driver/ad1889", NULL)) == NULL) ||
- create_proc_read_entry("ac97", S_IFREG|S_IRUGO, proc_root, ac97_read_proc, dev->ac97_codec) == NULL ||
- create_proc_read_entry("info", S_IFREG|S_IRUGO, proc_root, ad1889_read_proc, dev) == NULL)
- goto out5;
-
- ad1889_initcfg(dev);
-
- //DBG(DEVNAME ": Driver initialization done!\n");
-
- ad1889_dev = dev;
-
- return 0;
-
-out5:
- unregister_sound_dsp(dev->dev_audio);
-out4:
- free_irq(pcidev->irq, dev);
-out3:
- iounmap(dev->regbase);
-out2:
- pci_release_region(pcidev, 0);
-out1:
- ad1889_free_dev(dev);
- pci_set_drvdata(pcidev, NULL);
-
- return -ENODEV;
-}
-
-static void __devexit ad1889_remove(struct pci_dev *pcidev)
-{
- ad1889_dev_t *dev = pci_get_drvdata(pcidev);
-
- if (dev == NULL) return;
-
- unregister_sound_mixer(dev->ac97_codec->dev_mixer);
- unregister_sound_dsp(dev->dev_audio);
- free_irq(pcidev->irq, dev);
- iounmap(dev->regbase);
- pci_release_region(pcidev, 0);
-
- /* any hw programming needed? */
- ad1889_free_dev(dev);
- pci_set_drvdata(pcidev, NULL);
-}
-
-MODULE_AUTHOR("Randolph Chung");
-MODULE_DESCRIPTION("Analog Devices AD1889 PCI Audio");
-MODULE_LICENSE("GPL");
-
-static struct pci_driver ad1889_driver = {
- .name = DEVNAME,
- .id_table = ad1889_id_tbl,
- .probe = ad1889_probe,
- .remove = __devexit_p(ad1889_remove),
-};
-
-static int __init ad1889_init_module(void)
-{
- return pci_register_driver(&ad1889_driver);
-}
-
-static void ad1889_exit_module(void)
-{
- pci_unregister_driver(&ad1889_driver);
- return;
-}
-
-module_init(ad1889_init_module);
-module_exit(ad1889_exit_module);
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
deleted file mode 100644
index 09913765967a..000000000000
--- a/sound/oss/ad1889.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _AD1889_H_
-#define _AD1889_H_
-
-#define AD_DS_WSMC 0x00 /* DMA input wave/syn mixer control */
-#define AD_DS_RAMC 0x02 /* DMA output resamp/ADC mixer control */
-#define AD_DS_WADA 0x04 /* DMA input wave attenuation */
-#define AD_DS_SYDA 0x06 /* DMA input syn attentuation */
-#define AD_DS_WAS 0x08 /* wave input sample rate */
-#define AD_DS_RES 0x0a /* resampler output sample rate */
-#define AD_DS_CCS 0x0c /* chip control/status */
-
-#define AD_DMA_RESBA 0x40 /* RES base addr */
-#define AD_DMA_RESCA 0x44 /* RES current addr */
-#define AD_DMA_RESBC 0x48 /* RES base cnt */
-#define AD_DMA_RESCC 0x4c /* RES current count */
-#define AD_DMA_ADCBA 0x50 /* ADC */
-#define AD_DMA_ADCCA 0x54
-#define AD_DMA_ADCBC 0x58
-#define AD_DMA_ADCCC 0x5c
-#define AD_DMA_SYNBA 0x60 /* SYN */
-#define AD_DMA_SYNCA 0x64
-#define AD_DMA_SYNBC 0x68
-#define AD_DMA_SYNCC 0x6c
-#define AD_DMA_WAVBA 0x70 /* WAV */
-#define AD_DMA_WAVCA 0x74
-#define AD_DMA_WAVBC 0x78
-#define AD_DMA_WAVCC 0x7c
-#define AD_DMA_RESICC 0x80 /* RES interrupt current count */
-#define AD_DMA_RESIBC 0x84 /* RES interrupt base count */
-#define AD_DMA_ADCICC 0x88 /* ADC interrupt current count */
-#define AD_DMA_ADCIBC 0x8c /* ADC interrupt base count */
-#define AD_DMA_SYNICC 0x90 /* SYN interrupt current count */
-#define AD_DMA_SYNIBC 0x94 /* SYN interrupt base count */
-#define AD_DMA_WAVICC 0x98 /* WAV interrupt current count */
-#define AD_DMA_WAVIBC 0x9c /* WAV interrupt base count */
-#define AD_DMA_RESCTRL 0xa0 /* RES PCI control/status */
-#define AD_DMA_ADCCTRL 0xa8 /* ADC PCI control/status */
-#define AD_DMA_SYNCTRL 0xb0 /* SYN PCI control/status */
-#define AD_DMA_WAVCTRL 0xb8 /* WAV PCI control/status */
-#define AD_DMA_DISR 0xc0 /* PCI DMA intr status */
-#define AD_DMA_CHSS 0xc4 /* PCI DMA channel stop status */
-
-#define AD_GPIO_IPC 0xc8 /* IO port ctrl */
-#define AD_GPIO_OP 0xca /* IO output status */
-#define AD_GPIO_IP 0xcc /* IO input status */
-
-/* AC97 registers, 0x100 - 0x17f; see ac97.h */
-#define AD_AC97_BASE 0x100 /* ac97 base register */
-#define AD_AC97_ACIC 0x180 /* AC Link interface ctrl */
-
-/* OPL3; BAR1 */
-#define AD_OPL_M0AS 0x00 /* Music0 address/status */
-#define AD_OPL_M0DATA 0x01 /* Music0 data */
-#define AD_OPL_M1A 0x02 /* Music1 address */
-#define AD_OPL_M1DATA 0x03 /* Music1 data */
-/* 0x04-0x0f reserved */
-
-/* MIDI; BAR2 */
-#define AD_MIDA 0x00 /* MIDI data */
-#define AD_MISC 0x01 /* MIDI status/cmd */
-/* 0x02-0xff reserved */
-
-#define AD_DS_IOMEMSIZE 512
-#define AD_OPL_MEMSIZE 16
-#define AD_MIDI_MEMSIZE 16
-
-#define AD_WAV_STATE 0
-#define AD_ADC_STATE 1
-#define AD_MAX_STATES 2
-
-#define DMA_SIZE (128*1024)
-
-#define DMA_FLAG_MAPPED 1
-
-struct ad1889_dev;
-
-typedef struct ad1889_state {
- struct ad1889_dev *card;
-
- mode_t open_mode;
- struct dmabuf {
- unsigned int rate;
- unsigned char fmt, enable;
-
- /* buf management */
- size_t rawbuf_size;
- void *rawbuf;
- dma_addr_t dma_handle; /* mapped address */
- unsigned long dma_len; /* number of bytes mapped */
-
- /* indexes into rawbuf for setting up DMA engine */
- volatile unsigned long rd_ptr, wr_ptr;
-
- wait_queue_head_t wait; /* to wait for buf servicing */
-
- /* OSS bits */
- unsigned int mapped:1;
- unsigned int ready:1;
- unsigned int ossfragshift;
- int ossmaxfrags;
- unsigned int subdivision;
- } dmabuf;
-
- struct mutex mutex;
-} ad1889_state_t;
-
-typedef struct ad1889_dev {
- void __iomem *regbase;
- struct pci_dev *pci;
-
- spinlock_t lock;
-
- int dev_audio;
-
- /* states; one per channel; right now only WAV and ADC */
- struct ad1889_state state[AD_MAX_STATES];
-
- /* AC97 codec */
- struct ac97_codec *ac97_codec;
- u16 ac97_features;
-
- /* debugging stuff */
- struct stats {
- unsigned int wav_intrs, adc_intrs;
- unsigned int blocks, underrun, error;
- } stats;
-} ad1889_dev_t;
-
-typedef struct ad1889_reg {
- const char *name;
- int offset;
- int width;
-} ad1889_reg_t;
-
-#endif
diff --git a/sound/oss/adlib_card.c b/sound/oss/adlib_card.c
deleted file mode 100644
index c9a7c9b470de..000000000000
--- a/sound/oss/adlib_card.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * sound/oss/adlib_card.c
- *
- * Detection routine for the AdLib card.
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "sound_config.h"
-
-#include "opl3.h"
-
-static void __init attach_adlib_card(struct address_info *hw_config)
-{
- hw_config->slots[0] = opl3_init(hw_config->io_base, hw_config->osp, THIS_MODULE);
-}
-
-static int __init probe_adlib(struct address_info *hw_config)
-{
- return opl3_detect(hw_config->io_base, hw_config->osp);
-}
-
-static struct address_info cfg;
-
-static int __initdata io = -1;
-
-module_param(io, int, 0);
-
-static int __init init_adlib(void)
-{
- cfg.io_base = io;
-
- if (cfg.io_base == -1) {
- printk(KERN_ERR "adlib: must specify I/O address.\n");
- return -EINVAL;
- }
- if (probe_adlib(&cfg) == 0)
- return -ENODEV;
- attach_adlib_card(&cfg);
-
- return 0;
-}
-
-static void __exit cleanup_adlib(void)
-{
- sound_unload_synthdev(cfg.slots[0]);
-
-}
-
-module_init(init_adlib);
-module_exit(cleanup_adlib);
-
-#ifndef MODULE
-static int __init setup_adlib(char *str)
-{
- /* io */
- int ints[2];
- str = get_options(str, ARRAY_SIZE(ints), ints);
-
- io = ints[1];
-
- return 1;
-}
-__setup("adlib=", setup_adlib);
-#endif
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/cs461x.h b/sound/oss/cs461x.h
deleted file mode 100644
index 0ce41338e6dd..000000000000
--- a/sound/oss/cs461x.h
+++ /dev/null
@@ -1,1691 +0,0 @@
-#ifndef __CS461X_H
-#define __CS461X_H
-
-/*
- * Copyright (c) by Cirrus Logic Corporation <pcaudio@crystal.cirrus.com>
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- * Definitions for Cirrus Logic CS461x chips
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS 0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
-#endif
-
-/*
- * Direct registers
- */
-
-/*
- * The following define the offsets of the registers accessed via base address
- * register zero on the CS461x part.
- */
-#define BA0_HISR 0x00000000
-#define BA0_HSR0 0x00000004
-#define BA0_HICR 0x00000008
-#define BA0_DMSR 0x00000100
-#define BA0_HSAR 0x00000110
-#define BA0_HDAR 0x00000114
-#define BA0_HDMR 0x00000118
-#define BA0_HDCR 0x0000011C
-#define BA0_PFMC 0x00000200
-#define BA0_PFCV1 0x00000204
-#define BA0_PFCV2 0x00000208
-#define BA0_PCICFG00 0x00000300
-#define BA0_PCICFG04 0x00000304
-#define BA0_PCICFG08 0x00000308
-#define BA0_PCICFG0C 0x0000030C
-#define BA0_PCICFG10 0x00000310
-#define BA0_PCICFG14 0x00000314
-#define BA0_PCICFG18 0x00000318
-#define BA0_PCICFG1C 0x0000031C
-#define BA0_PCICFG20 0x00000320
-#define BA0_PCICFG24 0x00000324
-#define BA0_PCICFG28 0x00000328
-#define BA0_PCICFG2C 0x0000032C
-#define BA0_PCICFG30 0x00000330
-#define BA0_PCICFG34 0x00000334
-#define BA0_PCICFG38 0x00000338
-#define BA0_PCICFG3C 0x0000033C
-#define BA0_CLKCR1 0x00000400
-#define BA0_CLKCR2 0x00000404
-#define BA0_PLLM 0x00000408
-#define BA0_PLLCC 0x0000040C
-#define BA0_FRR 0x00000410
-#define BA0_CFL1 0x00000414
-#define BA0_CFL2 0x00000418
-#define BA0_SERMC1 0x00000420
-#define BA0_SERMC2 0x00000424
-#define BA0_SERC1 0x00000428
-#define BA0_SERC2 0x0000042C
-#define BA0_SERC3 0x00000430
-#define BA0_SERC4 0x00000434
-#define BA0_SERC5 0x00000438
-#define BA0_SERBSP 0x0000043C
-#define BA0_SERBST 0x00000440
-#define BA0_SERBCM 0x00000444
-#define BA0_SERBAD 0x00000448
-#define BA0_SERBCF 0x0000044C
-#define BA0_SERBWP 0x00000450
-#define BA0_SERBRP 0x00000454
-#ifndef NO_CS4612
-#define BA0_ASER_FADDR 0x00000458
-#endif
-#define BA0_ACCTL 0x00000460
-#define BA0_ACSTS 0x00000464
-#define BA0_ACOSV 0x00000468
-#define BA0_ACCAD 0x0000046C
-#define BA0_ACCDA 0x00000470
-#define BA0_ACISV 0x00000474
-#define BA0_ACSAD 0x00000478
-#define BA0_ACSDA 0x0000047C
-#define BA0_JSPT 0x00000480
-#define BA0_JSCTL 0x00000484
-#define BA0_JSC1 0x00000488
-#define BA0_JSC2 0x0000048C
-#define BA0_MIDCR 0x00000490
-#define BA0_MIDSR 0x00000494
-#define BA0_MIDWP 0x00000498
-#define BA0_MIDRP 0x0000049C
-#define BA0_JSIO 0x000004A0
-#ifndef NO_CS4612
-#define BA0_ASER_MASTER 0x000004A4
-#endif
-#define BA0_CFGI 0x000004B0
-#define BA0_SSVID 0x000004B4
-#define BA0_GPIOR 0x000004B8
-#ifndef NO_CS4612
-#define BA0_EGPIODR 0x000004BC
-#define BA0_EGPIOPTR 0x000004C0
-#define BA0_EGPIOTR 0x000004C4
-#define BA0_EGPIOWR 0x000004C8
-#define BA0_EGPIOSR 0x000004CC
-#define BA0_SERC6 0x000004D0
-#define BA0_SERC7 0x000004D4
-#define BA0_SERACC 0x000004D8
-#define BA0_ACCTL2 0x000004E0
-#define BA0_ACSTS2 0x000004E4
-#define BA0_ACOSV2 0x000004E8
-#define BA0_ACCAD2 0x000004EC
-#define BA0_ACCDA2 0x000004F0
-#define BA0_ACISV2 0x000004F4
-#define BA0_ACSAD2 0x000004F8
-#define BA0_ACSDA2 0x000004FC
-#define BA0_IOTAC0 0x00000500
-#define BA0_IOTAC1 0x00000504
-#define BA0_IOTAC2 0x00000508
-#define BA0_IOTAC3 0x0000050C
-#define BA0_IOTAC4 0x00000510
-#define BA0_IOTAC5 0x00000514
-#define BA0_IOTAC6 0x00000518
-#define BA0_IOTAC7 0x0000051C
-#define BA0_IOTAC8 0x00000520
-#define BA0_IOTAC9 0x00000524
-#define BA0_IOTAC10 0x00000528
-#define BA0_IOTAC11 0x0000052C
-#define BA0_IOTFR0 0x00000540
-#define BA0_IOTFR1 0x00000544
-#define BA0_IOTFR2 0x00000548
-#define BA0_IOTFR3 0x0000054C
-#define BA0_IOTFR4 0x00000550
-#define BA0_IOTFR5 0x00000554
-#define BA0_IOTFR6 0x00000558
-#define BA0_IOTFR7 0x0000055C
-#define BA0_IOTFIFO 0x00000580
-#define BA0_IOTRRD 0x00000584
-#define BA0_IOTFP 0x00000588
-#define BA0_IOTCR 0x0000058C
-#define BA0_DPCID 0x00000590
-#define BA0_DPCIA 0x00000594
-#define BA0_DPCIC 0x00000598
-#define BA0_PCPCIR 0x00000600
-#define BA0_PCPCIG 0x00000604
-#define BA0_PCPCIEN 0x00000608
-#define BA0_EPCIPMC 0x00000610
-#endif
-
-/*
- * The following define the offsets of the registers and memories accessed via
- * base address register one on the CS461x part.
- */
-#define BA1_SP_DMEM0 0x00000000
-#define BA1_SP_DMEM1 0x00010000
-#define BA1_SP_PMEM 0x00020000
-#define BA1_SP_REG 0x00030000
-#define BA1_SPCR 0x00030000
-#define BA1_DREG 0x00030004
-#define BA1_DSRWP 0x00030008
-#define BA1_TWPR 0x0003000C
-#define BA1_SPWR 0x00030010
-#define BA1_SPIR 0x00030014
-#define BA1_FGR1 0x00030020
-#define BA1_SPCS 0x00030028
-#define BA1_SDSR 0x0003002C
-#define BA1_FRMT 0x00030030
-#define BA1_FRCC 0x00030034
-#define BA1_FRSC 0x00030038
-#define BA1_OMNI_MEM 0x000E0000
-
-/*
- * The following defines are for the flags in the host interrupt status
- * register.
- */
-#define HISR_VC_MASK 0x0000FFFF
-#define HISR_VC0 0x00000001
-#define HISR_VC1 0x00000002
-#define HISR_VC2 0x00000004
-#define HISR_VC3 0x00000008
-#define HISR_VC4 0x00000010
-#define HISR_VC5 0x00000020
-#define HISR_VC6 0x00000040
-#define HISR_VC7 0x00000080
-#define HISR_VC8 0x00000100
-#define HISR_VC9 0x00000200
-#define HISR_VC10 0x00000400
-#define HISR_VC11 0x00000800
-#define HISR_VC12 0x00001000
-#define HISR_VC13 0x00002000
-#define HISR_VC14 0x00004000
-#define HISR_VC15 0x00008000
-#define HISR_INT0 0x00010000
-#define HISR_INT1 0x00020000
-#define HISR_DMAI 0x00040000
-#define HISR_FROVR 0x00080000
-#define HISR_MIDI 0x00100000
-#ifdef NO_CS4612
-#define HISR_RESERVED 0x0FE00000
-#else
-#define HISR_SBINT 0x00200000
-#define HISR_RESERVED 0x0FC00000
-#endif
-#define HISR_H0P 0x40000000
-#define HISR_INTENA 0x80000000
-
-/*
- * The following defines are for the flags in the host signal register 0.
- */
-#define HSR0_VC_MASK 0xFFFFFFFF
-#define HSR0_VC16 0x00000001
-#define HSR0_VC17 0x00000002
-#define HSR0_VC18 0x00000004
-#define HSR0_VC19 0x00000008
-#define HSR0_VC20 0x00000010
-#define HSR0_VC21 0x00000020
-#define HSR0_VC22 0x00000040
-#define HSR0_VC23 0x00000080
-#define HSR0_VC24 0x00000100
-#define HSR0_VC25 0x00000200
-#define HSR0_VC26 0x00000400
-#define HSR0_VC27 0x00000800
-#define HSR0_VC28 0x00001000
-#define HSR0_VC29 0x00002000
-#define HSR0_VC30 0x00004000
-#define HSR0_VC31 0x00008000
-#define HSR0_VC32 0x00010000
-#define HSR0_VC33 0x00020000
-#define HSR0_VC34 0x00040000
-#define HSR0_VC35 0x00080000
-#define HSR0_VC36 0x00100000
-#define HSR0_VC37 0x00200000
-#define HSR0_VC38 0x00400000
-#define HSR0_VC39 0x00800000
-#define HSR0_VC40 0x01000000
-#define HSR0_VC41 0x02000000
-#define HSR0_VC42 0x04000000
-#define HSR0_VC43 0x08000000
-#define HSR0_VC44 0x10000000
-#define HSR0_VC45 0x20000000
-#define HSR0_VC46 0x40000000
-#define HSR0_VC47 0x80000000
-
-/*
- * The following defines are for the flags in the host interrupt control
- * register.
- */
-#define HICR_IEV 0x00000001
-#define HICR_CHGM 0x00000002
-
-/*
- * The following defines are for the flags in the DMA status register.
- */
-#define DMSR_HP 0x00000001
-#define DMSR_HR 0x00000002
-#define DMSR_SP 0x00000004
-#define DMSR_SR 0x00000008
-
-/*
- * The following defines are for the flags in the host DMA source address
- * register.
- */
-#define HSAR_HOST_ADDR_MASK 0xFFFFFFFF
-#define HSAR_DSP_ADDR_MASK 0x0000FFFF
-#define HSAR_MEMID_MASK 0x000F0000
-#define HSAR_MEMID_SP_DMEM0 0x00000000
-#define HSAR_MEMID_SP_DMEM1 0x00010000
-#define HSAR_MEMID_SP_PMEM 0x00020000
-#define HSAR_MEMID_SP_DEBUG 0x00030000
-#define HSAR_MEMID_OMNI_MEM 0x000E0000
-#define HSAR_END 0x40000000
-#define HSAR_ERR 0x80000000
-
-/*
- * The following defines are for the flags in the host DMA destination address
- * register.
- */
-#define HDAR_HOST_ADDR_MASK 0xFFFFFFFF
-#define HDAR_DSP_ADDR_MASK 0x0000FFFF
-#define HDAR_MEMID_MASK 0x000F0000
-#define HDAR_MEMID_SP_DMEM0 0x00000000
-#define HDAR_MEMID_SP_DMEM1 0x00010000
-#define HDAR_MEMID_SP_PMEM 0x00020000
-#define HDAR_MEMID_SP_DEBUG 0x00030000
-#define HDAR_MEMID_OMNI_MEM 0x000E0000
-#define HDAR_END 0x40000000
-#define HDAR_ERR 0x80000000
-
-/*
- * The following defines are for the flags in the host DMA control register.
- */
-#define HDMR_AC_MASK 0x0000F000
-#define HDMR_AC_8_16 0x00001000
-#define HDMR_AC_M_S 0x00002000
-#define HDMR_AC_B_L 0x00004000
-#define HDMR_AC_S_U 0x00008000
-
-/*
- * The following defines are for the flags in the host DMA control register.
- */
-#define HDCR_COUNT_MASK 0x000003FF
-#define HDCR_DONE 0x00004000
-#define HDCR_OPT 0x00008000
-#define HDCR_WBD 0x00400000
-#define HDCR_WBS 0x00800000
-#define HDCR_DMS_MASK 0x07000000
-#define HDCR_DMS_LINEAR 0x00000000
-#define HDCR_DMS_16_DWORDS 0x01000000
-#define HDCR_DMS_32_DWORDS 0x02000000
-#define HDCR_DMS_64_DWORDS 0x03000000
-#define HDCR_DMS_128_DWORDS 0x04000000
-#define HDCR_DMS_256_DWORDS 0x05000000
-#define HDCR_DMS_512_DWORDS 0x06000000
-#define HDCR_DMS_1024_DWORDS 0x07000000
-#define HDCR_DH 0x08000000
-#define HDCR_SMS_MASK 0x70000000
-#define HDCR_SMS_LINEAR 0x00000000
-#define HDCR_SMS_16_DWORDS 0x10000000
-#define HDCR_SMS_32_DWORDS 0x20000000
-#define HDCR_SMS_64_DWORDS 0x30000000
-#define HDCR_SMS_128_DWORDS 0x40000000
-#define HDCR_SMS_256_DWORDS 0x50000000
-#define HDCR_SMS_512_DWORDS 0x60000000
-#define HDCR_SMS_1024_DWORDS 0x70000000
-#define HDCR_SH 0x80000000
-#define HDCR_COUNT_SHIFT 0
-
-/*
- * The following defines are for the flags in the performance monitor control
- * register.
- */
-#define PFMC_C1SS_MASK 0x0000001F
-#define PFMC_C1EV 0x00000020
-#define PFMC_C1RS 0x00008000
-#define PFMC_C2SS_MASK 0x001F0000
-#define PFMC_C2EV 0x00200000
-#define PFMC_C2RS 0x80000000
-#define PFMC_C1SS_SHIFT 0
-#define PFMC_C2SS_SHIFT 16
-#define PFMC_BUS_GRANT 0
-#define PFMC_GRANT_AFTER_REQ 1
-#define PFMC_TRANSACTION 2
-#define PFMC_DWORD_TRANSFER 3
-#define PFMC_SLAVE_READ 4
-#define PFMC_SLAVE_WRITE 5
-#define PFMC_PREEMPTION 6
-#define PFMC_DISCONNECT_RETRY 7
-#define PFMC_INTERRUPT 8
-#define PFMC_BUS_OWNERSHIP 9
-#define PFMC_TRANSACTION_LAG 10
-#define PFMC_PCI_CLOCK 11
-#define PFMC_SERIAL_CLOCK 12
-#define PFMC_SP_CLOCK 13
-
-/*
- * The following defines are for the flags in the performance counter value 1
- * register.
- */
-#define PFCV1_PC1V_MASK 0xFFFFFFFF
-#define PFCV1_PC1V_SHIFT 0
-
-/*
- * The following defines are for the flags in the performance counter value 2
- * register.
- */
-#define PFCV2_PC2V_MASK 0xFFFFFFFF
-#define PFCV2_PC2V_SHIFT 0
-
-/*
- * The following defines are for the flags in the clock control register 1.
- */
-#define CLKCR1_OSCS 0x00000001
-#define CLKCR1_OSCP 0x00000002
-#define CLKCR1_PLLSS_MASK 0x0000000C
-#define CLKCR1_PLLSS_SERIAL 0x00000000
-#define CLKCR1_PLLSS_CRYSTAL 0x00000004
-#define CLKCR1_PLLSS_PCI 0x00000008
-#define CLKCR1_PLLSS_RESERVED 0x0000000C
-#define CLKCR1_PLLP 0x00000010
-#define CLKCR1_SWCE 0x00000020
-#define CLKCR1_PLLOS 0x00000040
-
-/*
- * The following defines are for the flags in the clock control register 2.
- */
-#define CLKCR2_PDIVS_MASK 0x0000000F
-#define CLKCR2_PDIVS_1 0x00000001
-#define CLKCR2_PDIVS_2 0x00000002
-#define CLKCR2_PDIVS_4 0x00000004
-#define CLKCR2_PDIVS_7 0x00000007
-#define CLKCR2_PDIVS_8 0x00000008
-#define CLKCR2_PDIVS_16 0x00000000
-
-/*
- * The following defines are for the flags in the PLL multiplier register.
- */
-#define PLLM_MASK 0x000000FF
-#define PLLM_SHIFT 0
-
-/*
- * The following defines are for the flags in the PLL capacitor coefficient
- * register.
- */
-#define PLLCC_CDR_MASK 0x00000007
-#ifndef NO_CS4610
-#define PLLCC_CDR_240_350_MHZ 0x00000000
-#define PLLCC_CDR_184_265_MHZ 0x00000001
-#define PLLCC_CDR_144_205_MHZ 0x00000002
-#define PLLCC_CDR_111_160_MHZ 0x00000003
-#define PLLCC_CDR_87_123_MHZ 0x00000004
-#define PLLCC_CDR_67_96_MHZ 0x00000005
-#define PLLCC_CDR_52_74_MHZ 0x00000006
-#define PLLCC_CDR_45_58_MHZ 0x00000007
-#endif
-#ifndef NO_CS4612
-#define PLLCC_CDR_271_398_MHZ 0x00000000
-#define PLLCC_CDR_227_330_MHZ 0x00000001
-#define PLLCC_CDR_167_239_MHZ 0x00000002
-#define PLLCC_CDR_150_215_MHZ 0x00000003
-#define PLLCC_CDR_107_154_MHZ 0x00000004
-#define PLLCC_CDR_98_140_MHZ 0x00000005
-#define PLLCC_CDR_73_104_MHZ 0x00000006
-#define PLLCC_CDR_63_90_MHZ 0x00000007
-#endif
-#define PLLCC_LPF_MASK 0x000000F8
-#ifndef NO_CS4610
-#define PLLCC_LPF_23850_60000_KHZ 0x00000000
-#define PLLCC_LPF_7960_26290_KHZ 0x00000008
-#define PLLCC_LPF_4160_10980_KHZ 0x00000018
-#define PLLCC_LPF_1740_4580_KHZ 0x00000038
-#define PLLCC_LPF_724_1910_KHZ 0x00000078
-#define PLLCC_LPF_317_798_KHZ 0x000000F8
-#endif
-#ifndef NO_CS4612
-#define PLLCC_LPF_25580_64530_KHZ 0x00000000
-#define PLLCC_LPF_14360_37270_KHZ 0x00000008
-#define PLLCC_LPF_6100_16020_KHZ 0x00000018
-#define PLLCC_LPF_2540_6690_KHZ 0x00000038
-#define PLLCC_LPF_1050_2780_KHZ 0x00000078
-#define PLLCC_LPF_450_1160_KHZ 0x000000F8
-#endif
-
-/*
- * The following defines are for the flags in the feature reporting register.
- */
-#define FRR_FAB_MASK 0x00000003
-#define FRR_MASK_MASK 0x0000001C
-#ifdef NO_CS4612
-#define FRR_CFOP_MASK 0x000000E0
-#else
-#define FRR_CFOP_MASK 0x00000FE0
-#endif
-#define FRR_CFOP_NOT_DVD 0x00000020
-#define FRR_CFOP_A3D 0x00000040
-#define FRR_CFOP_128_PIN 0x00000080
-#ifndef NO_CS4612
-#define FRR_CFOP_CS4280 0x00000800
-#endif
-#define FRR_FAB_SHIFT 0
-#define FRR_MASK_SHIFT 2
-#define FRR_CFOP_SHIFT 5
-
-/*
- * The following defines are for the flags in the configuration load 1
- * register.
- */
-#define CFL1_CLOCK_SOURCE_MASK 0x00000003
-#define CFL1_CLOCK_SOURCE_CS423X 0x00000000
-#define CFL1_CLOCK_SOURCE_AC97 0x00000001
-#define CFL1_CLOCK_SOURCE_CRYSTAL 0x00000002
-#define CFL1_CLOCK_SOURCE_DUAL_AC97 0x00000003
-#define CFL1_VALID_DATA_MASK 0x000000FF
-
-/*
- * The following defines are for the flags in the configuration load 2
- * register.
- */
-#define CFL2_VALID_DATA_MASK 0x000000FF
-
-/*
- * The following defines are for the flags in the serial port master control
- * register 1.
- */
-#define SERMC1_MSPE 0x00000001
-#define SERMC1_PTC_MASK 0x0000000E
-#define SERMC1_PTC_CS423X 0x00000000
-#define SERMC1_PTC_AC97 0x00000002
-#define SERMC1_PTC_DAC 0x00000004
-#define SERMC1_PLB 0x00000010
-#define SERMC1_XLB 0x00000020
-
-/*
- * The following defines are for the flags in the serial port master control
- * register 2.
- */
-#define SERMC2_LROE 0x00000001
-#define SERMC2_MCOE 0x00000002
-#define SERMC2_MCDIV 0x00000004
-
-/*
- * The following defines are for the flags in the serial port 1 configuration
- * register.
- */
-#define SERC1_SO1EN 0x00000001
-#define SERC1_SO1F_MASK 0x0000000E
-#define SERC1_SO1F_CS423X 0x00000000
-#define SERC1_SO1F_AC97 0x00000002
-#define SERC1_SO1F_DAC 0x00000004
-#define SERC1_SO1F_SPDIF 0x00000006
-
-/*
- * The following defines are for the flags in the serial port 2 configuration
- * register.
- */
-#define SERC2_SI1EN 0x00000001
-#define SERC2_SI1F_MASK 0x0000000E
-#define SERC2_SI1F_CS423X 0x00000000
-#define SERC2_SI1F_AC97 0x00000002
-#define SERC2_SI1F_ADC 0x00000004
-#define SERC2_SI1F_SPDIF 0x00000006
-
-/*
- * The following defines are for the flags in the serial port 3 configuration
- * register.
- */
-#define SERC3_SO2EN 0x00000001
-#define SERC3_SO2F_MASK 0x00000006
-#define SERC3_SO2F_DAC 0x00000000
-#define SERC3_SO2F_SPDIF 0x00000002
-
-/*
- * The following defines are for the flags in the serial port 4 configuration
- * register.
- */
-#define SERC4_SO3EN 0x00000001
-#define SERC4_SO3F_MASK 0x00000006
-#define SERC4_SO3F_DAC 0x00000000
-#define SERC4_SO3F_SPDIF 0x00000002
-
-/*
- * The following defines are for the flags in the serial port 5 configuration
- * register.
- */
-#define SERC5_SI2EN 0x00000001
-#define SERC5_SI2F_MASK 0x00000006
-#define SERC5_SI2F_ADC 0x00000000
-#define SERC5_SI2F_SPDIF 0x00000002
-
-/*
- * The following defines are for the flags in the serial port backdoor sample
- * pointer register.
- */
-#define SERBSP_FSP_MASK 0x0000000F
-#define SERBSP_FSP_SHIFT 0
-
-/*
- * The following defines are for the flags in the serial port backdoor status
- * register.
- */
-#define SERBST_RRDY 0x00000001
-#define SERBST_WBSY 0x00000002
-
-/*
- * The following defines are for the flags in the serial port backdoor command
- * register.
- */
-#define SERBCM_RDC 0x00000001
-#define SERBCM_WRC 0x00000002
-
-/*
- * The following defines are for the flags in the serial port backdoor address
- * register.
- */
-#ifdef NO_CS4612
-#define SERBAD_FAD_MASK 0x000000FF
-#else
-#define SERBAD_FAD_MASK 0x000001FF
-#endif
-#define SERBAD_FAD_SHIFT 0
-
-/*
- * The following defines are for the flags in the serial port backdoor
- * configuration register.
- */
-#define SERBCF_HBP 0x00000001
-
-/*
- * The following defines are for the flags in the serial port backdoor write
- * port register.
- */
-#define SERBWP_FWD_MASK 0x000FFFFF
-#define SERBWP_FWD_SHIFT 0
-
-/*
- * The following defines are for the flags in the serial port backdoor read
- * port register.
- */
-#define SERBRP_FRD_MASK 0x000FFFFF
-#define SERBRP_FRD_SHIFT 0
-
-/*
- * The following defines are for the flags in the async FIFO address register.
- */
-#ifndef NO_CS4612
-#define ASER_FADDR_A1_MASK 0x000001FF
-#define ASER_FADDR_EN1 0x00008000
-#define ASER_FADDR_A2_MASK 0x01FF0000
-#define ASER_FADDR_EN2 0x80000000
-#define ASER_FADDR_A1_SHIFT 0
-#define ASER_FADDR_A2_SHIFT 16
-#endif
-
-/*
- * The following defines are for the flags in the AC97 control register.
- */
-#define ACCTL_RSTN 0x00000001
-#define ACCTL_ESYN 0x00000002
-#define ACCTL_VFRM 0x00000004
-#define ACCTL_DCV 0x00000008
-#define ACCTL_CRW 0x00000010
-#define ACCTL_ASYN 0x00000020
-#ifndef NO_CS4612
-#define ACCTL_TC 0x00000040
-#endif
-
-/*
- * The following defines are for the flags in the AC97 status register.
- */
-#define ACSTS_CRDY 0x00000001
-#define ACSTS_VSTS 0x00000002
-#ifndef NO_CS4612
-#define ACSTS_WKUP 0x00000004
-#endif
-
-/*
- * The following defines are for the flags in the AC97 output slot valid
- * register.
- */
-#define ACOSV_SLV3 0x00000001
-#define ACOSV_SLV4 0x00000002
-#define ACOSV_SLV5 0x00000004
-#define ACOSV_SLV6 0x00000008
-#define ACOSV_SLV7 0x00000010
-#define ACOSV_SLV8 0x00000020
-#define ACOSV_SLV9 0x00000040
-#define ACOSV_SLV10 0x00000080
-#define ACOSV_SLV11 0x00000100
-#define ACOSV_SLV12 0x00000200
-
-/*
- * The following defines are for the flags in the AC97 command address
- * register.
- */
-#define ACCAD_CI_MASK 0x0000007F
-#define ACCAD_CI_SHIFT 0
-
-/*
- * The following defines are for the flags in the AC97 command data register.
- */
-#define ACCDA_CD_MASK 0x0000FFFF
-#define ACCDA_CD_SHIFT 0
-
-/*
- * The following defines are for the flags in the AC97 input slot valid
- * register.
- */
-#define ACISV_ISV3 0x00000001
-#define ACISV_ISV4 0x00000002
-#define ACISV_ISV5 0x00000004
-#define ACISV_ISV6 0x00000008
-#define ACISV_ISV7 0x00000010
-#define ACISV_ISV8 0x00000020
-#define ACISV_ISV9 0x00000040
-#define ACISV_ISV10 0x00000080
-#define ACISV_ISV11 0x00000100
-#define ACISV_ISV12 0x00000200
-
-/*
- * The following defines are for the flags in the AC97 status address
- * register.
- */
-#define ACSAD_SI_MASK 0x0000007F
-#define ACSAD_SI_SHIFT 0
-
-/*
- * The following defines are for the flags in the AC97 status data register.
- */
-#define ACSDA_SD_MASK 0x0000FFFF
-#define ACSDA_SD_SHIFT 0
-
-/*
- * The following defines are for the flags in the joystick poll/trigger
- * register.
- */
-#define JSPT_CAX 0x00000001
-#define JSPT_CAY 0x00000002
-#define JSPT_CBX 0x00000004
-#define JSPT_CBY 0x00000008
-#define JSPT_BA1 0x00000010
-#define JSPT_BA2 0x00000020
-#define JSPT_BB1 0x00000040
-#define JSPT_BB2 0x00000080
-
-/*
- * The following defines are for the flags in the joystick control register.
- */
-#define JSCTL_SP_MASK 0x00000003
-#define JSCTL_SP_SLOW 0x00000000
-#define JSCTL_SP_MEDIUM_SLOW 0x00000001
-#define JSCTL_SP_MEDIUM_FAST 0x00000002
-#define JSCTL_SP_FAST 0x00000003
-#define JSCTL_ARE 0x00000004
-
-/*
- * The following defines are for the flags in the joystick coordinate pair 1
- * readback register.
- */
-#define JSC1_Y1V_MASK 0x0000FFFF
-#define JSC1_X1V_MASK 0xFFFF0000
-#define JSC1_Y1V_SHIFT 0
-#define JSC1_X1V_SHIFT 16
-
-/*
- * The following defines are for the flags in the joystick coordinate pair 2
- * readback register.
- */
-#define JSC2_Y2V_MASK 0x0000FFFF
-#define JSC2_X2V_MASK 0xFFFF0000
-#define JSC2_Y2V_SHIFT 0
-#define JSC2_X2V_SHIFT 16
-
-/*
- * The following defines are for the flags in the MIDI control register.
- */
-#define MIDCR_TXE 0x00000001 /* Enable transmitting. */
-#define MIDCR_RXE 0x00000002 /* Enable receiving. */
-#define MIDCR_RIE 0x00000004 /* Interrupt upon tx ready. */
-#define MIDCR_TIE 0x00000008 /* Interrupt upon rx ready. */
-#define MIDCR_MLB 0x00000010 /* Enable midi loopback. */
-#define MIDCR_MRST 0x00000020 /* Reset interface. */
-
-/*
- * The following defines are for the flags in the MIDI status register.
- */
-#define MIDSR_TBF 0x00000001 /* Tx FIFO is full. */
-#define MIDSR_RBE 0x00000002 /* Rx FIFO is empty. */
-
-/*
- * The following defines are for the flags in the MIDI write port register.
- */
-#define MIDWP_MWD_MASK 0x000000FF
-#define MIDWP_MWD_SHIFT 0
-
-/*
- * The following defines are for the flags in the MIDI read port register.
- */
-#define MIDRP_MRD_MASK 0x000000FF
-#define MIDRP_MRD_SHIFT 0
-
-/*
- * The following defines are for the flags in the joystick GPIO register.
- */
-#define JSIO_DAX 0x00000001
-#define JSIO_DAY 0x00000002
-#define JSIO_DBX 0x00000004
-#define JSIO_DBY 0x00000008
-#define JSIO_AXOE 0x00000010
-#define JSIO_AYOE 0x00000020
-#define JSIO_BXOE 0x00000040
-#define JSIO_BYOE 0x00000080
-
-/*
- * The following defines are for the flags in the master async/sync serial
- * port enable register.
- */
-#ifndef NO_CS4612
-#define ASER_MASTER_ME 0x00000001
-#endif
-
-/*
- * The following defines are for the flags in the configuration interface
- * register.
- */
-#define CFGI_CLK 0x00000001
-#define CFGI_DOUT 0x00000002
-#define CFGI_DIN_EEN 0x00000004
-#define CFGI_EELD 0x00000008
-
-/*
- * The following defines are for the flags in the subsystem ID and vendor ID
- * register.
- */
-#define SSVID_VID_MASK 0x0000FFFF
-#define SSVID_SID_MASK 0xFFFF0000
-#define SSVID_VID_SHIFT 0
-#define SSVID_SID_SHIFT 16
-
-/*
- * The following defines are for the flags in the GPIO pin interface register.
- */
-#define GPIOR_VOLDN 0x00000001
-#define GPIOR_VOLUP 0x00000002
-#define GPIOR_SI2D 0x00000004
-#define GPIOR_SI2OE 0x00000008
-
-/*
- * The following defines are for the flags in the extended GPIO pin direction
- * register.
- */
-#ifndef NO_CS4612
-#define EGPIODR_GPOE0 0x00000001
-#define EGPIODR_GPOE1 0x00000002
-#define EGPIODR_GPOE2 0x00000004
-#define EGPIODR_GPOE3 0x00000008
-#define EGPIODR_GPOE4 0x00000010
-#define EGPIODR_GPOE5 0x00000020
-#define EGPIODR_GPOE6 0x00000040
-#define EGPIODR_GPOE7 0x00000080
-#define EGPIODR_GPOE8 0x00000100
-#endif
-
-/*
- * The following defines are for the flags in the extended GPIO pin polarity/
- * type register.
- */
-#ifndef NO_CS4612
-#define EGPIOPTR_GPPT0 0x00000001
-#define EGPIOPTR_GPPT1 0x00000002
-#define EGPIOPTR_GPPT2 0x00000004
-#define EGPIOPTR_GPPT3 0x00000008
-#define EGPIOPTR_GPPT4 0x00000010
-#define EGPIOPTR_GPPT5 0x00000020
-#define EGPIOPTR_GPPT6 0x00000040
-#define EGPIOPTR_GPPT7 0x00000080
-#define EGPIOPTR_GPPT8 0x00000100
-#endif
-
-/*
- * The following defines are for the flags in the extended GPIO pin sticky
- * register.
- */
-#ifndef NO_CS4612
-#define EGPIOTR_GPS0 0x00000001
-#define EGPIOTR_GPS1 0x00000002
-#define EGPIOTR_GPS2 0x00000004
-#define EGPIOTR_GPS3 0x00000008
-#define EGPIOTR_GPS4 0x00000010
-#define EGPIOTR_GPS5 0x00000020
-#define EGPIOTR_GPS6 0x00000040
-#define EGPIOTR_GPS7 0x00000080
-#define EGPIOTR_GPS8 0x00000100
-#endif
-
-/*
- * The following defines are for the flags in the extended GPIO ping wakeup
- * register.
- */
-#ifndef NO_CS4612
-#define EGPIOWR_GPW0 0x00000001
-#define EGPIOWR_GPW1 0x00000002
-#define EGPIOWR_GPW2 0x00000004
-#define EGPIOWR_GPW3 0x00000008
-#define EGPIOWR_GPW4 0x00000010
-#define EGPIOWR_GPW5 0x00000020
-#define EGPIOWR_GPW6 0x00000040
-#define EGPIOWR_GPW7 0x00000080
-#define EGPIOWR_GPW8 0x00000100
-#endif
-
-/*
- * The following defines are for the flags in the extended GPIO pin status
- * register.
- */
-#ifndef NO_CS4612
-#define EGPIOSR_GPS0 0x00000001
-#define EGPIOSR_GPS1 0x00000002
-#define EGPIOSR_GPS2 0x00000004
-#define EGPIOSR_GPS3 0x00000008
-#define EGPIOSR_GPS4 0x00000010
-#define EGPIOSR_GPS5 0x00000020
-#define EGPIOSR_GPS6 0x00000040
-#define EGPIOSR_GPS7 0x00000080
-#define EGPIOSR_GPS8 0x00000100
-#endif
-
-/*
- * The following defines are for the flags in the serial port 6 configuration
- * register.
- */
-#ifndef NO_CS4612
-#define SERC6_ASDO2EN 0x00000001
-#endif
-
-/*
- * The following defines are for the flags in the serial port 7 configuration
- * register.
- */
-#ifndef NO_CS4612
-#define SERC7_ASDI2EN 0x00000001
-#define SERC7_POSILB 0x00000002
-#define SERC7_SIPOLB 0x00000004
-#define SERC7_SOSILB 0x00000008
-#define SERC7_SISOLB 0x00000010
-#endif
-
-/*
- * The following defines are for the flags in the serial port AC link
- * configuration register.
- */
-#ifndef NO_CS4612
-#define SERACC_CODEC_TYPE_MASK 0x00000001
-#define SERACC_CODEC_TYPE_1_03 0x00000000
-#define SERACC_CODEC_TYPE_2_0 0x00000001
-#define SERACC_TWO_CODECS 0x00000002
-#define SERACC_MDM 0x00000004
-#define SERACC_HSP 0x00000008
-#endif
-
-/*
- * The following defines are for the flags in the AC97 control register 2.
- */
-#ifndef NO_CS4612
-#define ACCTL2_RSTN 0x00000001
-#define ACCTL2_ESYN 0x00000002
-#define ACCTL2_VFRM 0x00000004
-#define ACCTL2_DCV 0x00000008
-#define ACCTL2_CRW 0x00000010
-#define ACCTL2_ASYN 0x00000020
-#endif
-
-/*
- * The following defines are for the flags in the AC97 status register 2.
- */
-#ifndef NO_CS4612
-#define ACSTS2_CRDY 0x00000001
-#define ACSTS2_VSTS 0x00000002
-#endif
-
-/*
- * The following defines are for the flags in the AC97 output slot valid
- * register 2.
- */
-#ifndef NO_CS4612
-#define ACOSV2_SLV3 0x00000001
-#define ACOSV2_SLV4 0x00000002
-#define ACOSV2_SLV5 0x00000004
-#define ACOSV2_SLV6 0x00000008
-#define ACOSV2_SLV7 0x00000010
-#define ACOSV2_SLV8 0x00000020
-#define ACOSV2_SLV9 0x00000040
-#define ACOSV2_SLV10 0x00000080
-#define ACOSV2_SLV11 0x00000100
-#define ACOSV2_SLV12 0x00000200
-#endif
-
-/*
- * The following defines are for the flags in the AC97 command address
- * register 2.
- */
-#ifndef NO_CS4612
-#define ACCAD2_CI_MASK 0x0000007F
-#define ACCAD2_CI_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the AC97 command data register
- * 2.
- */
-#ifndef NO_CS4612
-#define ACCDA2_CD_MASK 0x0000FFFF
-#define ACCDA2_CD_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the AC97 input slot valid
- * register 2.
- */
-#ifndef NO_CS4612
-#define ACISV2_ISV3 0x00000001
-#define ACISV2_ISV4 0x00000002
-#define ACISV2_ISV5 0x00000004
-#define ACISV2_ISV6 0x00000008
-#define ACISV2_ISV7 0x00000010
-#define ACISV2_ISV8 0x00000020
-#define ACISV2_ISV9 0x00000040
-#define ACISV2_ISV10 0x00000080
-#define ACISV2_ISV11 0x00000100
-#define ACISV2_ISV12 0x00000200
-#endif
-
-/*
- * The following defines are for the flags in the AC97 status address
- * register 2.
- */
-#ifndef NO_CS4612
-#define ACSAD2_SI_MASK 0x0000007F
-#define ACSAD2_SI_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the AC97 status data register 2.
- */
-#ifndef NO_CS4612
-#define ACSDA2_SD_MASK 0x0000FFFF
-#define ACSDA2_SD_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the I/O trap address and control
- * registers (all 12).
- */
-#ifndef NO_CS4612
-#define IOTAC_SA_MASK 0x0000FFFF
-#define IOTAC_MSK_MASK 0x000F0000
-#define IOTAC_IODC_MASK 0x06000000
-#define IOTAC_IODC_16_BIT 0x00000000
-#define IOTAC_IODC_10_BIT 0x02000000
-#define IOTAC_IODC_12_BIT 0x04000000
-#define IOTAC_WSPI 0x08000000
-#define IOTAC_RSPI 0x10000000
-#define IOTAC_WSE 0x20000000
-#define IOTAC_WE 0x40000000
-#define IOTAC_RE 0x80000000
-#define IOTAC_SA_SHIFT 0
-#define IOTAC_MSK_SHIFT 16
-#endif
-
-/*
- * The following defines are for the flags in the I/O trap fast read registers
- * (all 8).
- */
-#ifndef NO_CS4612
-#define IOTFR_D_MASK 0x0000FFFF
-#define IOTFR_A_MASK 0x000F0000
-#define IOTFR_R_MASK 0x0F000000
-#define IOTFR_ALL 0x40000000
-#define IOTFR_VL 0x80000000
-#define IOTFR_D_SHIFT 0
-#define IOTFR_A_SHIFT 16
-#define IOTFR_R_SHIFT 24
-#endif
-
-/*
- * The following defines are for the flags in the I/O trap FIFO register.
- */
-#ifndef NO_CS4612
-#define IOTFIFO_BA_MASK 0x00003FFF
-#define IOTFIFO_S_MASK 0x00FF0000
-#define IOTFIFO_OF 0x40000000
-#define IOTFIFO_SPIOF 0x80000000
-#define IOTFIFO_BA_SHIFT 0
-#define IOTFIFO_S_SHIFT 16
-#endif
-
-/*
- * The following defines are for the flags in the I/O trap retry read data
- * register.
- */
-#ifndef NO_CS4612
-#define IOTRRD_D_MASK 0x0000FFFF
-#define IOTRRD_RDV 0x80000000
-#define IOTRRD_D_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the I/O trap FIFO pointer
- * register.
- */
-#ifndef NO_CS4612
-#define IOTFP_CA_MASK 0x00003FFF
-#define IOTFP_PA_MASK 0x3FFF0000
-#define IOTFP_CA_SHIFT 0
-#define IOTFP_PA_SHIFT 16
-#endif
-
-/*
- * The following defines are for the flags in the I/O trap control register.
- */
-#ifndef NO_CS4612
-#define IOTCR_ITD 0x00000001
-#define IOTCR_HRV 0x00000002
-#define IOTCR_SRV 0x00000004
-#define IOTCR_DTI 0x00000008
-#define IOTCR_DFI 0x00000010
-#define IOTCR_DDP 0x00000020
-#define IOTCR_JTE 0x00000040
-#define IOTCR_PPE 0x00000080
-#endif
-
-/*
- * The following defines are for the flags in the direct PCI data register.
- */
-#ifndef NO_CS4612
-#define DPCID_D_MASK 0xFFFFFFFF
-#define DPCID_D_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the direct PCI address register.
- */
-#ifndef NO_CS4612
-#define DPCIA_A_MASK 0xFFFFFFFF
-#define DPCIA_A_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the direct PCI command register.
- */
-#ifndef NO_CS4612
-#define DPCIC_C_MASK 0x0000000F
-#define DPCIC_C_IOREAD 0x00000002
-#define DPCIC_C_IOWRITE 0x00000003
-#define DPCIC_BE_MASK 0x000000F0
-#endif
-
-/*
- * The following defines are for the flags in the PC/PCI request register.
- */
-#ifndef NO_CS4612
-#define PCPCIR_RDC_MASK 0x00000007
-#define PCPCIR_C_MASK 0x00007000
-#define PCPCIR_REQ 0x00008000
-#define PCPCIR_RDC_SHIFT 0
-#define PCPCIR_C_SHIFT 12
-#endif
-
-/*
- * The following defines are for the flags in the PC/PCI grant register.
- */
-#ifndef NO_CS4612
-#define PCPCIG_GDC_MASK 0x00000007
-#define PCPCIG_VL 0x00008000
-#define PCPCIG_GDC_SHIFT 0
-#endif
-
-/*
- * The following defines are for the flags in the PC/PCI master enable
- * register.
- */
-#ifndef NO_CS4612
-#define PCPCIEN_EN 0x00000001
-#endif
-
-/*
- * The following defines are for the flags in the extended PCI power
- * management control register.
- */
-#ifndef NO_CS4612
-#define EPCIPMC_GWU 0x00000001
-#define EPCIPMC_FSPC 0x00000002
-#endif
-
-/*
- * The following defines are for the flags in the SP control register.
- */
-#define SPCR_RUN 0x00000001
-#define SPCR_STPFR 0x00000002
-#define SPCR_RUNFR 0x00000004
-#define SPCR_TICK 0x00000008
-#define SPCR_DRQEN 0x00000020
-#define SPCR_RSTSP 0x00000040
-#define SPCR_OREN 0x00000080
-#ifndef NO_CS4612
-#define SPCR_PCIINT 0x00000100
-#define SPCR_OINTD 0x00000200
-#define SPCR_CRE 0x00008000
-#endif
-
-/*
- * The following defines are for the flags in the debug index register.
- */
-#define DREG_REGID_MASK 0x0000007F
-#define DREG_DEBUG 0x00000080
-#define DREG_RGBK_MASK 0x00000700
-#define DREG_TRAP 0x00000800
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_TRAPX 0x00001000
-#endif
-#endif
-#define DREG_REGID_SHIFT 0
-#define DREG_RGBK_SHIFT 8
-#define DREG_RGBK_REGID_MASK 0x0000077F
-#define DREG_REGID_R0 0x00000010
-#define DREG_REGID_R1 0x00000011
-#define DREG_REGID_R2 0x00000012
-#define DREG_REGID_R3 0x00000013
-#define DREG_REGID_R4 0x00000014
-#define DREG_REGID_R5 0x00000015
-#define DREG_REGID_R6 0x00000016
-#define DREG_REGID_R7 0x00000017
-#define DREG_REGID_R8 0x00000018
-#define DREG_REGID_R9 0x00000019
-#define DREG_REGID_RA 0x0000001A
-#define DREG_REGID_RB 0x0000001B
-#define DREG_REGID_RC 0x0000001C
-#define DREG_REGID_RD 0x0000001D
-#define DREG_REGID_RE 0x0000001E
-#define DREG_REGID_RF 0x0000001F
-#define DREG_REGID_RA_BUS_LOW 0x00000020
-#define DREG_REGID_RA_BUS_HIGH 0x00000038
-#define DREG_REGID_YBUS_LOW 0x00000050
-#define DREG_REGID_YBUS_HIGH 0x00000058
-#define DREG_REGID_TRAP_0 0x00000100
-#define DREG_REGID_TRAP_1 0x00000101
-#define DREG_REGID_TRAP_2 0x00000102
-#define DREG_REGID_TRAP_3 0x00000103
-#define DREG_REGID_TRAP_4 0x00000104
-#define DREG_REGID_TRAP_5 0x00000105
-#define DREG_REGID_TRAP_6 0x00000106
-#define DREG_REGID_TRAP_7 0x00000107
-#define DREG_REGID_INDIRECT_ADDRESS 0x0000010E
-#define DREG_REGID_TOP_OF_STACK 0x0000010F
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_8 0x00000110
-#define DREG_REGID_TRAP_9 0x00000111
-#define DREG_REGID_TRAP_10 0x00000112
-#define DREG_REGID_TRAP_11 0x00000113
-#define DREG_REGID_TRAP_12 0x00000114
-#define DREG_REGID_TRAP_13 0x00000115
-#define DREG_REGID_TRAP_14 0x00000116
-#define DREG_REGID_TRAP_15 0x00000117
-#define DREG_REGID_TRAP_16 0x00000118
-#define DREG_REGID_TRAP_17 0x00000119
-#define DREG_REGID_TRAP_18 0x0000011A
-#define DREG_REGID_TRAP_19 0x0000011B
-#define DREG_REGID_TRAP_20 0x0000011C
-#define DREG_REGID_TRAP_21 0x0000011D
-#define DREG_REGID_TRAP_22 0x0000011E
-#define DREG_REGID_TRAP_23 0x0000011F
-#endif
-#endif
-#define DREG_REGID_RSA0_LOW 0x00000200
-#define DREG_REGID_RSA0_HIGH 0x00000201
-#define DREG_REGID_RSA1_LOW 0x00000202
-#define DREG_REGID_RSA1_HIGH 0x00000203
-#define DREG_REGID_RSA2 0x00000204
-#define DREG_REGID_RSA3 0x00000205
-#define DREG_REGID_RSI0_LOW 0x00000206
-#define DREG_REGID_RSI0_HIGH 0x00000207
-#define DREG_REGID_RSI1 0x00000208
-#define DREG_REGID_RSI2 0x00000209
-#define DREG_REGID_SAGUSTATUS 0x0000020A
-#define DREG_REGID_RSCONFIG01_LOW 0x0000020B
-#define DREG_REGID_RSCONFIG01_HIGH 0x0000020C
-#define DREG_REGID_RSCONFIG23_LOW 0x0000020D
-#define DREG_REGID_RSCONFIG23_HIGH 0x0000020E
-#define DREG_REGID_RSDMA01E 0x0000020F
-#define DREG_REGID_RSDMA23E 0x00000210
-#define DREG_REGID_RSD0_LOW 0x00000211
-#define DREG_REGID_RSD0_HIGH 0x00000212
-#define DREG_REGID_RSD1_LOW 0x00000213
-#define DREG_REGID_RSD1_HIGH 0x00000214
-#define DREG_REGID_RSD2_LOW 0x00000215
-#define DREG_REGID_RSD2_HIGH 0x00000216
-#define DREG_REGID_RSD3_LOW 0x00000217
-#define DREG_REGID_RSD3_HIGH 0x00000218
-#define DREG_REGID_SRAR_HIGH 0x0000021A
-#define DREG_REGID_SRAR_LOW 0x0000021B
-#define DREG_REGID_DMA_STATE 0x0000021C
-#define DREG_REGID_CURRENT_DMA_STREAM 0x0000021D
-#define DREG_REGID_NEXT_DMA_STREAM 0x0000021E
-#define DREG_REGID_CPU_STATUS 0x00000300
-#define DREG_REGID_MAC_MODE 0x00000301
-#define DREG_REGID_STACK_AND_REPEAT 0x00000302
-#define DREG_REGID_INDEX0 0x00000304
-#define DREG_REGID_INDEX1 0x00000305
-#define DREG_REGID_DMA_STATE_0_3 0x00000400
-#define DREG_REGID_DMA_STATE_4_7 0x00000404
-#define DREG_REGID_DMA_STATE_8_11 0x00000408
-#define DREG_REGID_DMA_STATE_12_15 0x0000040C
-#define DREG_REGID_DMA_STATE_16_19 0x00000410
-#define DREG_REGID_DMA_STATE_20_23 0x00000414
-#define DREG_REGID_DMA_STATE_24_27 0x00000418
-#define DREG_REGID_DMA_STATE_28_31 0x0000041C
-#define DREG_REGID_DMA_STATE_32_35 0x00000420
-#define DREG_REGID_DMA_STATE_36_39 0x00000424
-#define DREG_REGID_DMA_STATE_40_43 0x00000428
-#define DREG_REGID_DMA_STATE_44_47 0x0000042C
-#define DREG_REGID_DMA_STATE_48_51 0x00000430
-#define DREG_REGID_DMA_STATE_52_55 0x00000434
-#define DREG_REGID_DMA_STATE_56_59 0x00000438
-#define DREG_REGID_DMA_STATE_60_63 0x0000043C
-#define DREG_REGID_DMA_STATE_64_67 0x00000440
-#define DREG_REGID_DMA_STATE_68_71 0x00000444
-#define DREG_REGID_DMA_STATE_72_75 0x00000448
-#define DREG_REGID_DMA_STATE_76_79 0x0000044C
-#define DREG_REGID_DMA_STATE_80_83 0x00000450
-#define DREG_REGID_DMA_STATE_84_87 0x00000454
-#define DREG_REGID_DMA_STATE_88_91 0x00000458
-#define DREG_REGID_DMA_STATE_92_95 0x0000045C
-#define DREG_REGID_TRAP_SELECT 0x00000500
-#define DREG_REGID_TRAP_WRITE_0 0x00000500
-#define DREG_REGID_TRAP_WRITE_1 0x00000501
-#define DREG_REGID_TRAP_WRITE_2 0x00000502
-#define DREG_REGID_TRAP_WRITE_3 0x00000503
-#define DREG_REGID_TRAP_WRITE_4 0x00000504
-#define DREG_REGID_TRAP_WRITE_5 0x00000505
-#define DREG_REGID_TRAP_WRITE_6 0x00000506
-#define DREG_REGID_TRAP_WRITE_7 0x00000507
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_WRITE_8 0x00000510
-#define DREG_REGID_TRAP_WRITE_9 0x00000511
-#define DREG_REGID_TRAP_WRITE_10 0x00000512
-#define DREG_REGID_TRAP_WRITE_11 0x00000513
-#define DREG_REGID_TRAP_WRITE_12 0x00000514
-#define DREG_REGID_TRAP_WRITE_13 0x00000515
-#define DREG_REGID_TRAP_WRITE_14 0x00000516
-#define DREG_REGID_TRAP_WRITE_15 0x00000517
-#define DREG_REGID_TRAP_WRITE_16 0x00000518
-#define DREG_REGID_TRAP_WRITE_17 0x00000519
-#define DREG_REGID_TRAP_WRITE_18 0x0000051A
-#define DREG_REGID_TRAP_WRITE_19 0x0000051B
-#define DREG_REGID_TRAP_WRITE_20 0x0000051C
-#define DREG_REGID_TRAP_WRITE_21 0x0000051D
-#define DREG_REGID_TRAP_WRITE_22 0x0000051E
-#define DREG_REGID_TRAP_WRITE_23 0x0000051F
-#endif
-#endif
-#define DREG_REGID_MAC0_ACC0_LOW 0x00000600
-#define DREG_REGID_MAC0_ACC1_LOW 0x00000601
-#define DREG_REGID_MAC0_ACC2_LOW 0x00000602
-#define DREG_REGID_MAC0_ACC3_LOW 0x00000603
-#define DREG_REGID_MAC1_ACC0_LOW 0x00000604
-#define DREG_REGID_MAC1_ACC1_LOW 0x00000605
-#define DREG_REGID_MAC1_ACC2_LOW 0x00000606
-#define DREG_REGID_MAC1_ACC3_LOW 0x00000607
-#define DREG_REGID_MAC0_ACC0_MID 0x00000608
-#define DREG_REGID_MAC0_ACC1_MID 0x00000609
-#define DREG_REGID_MAC0_ACC2_MID 0x0000060A
-#define DREG_REGID_MAC0_ACC3_MID 0x0000060B
-#define DREG_REGID_MAC1_ACC0_MID 0x0000060C
-#define DREG_REGID_MAC1_ACC1_MID 0x0000060D
-#define DREG_REGID_MAC1_ACC2_MID 0x0000060E
-#define DREG_REGID_MAC1_ACC3_MID 0x0000060F
-#define DREG_REGID_MAC0_ACC0_HIGH 0x00000610
-#define DREG_REGID_MAC0_ACC1_HIGH 0x00000611
-#define DREG_REGID_MAC0_ACC2_HIGH 0x00000612
-#define DREG_REGID_MAC0_ACC3_HIGH 0x00000613
-#define DREG_REGID_MAC1_ACC0_HIGH 0x00000614
-#define DREG_REGID_MAC1_ACC1_HIGH 0x00000615
-#define DREG_REGID_MAC1_ACC2_HIGH 0x00000616
-#define DREG_REGID_MAC1_ACC3_HIGH 0x00000617
-#define DREG_REGID_RSHOUT_LOW 0x00000620
-#define DREG_REGID_RSHOUT_MID 0x00000628
-#define DREG_REGID_RSHOUT_HIGH 0x00000630
-
-/*
- * The following defines are for the flags in the DMA stream requestor write
- */
-#define DSRWP_DSR_MASK 0x0000000F
-#define DSRWP_DSR_BG_RQ 0x00000001
-#define DSRWP_DSR_PRIORITY_MASK 0x00000006
-#define DSRWP_DSR_PRIORITY_0 0x00000000
-#define DSRWP_DSR_PRIORITY_1 0x00000002
-#define DSRWP_DSR_PRIORITY_2 0x00000004
-#define DSRWP_DSR_PRIORITY_3 0x00000006
-#define DSRWP_DSR_RQ_PENDING 0x00000008
-
-/*
- * The following defines are for the flags in the trap write port register.
- */
-#define TWPR_TW_MASK 0x0000FFFF
-#define TWPR_TW_SHIFT 0
-
-/*
- * The following defines are for the flags in the stack pointer write
- * register.
- */
-#define SPWR_STKP_MASK 0x0000000F
-#define SPWR_STKP_SHIFT 0
-
-/*
- * The following defines are for the flags in the SP interrupt register.
- */
-#define SPIR_FRI 0x00000001
-#define SPIR_DOI 0x00000002
-#define SPIR_GPI2 0x00000004
-#define SPIR_GPI3 0x00000008
-#define SPIR_IP0 0x00000010
-#define SPIR_IP1 0x00000020
-#define SPIR_IP2 0x00000040
-#define SPIR_IP3 0x00000080
-
-/*
- * The following defines are for the flags in the functional group 1 register.
- */
-#define FGR1_F1S_MASK 0x0000FFFF
-#define FGR1_F1S_SHIFT 0
-
-/*
- * The following defines are for the flags in the SP clock status register.
- */
-#define SPCS_FRI 0x00000001
-#define SPCS_DOI 0x00000002
-#define SPCS_GPI2 0x00000004
-#define SPCS_GPI3 0x00000008
-#define SPCS_IP0 0x00000010
-#define SPCS_IP1 0x00000020
-#define SPCS_IP2 0x00000040
-#define SPCS_IP3 0x00000080
-#define SPCS_SPRUN 0x00000100
-#define SPCS_SLEEP 0x00000200
-#define SPCS_FG 0x00000400
-#define SPCS_ORUN 0x00000800
-#define SPCS_IRQ 0x00001000
-#define SPCS_FGN_MASK 0x0000E000
-#define SPCS_FGN_SHIFT 13
-
-/*
- * The following defines are for the flags in the SP DMA requestor status
- * register.
- */
-#define SDSR_DCS_MASK 0x000000FF
-#define SDSR_DCS_SHIFT 0
-#define SDSR_DCS_NONE 0x00000007
-
-/*
- * The following defines are for the flags in the frame timer register.
- */
-#define FRMT_FTV_MASK 0x0000FFFF
-#define FRMT_FTV_SHIFT 0
-
-/*
- * The following defines are for the flags in the frame timer current count
- * register.
- */
-#define FRCC_FCC_MASK 0x0000FFFF
-#define FRCC_FCC_SHIFT 0
-
-/*
- * The following defines are for the flags in the frame timer save count
- * register.
- */
-#define FRSC_FCS_MASK 0x0000FFFF
-#define FRSC_FCS_SHIFT 0
-
-/*
- * The following define the various flags stored in the scatter/gather
- * descriptors.
- */
-#define DMA_SG_NEXT_ENTRY_MASK 0x00000FF8
-#define DMA_SG_SAMPLE_END_MASK 0x0FFF0000
-#define DMA_SG_SAMPLE_END_FLAG 0x10000000
-#define DMA_SG_LOOP_END_FLAG 0x20000000
-#define DMA_SG_SIGNAL_END_FLAG 0x40000000
-#define DMA_SG_SIGNAL_PAGE_FLAG 0x80000000
-#define DMA_SG_NEXT_ENTRY_SHIFT 3
-#define DMA_SG_SAMPLE_END_SHIFT 16
-
-/*
- * The following define the offsets of the fields within the on-chip generic
- * DMA requestor.
- */
-#define DMA_RQ_CONTROL1 0x00000000
-#define DMA_RQ_CONTROL2 0x00000004
-#define DMA_RQ_SOURCE_ADDR 0x00000008
-#define DMA_RQ_DESTINATION_ADDR 0x0000000C
-#define DMA_RQ_NEXT_PAGE_ADDR 0x00000010
-#define DMA_RQ_NEXT_PAGE_SGDESC 0x00000014
-#define DMA_RQ_LOOP_START_ADDR 0x00000018
-#define DMA_RQ_POST_LOOP_ADDR 0x0000001C
-#define DMA_RQ_PAGE_MAP_ADDR 0x00000020
-
-/*
- * The following defines are for the flags in the first control word of the
- * on-chip generic DMA requestor.
- */
-#define DMA_RQ_C1_COUNT_MASK 0x000003FF
-#define DMA_RQ_C1_DESTINATION_SCATTER 0x00001000
-#define DMA_RQ_C1_SOURCE_GATHER 0x00002000
-#define DMA_RQ_C1_DONE_FLAG 0x00004000
-#define DMA_RQ_C1_OPTIMIZE_STATE 0x00008000
-#define DMA_RQ_C1_SAMPLE_END_STATE_MASK 0x00030000
-#define DMA_RQ_C1_FULL_PAGE 0x00000000
-#define DMA_RQ_C1_BEFORE_SAMPLE_END 0x00010000
-#define DMA_RQ_C1_PAGE_MAP_ERROR 0x00020000
-#define DMA_RQ_C1_AT_SAMPLE_END 0x00030000
-#define DMA_RQ_C1_LOOP_END_STATE_MASK 0x000C0000
-#define DMA_RQ_C1_NOT_LOOP_END 0x00000000
-#define DMA_RQ_C1_BEFORE_LOOP_END 0x00040000
-#define DMA_RQ_C1_2PAGE_LOOP_BEGIN 0x00080000
-#define DMA_RQ_C1_LOOP_BEGIN 0x000C0000
-#define DMA_RQ_C1_PAGE_MAP_MASK 0x00300000
-#define DMA_RQ_C1_PM_NONE_PENDING 0x00000000
-#define DMA_RQ_C1_PM_NEXT_PENDING 0x00100000
-#define DMA_RQ_C1_PM_RESERVED 0x00200000
-#define DMA_RQ_C1_PM_LOOP_NEXT_PENDING 0x00300000
-#define DMA_RQ_C1_WRITEBACK_DEST_FLAG 0x00400000
-#define DMA_RQ_C1_WRITEBACK_SRC_FLAG 0x00800000
-#define DMA_RQ_C1_DEST_SIZE_MASK 0x07000000
-#define DMA_RQ_C1_DEST_LINEAR 0x00000000
-#define DMA_RQ_C1_DEST_MOD16 0x01000000
-#define DMA_RQ_C1_DEST_MOD32 0x02000000
-#define DMA_RQ_C1_DEST_MOD64 0x03000000
-#define DMA_RQ_C1_DEST_MOD128 0x04000000
-#define DMA_RQ_C1_DEST_MOD256 0x05000000
-#define DMA_RQ_C1_DEST_MOD512 0x06000000
-#define DMA_RQ_C1_DEST_MOD1024 0x07000000
-#define DMA_RQ_C1_DEST_ON_HOST 0x08000000
-#define DMA_RQ_C1_SOURCE_SIZE_MASK 0x70000000
-#define DMA_RQ_C1_SOURCE_LINEAR 0x00000000
-#define DMA_RQ_C1_SOURCE_MOD16 0x10000000
-#define DMA_RQ_C1_SOURCE_MOD32 0x20000000
-#define DMA_RQ_C1_SOURCE_MOD64 0x30000000
-#define DMA_RQ_C1_SOURCE_MOD128 0x40000000
-#define DMA_RQ_C1_SOURCE_MOD256 0x50000000
-#define DMA_RQ_C1_SOURCE_MOD512 0x60000000
-#define DMA_RQ_C1_SOURCE_MOD1024 0x70000000
-#define DMA_RQ_C1_SOURCE_ON_HOST 0x80000000
-#define DMA_RQ_C1_COUNT_SHIFT 0
-
-/*
- * The following defines are for the flags in the second control word of the
- * on-chip generic DMA requestor.
- */
-#define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK 0x0000003F
-#define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK 0x00000300
-#define DMA_RQ_C2_NO_VIRTUAL_SIGNAL 0x00000000
-#define DMA_RQ_C2_SIGNAL_EVERY_DMA 0x00000100
-#define DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG 0x00000200
-#define DMA_RQ_C2_SIGNAL_DEST_PINGPONG 0x00000300
-#define DMA_RQ_C2_AUDIO_CONVERT_MASK 0x0000F000
-#define DMA_RQ_C2_AC_NONE 0x00000000
-#define DMA_RQ_C2_AC_8_TO_16_BIT 0x00001000
-#define DMA_RQ_C2_AC_MONO_TO_STEREO 0x00002000
-#define DMA_RQ_C2_AC_ENDIAN_CONVERT 0x00004000
-#define DMA_RQ_C2_AC_SIGNED_CONVERT 0x00008000
-#define DMA_RQ_C2_LOOP_END_MASK 0x0FFF0000
-#define DMA_RQ_C2_LOOP_MASK 0x30000000
-#define DMA_RQ_C2_NO_LOOP 0x00000000
-#define DMA_RQ_C2_ONE_PAGE_LOOP 0x10000000
-#define DMA_RQ_C2_TWO_PAGE_LOOP 0x20000000
-#define DMA_RQ_C2_MULTI_PAGE_LOOP 0x30000000
-#define DMA_RQ_C2_SIGNAL_LOOP_BACK 0x40000000
-#define DMA_RQ_C2_SIGNAL_POST_BEGIN_PAGE 0x80000000
-#define DMA_RQ_C2_VIRTUAL_CHANNEL_SHIFT 0
-#define DMA_RQ_C2_LOOP_END_SHIFT 16
-
-/*
- * The following defines are for the flags in the source and destination words
- * of the on-chip generic DMA requestor.
- */
-#define DMA_RQ_SD_ADDRESS_MASK 0x0000FFFF
-#define DMA_RQ_SD_MEMORY_ID_MASK 0x000F0000
-#define DMA_RQ_SD_SP_PARAM_ADDR 0x00000000
-#define DMA_RQ_SD_SP_SAMPLE_ADDR 0x00010000
-#define DMA_RQ_SD_SP_PROGRAM_ADDR 0x00020000
-#define DMA_RQ_SD_SP_DEBUG_ADDR 0x00030000
-#define DMA_RQ_SD_OMNIMEM_ADDR 0x000E0000
-#define DMA_RQ_SD_END_FLAG 0x40000000
-#define DMA_RQ_SD_ERROR_FLAG 0x80000000
-#define DMA_RQ_SD_ADDRESS_SHIFT 0
-
-/*
- * The following defines are for the flags in the page map address word of the
- * on-chip generic DMA requestor.
- */
-#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_MASK 0x00000FF8
-#define DMA_RQ_PMA_PAGE_TABLE_MASK 0xFFFFF000
-#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_SHIFT 3
-#define DMA_RQ_PMA_PAGE_TABLE_SHIFT 12
-
-#define BA1_VARIDEC_BUF_1 0x000
-
-#define BA1_PDTC 0x0c0 /* BA1_PLAY_DMA_TRANSACTION_COUNT_REG */
-#define BA1_PFIE 0x0c4 /* BA1_PLAY_FORMAT_&_INTERRUPT_ENABLE_REG */
-#define BA1_PBA 0x0c8 /* BA1_PLAY_BUFFER_ADDRESS */
-#define BA1_PVOL 0x0f8 /* BA1_PLAY_VOLUME_REG */
-#define BA1_PSRC 0x288 /* BA1_PLAY_SAMPLE_RATE_CORRECTION_REG */
-#define BA1_PCTL 0x2a4 /* BA1_PLAY_CONTROL_REG */
-#define BA1_PPI 0x2b4 /* BA1_PLAY_PHASE_INCREMENT_REG */
-
-#define BA1_CCTL 0x064 /* BA1_CAPTURE_CONTROL_REG */
-#define BA1_CIE 0x104 /* BA1_CAPTURE_INTERRUPT_ENABLE_REG */
-#define BA1_CBA 0x10c /* BA1_CAPTURE_BUFFER_ADDRESS */
-#define BA1_CSRC 0x2c8 /* BA1_CAPTURE_SAMPLE_RATE_CORRECTION_REG */
-#define BA1_CCI 0x2d8 /* BA1_CAPTURE_COEFFICIENT_INCREMENT_REG */
-#define BA1_CD 0x2e0 /* BA1_CAPTURE_DELAY_REG */
-#define BA1_CPI 0x2f4 /* BA1_CAPTURE_PHASE_INCREMENT_REG */
-#define BA1_CVOL 0x2f8 /* BA1_CAPTURE_VOLUME_REG */
-
-#define BA1_CFG1 0x134 /* BA1_CAPTURE_FRAME_GROUP_1_REG */
-#define BA1_CFG2 0x138 /* BA1_CAPTURE_FRAME_GROUP_2_REG */
-#define BA1_CCST 0x13c /* BA1_CAPTURE_CONSTANT_REG */
-#define BA1_CSPB 0x340 /* BA1_CAPTURE_SPB_ADDRESS */
-
-/*
- *
- */
-
-#define CS461X_MODE_OUTPUT (1<<0) /* MIDI UART - output */
-#define CS461X_MODE_INPUT (1<<1) /* MIDI UART - input */
-
-//****************************************************************************
-//
-// The following define the offsets of the AC97 shadow registers, which appear
-// as a virtual extension to the base address register zero memory range.
-//
-//****************************************************************************
-#define AC97_REG_OFFSET_MASK 0x0000007EL
-#define AC97_CODEC_NUMBER_MASK 0x00003000L
-
-#define BA0_AC97_RESET 0x00001000L
-#define BA0_AC97_MASTER_VOLUME 0x00001002L
-#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L
-#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L
-#define BA0_AC97_MASTER_TONE 0x00001008L
-#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL
-#define BA0_AC97_PHONE_VOLUME 0x0000100CL
-#define BA0_AC97_MIC_VOLUME 0x0000100EL
-#define BA0_AC97_LINE_IN_VOLUME 0x00001010L
-#define BA0_AC97_CD_VOLUME 0x00001012L
-#define BA0_AC97_VIDEO_VOLUME 0x00001014L
-#define BA0_AC97_AUX_VOLUME 0x00001016L
-#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L
-#define BA0_AC97_RECORD_SELECT 0x0000101AL
-#define BA0_AC97_RECORD_GAIN 0x0000101CL
-#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL
-#define BA0_AC97_GENERAL_PURPOSE 0x00001020L
-#define BA0_AC97_3D_CONTROL 0x00001022L
-#define BA0_AC97_MODEM_RATE 0x00001024L
-#define BA0_AC97_POWERDOWN 0x00001026L
-#define BA0_AC97_EXT_AUDIO_ID 0x00001028L
-#define BA0_AC97_EXT_AUDIO_POWER 0x0000102AL
-#define BA0_AC97_PCM_FRONT_DAC_RATE 0x0000102CL
-#define BA0_AC97_PCM_SURR_DAC_RATE 0x0000102EL
-#define BA0_AC97_PCM_LFE_DAC_RATE 0x00001030L
-#define BA0_AC97_PCM_LR_ADC_RATE 0x00001032L
-#define BA0_AC97_MIC_ADC_RATE 0x00001034L
-#define BA0_AC97_6CH_VOL_C_LFE 0x00001036L
-#define BA0_AC97_6CH_VOL_SURROUND 0x00001038L
-#define BA0_AC97_RESERVED_3A 0x0000103AL
-#define BA0_AC97_EXT_MODEM_ID 0x0000103CL
-#define BA0_AC97_EXT_MODEM_POWER 0x0000103EL
-#define BA0_AC97_LINE1_CODEC_RATE 0x00001040L
-#define BA0_AC97_LINE2_CODEC_RATE 0x00001042L
-#define BA0_AC97_HANDSET_CODEC_RATE 0x00001044L
-#define BA0_AC97_LINE1_CODEC_LEVEL 0x00001046L
-#define BA0_AC97_LINE2_CODEC_LEVEL 0x00001048L
-#define BA0_AC97_HANDSET_CODEC_LEVEL 0x0000104AL
-#define BA0_AC97_GPIO_PIN_CONFIG 0x0000104CL
-#define BA0_AC97_GPIO_PIN_TYPE 0x0000104EL
-#define BA0_AC97_GPIO_PIN_STICKY 0x00001050L
-#define BA0_AC97_GPIO_PIN_WAKEUP 0x00001052L
-#define BA0_AC97_GPIO_PIN_STATUS 0x00001054L
-#define BA0_AC97_MISC_MODEM_AFE_STAT 0x00001056L
-#define BA0_AC97_RESERVED_58 0x00001058L
-#define BA0_AC97_CRYSTAL_REV_N_FAB_ID 0x0000105AL
-#define BA0_AC97_TEST_AND_MISC_CTRL 0x0000105CL
-#define BA0_AC97_AC_MODE 0x0000105EL
-#define BA0_AC97_MISC_CRYSTAL_CONTROL 0x00001060L
-#define BA0_AC97_LINE1_HYPRID_CTRL 0x00001062L
-#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L
-#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L
-#define BA0_AC97_SPDIF_CONTROL 0x00001068L
-#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL
-#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL
-#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL
-#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L
-#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L
-#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L
-#define BA0_AC97_CAL_ADDRESS 0x00001076L
-#define BA0_AC97_CAL_DATA 0x00001078L
-#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL
-#define BA0_AC97_VENDOR_ID1 0x0000107CL
-#define BA0_AC97_VENDOR_ID2 0x0000107EL
-#endif /* __CS461X_H */
diff --git a/sound/oss/cs461x_image.h b/sound/oss/cs461x_image.h
deleted file mode 100644
index b5c5a46d3423..000000000000
--- a/sound/oss/cs461x_image.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/****************************************************************************
- * "CWCIMAGE.H"-- For CS46XX. Ver 1.04
- * Copyright 1998-2001 (c) Cirrus Logic Corp.
- * Version 1.04
- ****************************************************************************
- */
-#ifndef __CS_IMAGE_H
-#define __CS_IMAGE_H
-
-#define CLEAR__COUNT 3
-#define FILL__COUNT 4
-#define BA1__DWORD_SIZE 13*1024+512
-
-static struct
-{
- unsigned BA1__DestByteOffset;
- unsigned BA1__SourceSize;
-} ClrStat[CLEAR__COUNT] ={ {0x00000000, 0x00003000 },
- {0x00010000, 0x00003800 },
- {0x00020000, 0x00007000 } };
-
-static u32 FillArray1[]={
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00200040,0x00008010,0x00000000,
-0x00000000,0x80000001,0x00000001,0x00060000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00900080,0x00000173,0x00000000,
-0x00000000,0x00000010,0x00800000,0x00900000,
-0xf2c0000f,0x00000200,0x00000000,0x00010600,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x330300c2,
-0x06000000,0x00000000,0x80008000,0x80008000,
-0x3fc0000f,0x00000301,0x00010400,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-0x04800000,0x00000001,0x00800001,0x0000ffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x066a0600,0x06350070,0x0000929d,0x929d929d,
-0x00000000,0x0000735a,0x00000600,0x00000000,
-0x929d735a,0x00000000,0x00010000,0x735a735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000804f,0x000000c3,
-0x05000000,0x00a00010,0x00000000,0x80008000,
-0x00000000,0x00000000,0x00000700,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000080,0x00a00000,0x0000809a,0x000000c2,
-0x07400000,0x00000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x000107a0,
-0x00c80028,0x000000c2,0x06800000,0x00000000,
-0x06e00080,0x00300000,0x000080bb,0x000000c9,
-0x07a00000,0x04000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x00000780,
-0x00c80028,0x000000c5,0xff800000,0x00000000,
-0x00640080,0x00c00000,0x00008197,0x000000c9,
-0x07800000,0x04000000,0x80008000,0xffffffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000805e,0x000000c1,
-0x00000000,0x00800000,0x80008000,0x80008000,
-0x00020000,0x0000ffff,0x00000000,0x00000000};
-
-static u32 FillArray2[]={
-0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x00100635,0x060b013f,0x00000004,
-0x00000001,0x007a0002,0x00000000,0x066e0610,
-0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-0x00000000,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x00000000,0x06400136,
-0x0000270f,0x00010000,0x007a0000,0x00000000,
-0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x735a0100,0x00000000,0x00000000,0x00000000};
-
-static u32 FillArray3[]={
-0x00000000,0x00000000,0x00000000,0x00010004};
-
-static u32 FillArray4[]={
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00001705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00009705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00011705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00019705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00021705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00029705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00031705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00039705,0x00001400,0x000a411e,0x00001003,
-0x000fe19e,0x00001003,0x0009c730,0x00001003,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00009705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00011705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00019705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00021705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00029705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00031705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00039705,0x00001400,0x000a211e,0x00001003,
-0x0000a730,0x00001008,0x000e2730,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x00000000,0x00000000,0x000f619c,0x00001003,
-0x0007f801,0x000c0000,0x00000037,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0000373c,0x00001000,0x00000000,0x00000000,
-0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000273c,0x00001000,
-0x00000033,0x00001000,0x000e679e,0x00001003,
-0x00007705,0x00001400,0x000ac71e,0x00001003,
-0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000a730,0x00001003,
-0x00000033,0x00001000,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x000c0000,
-0x00000032,0x00001000,0x0000273d,0x00001000,
-0x0004a730,0x00001003,0x00000f41,0x00097140,
-0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-0x00002725,0x000aa400,0x00013705,0x00093a00,
-0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-0x00031705,0x00092240,0x00039f05,0x000932c0,
-0x0003520a,0x00000000,0x00040731,0x0000100b,
-0x00010705,0x000b20c0,0x00000000,0x000eba44,
-0x00032108,0x000c60c4,0x00065208,0x000c2917,
-0x000406b0,0x00001007,0x00012f05,0x00036880,
-0x0002818e,0x000c0000,0x0004410a,0x00000000,
-0x00040630,0x00001007,0x00029705,0x000c0000,
-0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-0x000683ad,0x00095241,0x00020f05,0x000991c1,
-0x00000000,0x00000000,0x00086f88,0x00001000,
-0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-0x000a1681,0x000b97c0,0x00021601,0x00002500,
-0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-0x00021681,0x00002d00,0x00020f81,0x000bd800,
-0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-0x00021681,0x00020d00,0x00020f81,0x000bde80,
-0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-0x0007e48a,0x00000000,0x00011f05,0x00084080,
-0x00000000,0x00000000,0x00001705,0x000b3540,
-0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-0x00055488,0x00000000,0x0000d482,0x0003fc40,
-0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-0x000c86b0,0x00001007,0x00008281,0x000bb240,
-0x0000b801,0x000b7140,0x00007888,0x00000000,
-0x0000073c,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x00055288,0x000c555c,
-0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-0x0000fa88,0x00000000,0x00000032,0x00001000,
-0x0000073d,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x0008c01c,0x00001003,
-0x00002705,0x00001008,0x0008b201,0x000c1392,
-0x0000ba01,0x00000000,0x00008731,0x00001400,
-0x0004c108,0x000fe0c4,0x00057488,0x00000000,
-0x000a6388,0x00001001,0x0008b334,0x000bc141,
-0x0003020e,0x00000000,0x000886b0,0x00001008,
-0x00003625,0x000c5dfa,0x000a638a,0x00001001,
-0x0008020e,0x00001002,0x0008a6b0,0x00001008,
-0x0007f301,0x00000000,0x00000000,0x00000000,
-0x00002725,0x000a8c40,0x000000ae,0x00000000,
-0x000d8630,0x00001008,0x00000000,0x000c74e0,
-0x0007d182,0x0002d640,0x000a8630,0x00001008,
-0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
-0x0007420a,0x000c0000,0x00062208,0x000c4117,
-0x00070630,0x00001009,0x00000000,0x000c0000,
-0x0001022e,0x00000000,0x0003a630,0x00001009,
-0x00000000,0x000c0000,0x00000036,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x0002a730,0x00001008,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0002a730,0x00001008,
-0x00000033,0x00001000,0x0002a705,0x00001008,
-0x00007a01,0x000c0000,0x000e6288,0x000d550a,
-0x0006428a,0x00000000,0x00060730,0x0000100a,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-0x00057488,0x00000000,0x00033b94,0x00081140,
-0x000183ae,0x00000000,0x000786b0,0x0000100b,
-0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-0x00042731,0x00001003,0x0007aab0,0x00034880,
-0x00048fb0,0x0000100a,0x00057488,0x00000000,
-0x00033b94,0x00081140,0x000183ae,0x00000000,
-0x000806b0,0x0000100b,0x00022f05,0x00000000,
-0x00007401,0x00091140,0x00048f05,0x000951c0,
-0x00042731,0x00001003,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x000fe19e,0x00001003,0x00000000,0x00000000,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00000f41,0x00097140,0x0000a841,0x0009b240,
-0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
-0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
-0x00055208,0x00000000,0x00010705,0x000a2880,
-0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
-0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
-0x00065308,0x000c2997,0x000d86b0,0x0000100a,
-0x0004410a,0x000d40c7,0x00000000,0x00000000,
-0x00080730,0x00001004,0x00056f0a,0x000ea105,
-0x00000000,0x00000000,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x0000273d,0x00001000,0x00000000,0x000eba44,
-0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x00000000,0x000e5084,
-0x00000000,0x000eba44,0x00087401,0x000e4782,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
-0x0007e721,0x000bed40,0x00005f25,0x000badc0,
-0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
-0x00033217,0x00003ec0,0x00065590,0x000b8e40,
-0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
-0x000283a0,0x0000100c,0x000ee388,0x00042970,
-0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
-0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
-0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
-0x00078898,0x00001000,0x00038894,0x00000032,
-0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
-0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
-0x00041705,0x0009ed40,0x00058730,0x00001400,
-0x000d7488,0x000c3a00,0x00048f05,0x00000000};
-
-static struct
-{ u32 Offset;
- u32 Size;
- u32 *pFill;
-} FillStat[FILL__COUNT] = {
- {0x00000000, sizeof(FillArray1), FillArray1},
- {0x00001800, sizeof(FillArray2), FillArray2},
- {0x000137f0, sizeof(FillArray3), FillArray3},
- {0x00020000, sizeof(FillArray4), FillArray4}
- };
-
-
-#endif
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
deleted file mode 100644
index 2a1f0d9ac968..000000000000
--- a/sound/oss/cs46xx.c
+++ /dev/null
@@ -1,5444 +0,0 @@
-/*
- * Crystal SoundFusion CS46xx driver
- *
- * Copyright 1998-2001 Cirrus Logic Corporation <pcaudio@crystal.cirrus.com>
- * <twoller@crystal.cirrus.com>
- * Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz>
- * Copyright 2000 Alan Cox <alan@redhat.com>
- *
- * The core of this code is taken from the ALSA project driver by
- * Jaroslav. Please send Jaroslav the credit for the driver and
- * report bugs in this port to <alan@redhat.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.
- * Current maintainers:
- * Cirrus Logic Corporation, Thomas Woller (tw)
- * <twoller@crystal.cirrus.com>
- * Nils Faerber (nf)
- * <nils@kernelconcepts.de>
- * Thanks to David Pollard for testing.
- *
- * Changes:
- * 20000909-nf Changed cs_read, cs_write and drain_dac
- * 20001025-tw Separate Playback/Capture structs and buffers.
- * Added Scatter/Gather support for Playback.
- * Added Capture.
- * 20001027-nf Port to kernel 2.4.0-test9, some clean-ups
- * Start of powermanagement support (CS46XX_PM).
- * 20001128-tw Add module parm for default buffer order.
- * added DMA_GFP flag to kmalloc dma buffer allocs.
- * backfill silence to eliminate stuttering on
- * underruns.
- * 20001201-tw add resyncing of swptr on underruns.
- * 20001205-tw-nf fixed GETOSPACE ioctl() after open()
- * 20010113-tw patch from Hans Grobler general cleanup.
- * 20010117-tw 2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0
- * 20010118-tw basic PM support for 2.2.16+ and 2.4.0/2.4.2.
- * 20010228-dh patch from David Huggins - cs_update_ptr recursion.
- * 20010409-tw add hercules game theatre XP amp code.
- * 20010420-tw cleanup powerdown/up code.
- * 20010521-tw eliminate pops, and fixes for powerdown.
- * 20010525-tw added fixes for thinkpads with powerdown logic.
- * 20010723-sh patch from Horms (Simon Horman) -
- * SOUND_PCM_READ_BITS returns bits as set in driver
- * rather than a logical or of the possible values.
- * Various ioctls handle the case where the device
- * is open for reading or writing but not both better.
- *
- * Status:
- * Playback/Capture supported from 8k-48k.
- * 16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
- *
- * APM/PM - 2.2.x APM is enabled and functioning fine. APM can also
- * be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
- * definition.
- *
- * Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
- * so, use the drain/polarity to enable.
- * hercules_egpio_disable set to 1, will force a 0 to EGPIODR.
- *
- * VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
- * the external amplifier for the "back" speakers, since we do not
- * support the secondary codec then this external amp is also not
- * turned on.
- */
-
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/ac97_codec.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include "cs46xxpm.h"
-#include "cs46xx_wrapper-24.h"
-#include "cs461x.h"
-
-/* MIDI buffer sizes */
-#define CS_MIDIINBUF 500
-#define CS_MIDIOUTBUF 500
-
-#define ADC_RUNNING 1
-#define DAC_RUNNING 2
-
-#define CS_FMT_16BIT 1 /* These are fixed in fact */
-#define CS_FMT_STEREO 2
-#define CS_FMT_MASK 3
-
-#define CS_TYPE_ADC 1
-#define CS_TYPE_DAC 2
-
-#define CS_TRUE 1
-#define CS_FALSE 0
-
-#define CS_INC_USE_COUNT(m) (atomic_inc(m))
-#define CS_DEC_USE_COUNT(m) (atomic_dec(m))
-#define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m))
-#define CS_IN_USE(m) (atomic_read(m) != 0)
-
-#define CS_DBGBREAKPOINT {__asm__("INT $3");}
-/*
- * CS461x definitions
- */
-
-#define CS461X_BA0_SIZE 0x2000
-#define CS461X_BA1_DATA0_SIZE 0x3000
-#define CS461X_BA1_DATA1_SIZE 0x3800
-#define CS461X_BA1_PRG_SIZE 0x7000
-#define CS461X_BA1_REG_SIZE 0x0100
-
-#define GOF_PER_SEC 200
-
-#define CSDEBUG_INTERFACE 1
-#define CSDEBUG 1
-/*
- * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG
- *
- *
- * CSDEBUG is usual mode is set to 1, then use the
- * cs_debuglevel and cs_debugmask to turn on or off debugging.
- * Debug level of 1 has been defined to be kernel errors and info
- * that should be printed on any released driver.
- */
-#if CSDEBUG
-#define CS_DBGOUT(mask,level,x) if ((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;}
-#else
-#define CS_DBGOUT(mask,level,x)
-#endif
-/*
- * cs_debugmask areas
- */
-#define CS_INIT 0x00000001 /* initialization and probe functions */
-#define CS_ERROR 0x00000002 /* tmp debugging bit placeholder */
-#define CS_INTERRUPT 0x00000004 /* interrupt handler (separate from all other) */
-#define CS_FUNCTION 0x00000008 /* enter/leave functions */
-#define CS_WAVE_WRITE 0x00000010 /* write information for wave */
-#define CS_WAVE_READ 0x00000020 /* read information for wave */
-#define CS_MIDI_WRITE 0x00000040 /* write information for midi */
-#define CS_MIDI_READ 0x00000080 /* read information for midi */
-#define CS_MPU401_WRITE 0x00000100 /* write information for mpu401 */
-#define CS_MPU401_READ 0x00000200 /* read information for mpu401 */
-#define CS_OPEN 0x00000400 /* all open functions in the driver */
-#define CS_RELEASE 0x00000800 /* all release functions in the driver */
-#define CS_PARMS 0x00001000 /* functional and operational parameters */
-#define CS_IOCTL 0x00002000 /* ioctl (non-mixer) */
-#define CS_PM 0x00004000 /* PM */
-#define CS_TMP 0x10000000 /* tmp debug mask bit */
-
-#define CS_IOCTL_CMD_SUSPEND 0x1 // suspend
-#define CS_IOCTL_CMD_RESUME 0x2 // resume
-
-#if CSDEBUG
-static unsigned long cs_debuglevel = 1; /* levels range from 1-9 */
-module_param(cs_debuglevel, ulong, 0644);
-static unsigned long cs_debugmask = CS_INIT | CS_ERROR; /* use CS_DBGOUT with various mask values */
-module_param(cs_debugmask, ulong, 0644);
-#endif
-static unsigned long hercules_egpio_disable; /* if non-zero set all EGPIO to 0 */
-module_param(hercules_egpio_disable, ulong, 0);
-static unsigned long initdelay = 700; /* PM delay in millisecs */
-module_param(initdelay, ulong, 0);
-static unsigned long powerdown = -1; /* turn on/off powerdown processing in driver */
-module_param(powerdown, ulong, 0);
-#define DMABUF_DEFAULTORDER 3
-static unsigned long defaultorder = DMABUF_DEFAULTORDER;
-module_param(defaultorder, ulong, 0);
-
-static int external_amp;
-module_param(external_amp, bool, 0);
-static int thinkpad;
-module_param(thinkpad, bool, 0);
-
-/*
-* set the powerdown module parm to 0 to disable all
-* powerdown. also set thinkpad to 1 to disable powerdown,
-* but also to enable the clkrun functionality.
-*/
-static unsigned cs_powerdown = 1;
-static unsigned cs_laptop_wait = 1;
-
-/* An instance of the 4610 channel */
-struct cs_channel
-{
- int used;
- int num;
- void *state;
-};
-
-#define CS46XX_MAJOR_VERSION "1"
-#define CS46XX_MINOR_VERSION "28"
-
-#ifdef __ia64__
-#define CS46XX_ARCH "64" //architecture key
-#else
-#define CS46XX_ARCH "32" //architecture key
-#endif
-
-static struct list_head cs46xx_devs = { &cs46xx_devs, &cs46xx_devs };
-
-/* magic numbers to protect our data structures */
-#define CS_CARD_MAGIC 0x43525553 /* "CRUS" */
-#define CS_STATE_MAGIC 0x4c4f4749 /* "LOGI" */
-#define NR_HW_CH 3
-
-/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
-#define NR_AC97 2
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct cs_state {
- unsigned int magic;
- struct cs_card *card; /* Card info */
-
- /* single open lock mechanism, only used for recording */
- struct mutex open_mutex;
- wait_queue_head_t open_wait;
-
- /* file mode */
- mode_t open_mode;
-
- /* virtual channel number */
- int virt;
-
- struct dmabuf {
- /* wave sample stuff */
- unsigned int rate;
- unsigned char fmt, enable;
-
- /* hardware channel */
- struct cs_channel *channel;
- int pringbuf; /* Software ring slot */
- void *pbuf; /* 4K hardware DMA buffer */
-
- /* OSS buffer management stuff */
- void *rawbuf;
- dma_addr_t dma_handle;
- unsigned buforder;
- unsigned numfrag;
- unsigned fragshift;
- unsigned divisor;
- unsigned type;
- void *tmpbuff; /* tmp buffer for sample conversions */
- dma_addr_t dmaaddr;
- dma_addr_t dmaaddr_tmpbuff;
- unsigned buforder_tmpbuff; /* Log base 2 of size in bytes.. */
-
- /* our buffer acts like a circular ring */
- unsigned hwptr; /* where dma last started, updated by update_ptr */
- unsigned swptr; /* where driver last clear/filled, updated by read/write */
- int count; /* bytes to be comsumed or been generated by dma machine */
- unsigned total_bytes; /* total bytes dmaed by hardware */
- unsigned blocks; /* total blocks */
-
- unsigned error; /* number of over/underruns */
- unsigned underrun; /* underrun pending before next write has occurred */
- wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
-
- /* redundant, but makes calculations easier */
- unsigned fragsize;
- unsigned dmasize;
- unsigned fragsamples;
-
- /* OSS stuff */
- unsigned mapped:1;
- unsigned ready:1;
- unsigned endcleared:1;
- unsigned SGok:1;
- unsigned update_flag;
- unsigned ossfragshift;
- int ossmaxfrags;
- unsigned subdivision;
- } dmabuf;
- /* Guard against mmap/write/read races */
- struct mutex sem;
-};
-
-struct cs_card {
- struct cs_channel channel[2];
- unsigned int magic;
-
- /* We keep cs461x cards in a linked list */
- struct cs_card *next;
-
- /* The cs461x has a certain amount of cross channel interaction
- so we use a single per card lock */
- spinlock_t lock;
-
- /* Keep AC97 sane */
- spinlock_t ac97_lock;
-
- /* mixer use count */
- atomic_t mixer_use_cnt;
-
- /* PCI device stuff */
- struct pci_dev *pci_dev;
- struct list_head list;
-
- unsigned int pctl, cctl; /* Hardware DMA flag sets */
-
- /* soundcore stuff */
- int dev_audio;
- int dev_midi;
-
- /* structures for abstraction of hardware facilities, codecs, banks and channels*/
- struct ac97_codec *ac97_codec[NR_AC97];
- struct cs_state *states[2];
-
- u16 ac97_features;
-
- int amplifier; /* Amplifier control */
- void (*amplifier_ctrl)(struct cs_card *, int);
- void (*amp_init)(struct cs_card *);
-
- int active; /* Active clocking */
- void (*active_ctrl)(struct cs_card *, int);
-
- /* hardware resources */
- unsigned long ba0_addr;
- unsigned long ba1_addr;
- u32 irq;
-
- /* mappings */
- void __iomem *ba0;
- union
- {
- struct
- {
- u8 __iomem *data0;
- u8 __iomem *data1;
- u8 __iomem *pmem;
- u8 __iomem *reg;
- } name;
- u8 __iomem *idx[4];
- } ba1;
-
- /* Function support */
- struct cs_channel *(*alloc_pcm_channel)(struct cs_card *);
- struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *);
- void (*free_pcm_channel)(struct cs_card *, int chan);
-
- /* /dev/midi stuff */
- struct {
- unsigned ird, iwr, icnt;
- unsigned ord, owr, ocnt;
- wait_queue_head_t open_wait;
- wait_queue_head_t iwait;
- wait_queue_head_t owait;
- spinlock_t lock;
- unsigned char ibuf[CS_MIDIINBUF];
- unsigned char obuf[CS_MIDIOUTBUF];
- mode_t open_mode;
- struct mutex open_mutex;
- } midi;
- struct cs46xx_pm pm;
-};
-
-static int cs_open_mixdev(struct inode *inode, struct file *file);
-static int cs_release_mixdev(struct inode *inode, struct file *file);
-static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg);
-static int cs_hardware_init(struct cs_card *card);
-static int cs46xx_powerup(struct cs_card *card, unsigned int type);
-static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
-static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
-#ifdef CONFIG_PM
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
-static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#endif
-
-#if CSDEBUG
-
-/* DEBUG ROUTINES */
-
-#define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int)
-#define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int)
-#define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int)
-#define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int)
-#define SOUND_MIXER_CS_APM _SIOWR('M',124, int)
-
-static void printioctl(unsigned int x)
-{
- unsigned int i;
- unsigned char vidx;
- /* these values are incorrect for the ac97 driver, fix.
- * Index of mixtable1[] member is Device ID
- * and must be <= SOUND_MIXER_NRDEVICES.
- * Value of array member is index into s->mix.vol[]
- */
- static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
- [SOUND_MIXER_PCM] = 1, /* voice */
- [SOUND_MIXER_LINE1] = 2, /* AUX */
- [SOUND_MIXER_CD] = 3, /* CD */
- [SOUND_MIXER_LINE] = 4, /* Line */
- [SOUND_MIXER_SYNTH] = 5, /* FM */
- [SOUND_MIXER_MIC] = 6, /* Mic */
- [SOUND_MIXER_SPEAKER] = 7, /* Speaker */
- [SOUND_MIXER_RECLEV] = 8, /* Recording level */
- [SOUND_MIXER_VOLUME] = 9 /* Master Volume */
- };
-
- switch (x) {
- case SOUND_MIXER_CS_GETDBGMASK:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") );
- break;
- case SOUND_MIXER_CS_GETDBGLEVEL:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") );
- break;
- case SOUND_MIXER_CS_SETDBGMASK:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") );
- break;
- case SOUND_MIXER_CS_SETDBGLEVEL:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") );
- break;
- case OSS_GETVERSION:
- CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") );
- break;
- case SNDCTL_DSP_SYNC:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") );
- break;
- case SNDCTL_DSP_SETDUPLEX:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") );
- break;
- case SNDCTL_DSP_GETCAPS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") );
- break;
- case SNDCTL_DSP_RESET:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") );
- break;
- case SNDCTL_DSP_SPEED:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") );
- break;
- case SNDCTL_DSP_STEREO:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") );
- break;
- case SNDCTL_DSP_CHANNELS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") );
- break;
- case SNDCTL_DSP_GETFMTS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") );
- break;
- case SNDCTL_DSP_SETFMT:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") );
- break;
- case SNDCTL_DSP_POST:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") );
- break;
- case SNDCTL_DSP_GETTRIGGER:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") );
- break;
- case SNDCTL_DSP_SETTRIGGER:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") );
- break;
- case SNDCTL_DSP_GETOSPACE:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") );
- break;
- case SNDCTL_DSP_GETISPACE:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") );
- break;
- case SNDCTL_DSP_NONBLOCK:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") );
- break;
- case SNDCTL_DSP_GETODELAY:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") );
- break;
- case SNDCTL_DSP_GETIPTR:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") );
- break;
- case SNDCTL_DSP_GETOPTR:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") );
- break;
- case SNDCTL_DSP_GETBLKSIZE:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") );
- break;
- case SNDCTL_DSP_SETFRAGMENT:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") );
- break;
- case SNDCTL_DSP_SUBDIVIDE:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") );
- break;
- case SOUND_PCM_READ_RATE:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") );
- break;
- case SOUND_PCM_READ_CHANNELS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") );
- break;
- case SOUND_PCM_READ_BITS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") );
- break;
- case SOUND_PCM_WRITE_FILTER:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") );
- break;
- case SNDCTL_DSP_SETSYNCRO:
- CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") );
- break;
- case SOUND_PCM_READ_FILTER:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") );
- break;
- case SOUND_MIXER_PRIVATE1:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") );
- break;
- case SOUND_MIXER_PRIVATE2:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") );
- break;
- case SOUND_MIXER_PRIVATE3:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") );
- break;
- case SOUND_MIXER_PRIVATE4:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") );
- break;
- case SOUND_MIXER_PRIVATE5:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") );
- break;
- case SOUND_MIXER_INFO:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") );
- break;
- case SOUND_OLD_MIXER_INFO:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") );
- break;
- default:
- switch (_IOC_NR(x)) {
- case SOUND_MIXER_VOLUME:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") );
- break;
- case SOUND_MIXER_SPEAKER:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") );
- break;
- case SOUND_MIXER_RECLEV:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") );
- break;
- case SOUND_MIXER_MIC:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") );
- break;
- case SOUND_MIXER_SYNTH:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") );
- break;
- case SOUND_MIXER_RECSRC:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") );
- break;
- case SOUND_MIXER_DEVMASK:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") );
- break;
- case SOUND_MIXER_RECMASK:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") );
- break;
- case SOUND_MIXER_STEREODEVS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") );
- break;
- case SOUND_MIXER_CAPS:
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") );
- break;
- default:
- i = _IOC_NR(x);
- if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) {
- CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) );
- } else {
- CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ",
- x,i));
- }
- break;
- }
- }
- CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) );
-}
-#endif
-
-/*
- * common I/O routines
- */
-
-static void cs461x_poke(struct cs_card *codec, unsigned long reg, unsigned int val)
-{
- writel(val, codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
-}
-
-static unsigned int cs461x_peek(struct cs_card *codec, unsigned long reg)
-{
- return readl(codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
-}
-
-static void cs461x_pokeBA0(struct cs_card *codec, unsigned long reg, unsigned int val)
-{
- writel(val, codec->ba0 + reg);
-}
-
-static unsigned int cs461x_peekBA0(struct cs_card *codec, unsigned long reg)
-{
- return readl(codec->ba0 + reg);
-}
-
-
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg);
-static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
-
-static struct cs_channel *cs_alloc_pcm_channel(struct cs_card *card)
-{
- if (card->channel[1].used == 1)
- return NULL;
- card->channel[1].used = 1;
- card->channel[1].num = 1;
- return &card->channel[1];
-}
-
-static struct cs_channel *cs_alloc_rec_pcm_channel(struct cs_card *card)
-{
- if (card->channel[0].used == 1)
- return NULL;
- card->channel[0].used = 1;
- card->channel[0].num = 0;
- return &card->channel[0];
-}
-
-static void cs_free_pcm_channel(struct cs_card *card, int channel)
-{
- card->channel[channel].state = NULL;
- card->channel[channel].used = 0;
-}
-
-/*
- * setup a divisor value to help with conversion from
- * 16bit Stereo, down to 8bit stereo/mono or 16bit mono.
- * assign a divisor of 1 if using 16bit Stereo as that is
- * the only format that the static image will capture.
- */
-static void cs_set_divisor(struct dmabuf *dmabuf)
-{
- if (dmabuf->type == CS_TYPE_DAC)
- dmabuf->divisor = 1;
- else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
- (dmabuf->fmt & CS_FMT_16BIT))
- dmabuf->divisor = 2;
- else if ((dmabuf->fmt & CS_FMT_STEREO) &&
- !(dmabuf->fmt & CS_FMT_16BIT))
- dmabuf->divisor = 2;
- else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
- !(dmabuf->fmt & CS_FMT_16BIT))
- dmabuf->divisor = 4;
- else
- dmabuf->divisor = 1;
-
- CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk(
- "cs46xx: cs_set_divisor()- %s %d\n",
- (dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC",
- dmabuf->divisor) );
-}
-
-/*
-* mute some of the more prevalent registers to avoid popping.
-*/
-static void cs_mute(struct cs_card *card, int state)
-{
- struct ac97_codec *dev = card->ac97_codec[0];
-
- CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n",
- (state == CS_TRUE) ? "Muting" : "UnMuting"));
-
- if (state == CS_TRUE) {
- /*
- * fix pops when powering up on thinkpads
- */
- card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev,
- (u8)BA0_AC97_MASTER_VOLUME);
- card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev,
- (u8)BA0_AC97_HEADPHONE_VOLUME);
- card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev,
- (u8)BA0_AC97_MASTER_VOLUME_MONO);
- card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev,
- (u8)BA0_AC97_PCM_OUT_VOLUME);
-
- cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
- cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
- cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
- cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
- } else {
- cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume);
- cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume);
- cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono);
- cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume);
- }
- CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()-\n"));
-}
-
-/* set playback sample rate */
-static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned int tmp1, tmp2;
- unsigned int phiIncr;
- unsigned int correctionPerGOF, correctionPerSec;
- unsigned long flags;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) );
-
- /*
- * Compute the values used to drive the actual sample rate conversion.
- * The following formulas are being computed, using inline assembly
- * since we need to use 64 bit arithmetic to compute the values:
- *
- * phiIncr = floor((Fs,in * 2^26) / Fs,out)
- * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
- * GOF_PER_SEC)
- * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
- * GOF_PER_SEC * correctionPerGOF
- *
- * i.e.
- *
- * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
- * correctionPerGOF:correctionPerSec =
- * dividend:remainder(ulOther / GOF_PER_SEC)
- */
- tmp1 = rate << 16;
- phiIncr = tmp1 / 48000;
- tmp1 -= phiIncr * 48000;
- tmp1 <<= 10;
- phiIncr <<= 10;
- tmp2 = tmp1 / 48000;
- phiIncr += tmp2;
- tmp1 -= tmp2 * 48000;
- correctionPerGOF = tmp1 / GOF_PER_SEC;
- tmp1 -= correctionPerGOF * GOF_PER_SEC;
- correctionPerSec = tmp1;
-
- /*
- * Fill in the SampleRateConverter control block.
- */
- spin_lock_irqsave(&state->card->lock, flags);
- cs461x_poke(state->card, BA1_PSRC,
- ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
- cs461x_poke(state->card, BA1_PPI, phiIncr);
- spin_unlock_irqrestore(&state->card->lock, flags);
- dmabuf->rate = rate;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) );
- return rate;
-}
-
-/* set recording sample rate */
-static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card = state->card;
- unsigned int phiIncr, coeffIncr, tmp1, tmp2;
- unsigned int correctionPerGOF, correctionPerSec, initialDelay;
- unsigned int frameGroupLength, cnt;
- unsigned long flags;
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) );
-
- /*
- * We can only decimate by up to a factor of 1/9th the hardware rate.
- * Correct the value if an attempt is made to stray outside that limit.
- */
- if ((rate * 9) < 48000)
- rate = 48000 / 9;
-
- /*
- * We cannot capture at at rate greater than the Input Rate (48000).
- * Return an error if an attempt is made to stray outside that limit.
- */
- if (rate > 48000)
- rate = 48000;
-
- /*
- * Compute the values used to drive the actual sample rate conversion.
- * The following formulas are being computed, using inline assembly
- * since we need to use 64 bit arithmetic to compute the values:
- *
- * coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
- * phiIncr = floor((Fs,in * 2^26) / Fs,out)
- * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
- * GOF_PER_SEC)
- * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
- * GOF_PER_SEC * correctionPerGOF
- * initialDelay = ceil((24 * Fs,in) / Fs,out)
- *
- * i.e.
- *
- * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
- * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
- * correctionPerGOF:correctionPerSec =
- * dividend:remainder(ulOther / GOF_PER_SEC)
- * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
- */
- tmp1 = rate << 16;
- coeffIncr = tmp1 / 48000;
- tmp1 -= coeffIncr * 48000;
- tmp1 <<= 7;
- coeffIncr <<= 7;
- coeffIncr += tmp1 / 48000;
- coeffIncr ^= 0xFFFFFFFF;
- coeffIncr++;
- tmp1 = 48000 << 16;
- phiIncr = tmp1 / rate;
- tmp1 -= phiIncr * rate;
- tmp1 <<= 10;
- phiIncr <<= 10;
- tmp2 = tmp1 / rate;
- phiIncr += tmp2;
- tmp1 -= tmp2 * rate;
- correctionPerGOF = tmp1 / GOF_PER_SEC;
- tmp1 -= correctionPerGOF * GOF_PER_SEC;
- correctionPerSec = tmp1;
- initialDelay = ((48000 * 24) + rate - 1) / rate;
-
- /*
- * Fill in the VariDecimate control block.
- */
- spin_lock_irqsave(&card->lock, flags);
- cs461x_poke(card, BA1_CSRC,
- ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
- cs461x_poke(card, BA1_CCI, coeffIncr);
- cs461x_poke(card, BA1_CD,
- (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
- cs461x_poke(card, BA1_CPI, phiIncr);
- spin_unlock_irqrestore(&card->lock, flags);
-
- /*
- * Figure out the frame group length for the write back task. Basically,
- * this is just the factors of 24000 (2^6*3*5^3) that are not present in
- * the output sample rate.
- */
- frameGroupLength = 1;
- for (cnt = 2; cnt <= 64; cnt *= 2) {
- if (((rate / cnt) * cnt) != rate)
- frameGroupLength *= 2;
- }
- if (((rate / 3) * 3) != rate) {
- frameGroupLength *= 3;
- }
- for (cnt = 5; cnt <= 125; cnt *= 5) {
- if (((rate / cnt) * cnt) != rate)
- frameGroupLength *= 5;
- }
-
- /*
- * Fill in the WriteBack control block.
- */
- spin_lock_irqsave(&card->lock, flags);
- cs461x_poke(card, BA1_CFG1, frameGroupLength);
- cs461x_poke(card, BA1_CFG2, (0x00800000 | frameGroupLength));
- cs461x_poke(card, BA1_CCST, 0x0000FFFF);
- cs461x_poke(card, BA1_CSPB, ((65536 * rate) / 24000));
- cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF);
- spin_unlock_irqrestore(&card->lock, flags);
- dmabuf->rate = rate;
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) );
- return rate;
-}
-
-/* prepare channel attributes for playback */
-static void cs_play_setup(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card = state->card;
- unsigned int tmp, Count, playFormat;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") );
- cs461x_poke(card, BA1_PVOL, 0x80008000);
- if (!dmabuf->SGok)
- cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));
-
- Count = 4;
- playFormat=cs461x_peek(card, BA1_PFIE);
- if ((dmabuf->fmt & CS_FMT_STEREO)) {
- playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO;
- Count *= 2;
- } else
- playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO;
-
- if ((dmabuf->fmt & CS_FMT_16BIT)) {
- playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT
- | DMA_RQ_C2_AC_SIGNED_CONVERT);
- Count *= 2;
- } else
- playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT
- | DMA_RQ_C2_AC_SIGNED_CONVERT);
-
- cs461x_poke(card, BA1_PFIE, playFormat);
-
- tmp = cs461x_peek(card, BA1_PDTC);
- tmp &= 0xfffffe00;
- cs461x_poke(card, BA1_PDTC, tmp | --Count);
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") );
-}
-
-static struct InitStruct
-{
- u32 off;
- u32 val;
-} InitArray[] = { {0x00000040, 0x3fc0000f},
- {0x0000004c, 0x04800000},
-
- {0x000000b3, 0x00000780},
- {0x000000b7, 0x00000000},
- {0x000000bc, 0x07800000},
-
- {0x000000cd, 0x00800000},
- };
-
-/*
- * "SetCaptureSPValues()" -- Initialize record task values before each
- * capture startup.
- */
-static void SetCaptureSPValues(struct cs_card *card)
-{
- unsigned i, offset;
- CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") );
- for (i = 0; i < sizeof(InitArray) / sizeof(struct InitStruct); i++) {
- offset = InitArray[i].off*4; /* 8bit to 32bit offset value */
- cs461x_poke(card, offset, InitArray[i].val );
- }
- CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") );
-}
-
-/* prepare channel attributes for recording */
-static void cs_rec_setup(struct cs_state *state)
-{
- struct cs_card *card = state->card;
- struct dmabuf *dmabuf = &state->dmabuf;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n"));
- SetCaptureSPValues(card);
-
- /*
- * set the attenuation to 0dB
- */
- cs461x_poke(card, BA1_CVOL, 0x80008000);
-
- /*
- * set the physical address of the capture buffer into the SP
- */
- cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf));
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") );
-}
-
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
- called with spinlock held! */
-
-static inline unsigned cs_get_dma_addr(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- u32 offset;
-
- if ( (!(dmabuf->enable & DAC_RUNNING)) &&
- (!(dmabuf->enable & ADC_RUNNING) ) )
- {
- CS_DBGOUT(CS_ERROR, 2, printk(
- "cs46xx: ERROR cs_get_dma_addr(): not enabled \n") );
- return 0;
- }
-
- /*
- * granularity is byte boundary, good part.
- */
- if (dmabuf->enable & DAC_RUNNING)
- offset = cs461x_peek(state->card, BA1_PBA);
- else /* ADC_RUNNING must be set */
- offset = cs461x_peek(state->card, BA1_CBA);
-
- CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9,
- printk("cs46xx: cs_get_dma_addr() %d\n",offset) );
- offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf;
- CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8,
- printk("cs46xx: cs_get_dma_addr()- %d\n",offset) );
- return offset;
-}
-
-static void resync_dma_ptrs(struct cs_state *state)
-{
- struct dmabuf *dmabuf;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );
- if (state) {
- dmabuf = &state->dmabuf;
- dmabuf->hwptr=dmabuf->swptr = 0;
- dmabuf->pringbuf = 0;
- }
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") );
-}
-
-/* Stop recording (lock held) */
-static inline void __stop_adc(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card = state->card;
- unsigned int tmp;
-
- dmabuf->enable &= ~ADC_RUNNING;
-
- tmp = cs461x_peek(card, BA1_CCTL);
- tmp &= 0xFFFF0000;
- cs461x_poke(card, BA1_CCTL, tmp );
-}
-
-static void stop_adc(struct cs_state *state)
-{
- unsigned long flags;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") );
- spin_lock_irqsave(&state->card->lock, flags);
- __stop_adc(state);
- spin_unlock_irqrestore(&state->card->lock, flags);
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") );
-}
-
-static void start_adc(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card = state->card;
- unsigned long flags;
- unsigned int tmp;
-
- spin_lock_irqsave(&card->lock, flags);
- if (!(dmabuf->enable & ADC_RUNNING) &&
- ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize)
- && dmabuf->ready) &&
- ((card->pm.flags & CS46XX_PM_IDLE) ||
- (card->pm.flags & CS46XX_PM_RESUMED)) )
- {
- dmabuf->enable |= ADC_RUNNING;
- cs_set_divisor(dmabuf);
- tmp = cs461x_peek(card, BA1_CCTL);
- tmp &= 0xFFFF0000;
- tmp |= card->cctl;
- CS_DBGOUT(CS_FUNCTION, 2, printk(
- "cs46xx: start_adc() poke 0x%x \n",tmp) );
- cs461x_poke(card, BA1_CCTL, tmp);
- }
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void __stop_dac(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card = state->card;
- unsigned int tmp;
-
- dmabuf->enable &= ~DAC_RUNNING;
-
- tmp=cs461x_peek(card, BA1_PCTL);
- tmp&=0xFFFF;
- cs461x_poke(card, BA1_PCTL, tmp);
-}
-
-static void stop_dac(struct cs_state *state)
-{
- unsigned long flags;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") );
- spin_lock_irqsave(&state->card->lock, flags);
- __stop_dac(state);
- spin_unlock_irqrestore(&state->card->lock, flags);
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") );
-}
-
-static void start_dac(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card = state->card;
- unsigned long flags;
- int tmp;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") );
- spin_lock_irqsave(&card->lock, flags);
- if (!(dmabuf->enable & DAC_RUNNING) &&
- ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) &&
- ((card->pm.flags & CS46XX_PM_IDLE) ||
- (card->pm.flags & CS46XX_PM_RESUMED)) )
- {
- dmabuf->enable |= DAC_RUNNING;
- tmp = cs461x_peek(card, BA1_PCTL);
- tmp &= 0xFFFF;
- tmp |= card->pctl;
- CS_DBGOUT(CS_PARMS, 6, printk(
- "cs46xx: start_dac() poke card=%p tmp=0x%.08x addr=%p \n",
- card, (unsigned)tmp,
- card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) );
- cs461x_poke(card, BA1_PCTL, tmp);
- }
- spin_unlock_irqrestore(&card->lock, flags);
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") );
-}
-
-#define DMABUF_MINORDER 1
-
-/*
- * allocate DMA buffer, playback and recording buffers are separate.
- */
-static int alloc_dmabuf(struct cs_state *state)
-{
-
- struct cs_card *card=state->card;
- struct dmabuf *dmabuf = &state->dmabuf;
- void *rawbuf = NULL;
- void *tmpbuff = NULL;
- int order;
- struct page *map, *mapend;
- unsigned long df;
-
- dmabuf->ready = dmabuf->mapped = 0;
- dmabuf->SGok = 0;
-/*
-* check for order within limits, but do not overwrite value.
-*/
- if ((defaultorder > 1) && (defaultorder < 12))
- df = defaultorder;
- else
- df = 2;
-
- for (order = df; order >= DMABUF_MINORDER; order--)
- if ((rawbuf = (void *)pci_alloc_consistent(
- card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr)))
- break;
- if (!rawbuf) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
- "cs46xx: alloc_dmabuf(): unable to allocate rawbuf\n"));
- return -ENOMEM;
- }
- dmabuf->buforder = order;
- dmabuf->rawbuf = rawbuf;
- // Now mark the pages as reserved; otherwise the
- // remap_pfn_range() in cs46xx_mmap doesn't work.
- // 1. get index to last page in mem_map array for rawbuf.
- mapend = virt_to_page(dmabuf->rawbuf +
- (PAGE_SIZE << dmabuf->buforder) - 1);
-
- // 2. mark each physical page in range as 'reserved'.
- for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
- cs4x_mem_map_reserve(map);
-
- CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n",
- PAGE_SIZE << order, order, rawbuf) );
-
-/*
-* only allocate the conversion buffer for the ADC
-*/
- if (dmabuf->type == CS_TYPE_DAC) {
- dmabuf->tmpbuff = NULL;
- dmabuf->buforder_tmpbuff = 0;
- return 0;
- }
-/*
- * now the temp buffer for 16/8 conversions
- */
-
- tmpbuff = (void *) pci_alloc_consistent(
- card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr_tmpbuff);
-
- if (!tmpbuff)
- return -ENOMEM;
- CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: allocated %ld (order = %d) bytes at %p\n",
- PAGE_SIZE << order, order, tmpbuff) );
-
- dmabuf->tmpbuff = tmpbuff;
- dmabuf->buforder_tmpbuff = order;
-
- // Now mark the pages as reserved; otherwise the
- // remap_pfn_range() in cs46xx_mmap doesn't work.
- // 1. get index to last page in mem_map array for rawbuf.
- mapend = virt_to_page(dmabuf->tmpbuff +
- (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
-
- // 2. mark each physical page in range as 'reserved'.
- for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
- cs4x_mem_map_reserve(map);
- return 0;
-}
-
-/* free DMA buffer */
-static void dealloc_dmabuf(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct page *map, *mapend;
-
- if (dmabuf->rawbuf) {
- // Undo prog_dmabuf()'s marking the pages as reserved
- mapend = virt_to_page(dmabuf->rawbuf +
- (PAGE_SIZE << dmabuf->buforder) - 1);
- for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
- cs4x_mem_map_unreserve(map);
- free_dmabuf(state->card, dmabuf);
- }
-
- if (dmabuf->tmpbuff) {
- // Undo prog_dmabuf()'s marking the pages as reserved
- mapend = virt_to_page(dmabuf->tmpbuff +
- (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
- for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
- cs4x_mem_map_unreserve(map);
- free_dmabuf2(state->card, dmabuf);
- }
-
- dmabuf->rawbuf = NULL;
- dmabuf->tmpbuff = NULL;
- dmabuf->mapped = dmabuf->ready = 0;
- dmabuf->SGok = 0;
-}
-
-static int __prog_dmabuf(struct cs_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned long flags;
- unsigned long allocated_pages, allocated_bytes;
- unsigned long tmp1, tmp2, fmt=0;
- unsigned long *ptmp = (unsigned long *) dmabuf->pbuf;
- unsigned long SGarray[9], nSGpages=0;
- int ret;
-
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n"));
-/*
- * check for CAPTURE and use only non-sg for initial release
- */
- if (dmabuf->type == CS_TYPE_ADC) {
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n"));
- /*
- * add in non-sg support for capture.
- */
- spin_lock_irqsave(&state->card->lock, flags);
- /* add code to reset the rawbuf memory. TRW */
- resync_dma_ptrs(state);
- dmabuf->total_bytes = dmabuf->blocks = 0;
- dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
-
- dmabuf->SGok = 0;
-
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* allocate DMA buffer if not allocated yet */
- if (!dmabuf->rawbuf || !dmabuf->tmpbuff)
- if ((ret = alloc_dmabuf(state)))
- return ret;
- /*
- * static image only supports 16Bit signed, stereo - hard code fmt
- */
- fmt = CS_FMT_16BIT | CS_FMT_STEREO;
-
- dmabuf->numfrag = 2;
- dmabuf->fragsize = 2048;
- dmabuf->fragsamples = 2048 >> sample_shift[fmt];
- dmabuf->dmasize = 4096;
- dmabuf->fragshift = 11;
-
- memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80,
- dmabuf->dmasize);
- memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80,
- PAGE_SIZE<<dmabuf->buforder_tmpbuff);
-
- /*
- * Now set up the ring
- */
-
- spin_lock_irqsave(&state->card->lock, flags);
- cs_rec_setup(state);
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* set the ready flag for the dma buffer */
- dmabuf->ready = 1;
-
- CS_DBGOUT(CS_PARMS, 4, printk(
- "cs46xx: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d "
- "fragsize=%d dmasize=%d\n",
- dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
- dmabuf->fragsize, dmabuf->dmasize) );
-
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n"));
- return 0;
- } else if (dmabuf->type == CS_TYPE_DAC) {
- /*
- * Must be DAC
- */
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n"));
- spin_lock_irqsave(&state->card->lock, flags);
- resync_dma_ptrs(state);
- dmabuf->total_bytes = dmabuf->blocks = 0;
- dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
-
- dmabuf->SGok = 0;
-
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* allocate DMA buffer if not allocated yet */
- if (!dmabuf->rawbuf)
- if ((ret = alloc_dmabuf(state)))
- return ret;
-
- allocated_pages = 1 << dmabuf->buforder;
- allocated_bytes = allocated_pages*PAGE_SIZE;
-
- if (allocated_pages < 2) {
- CS_DBGOUT(CS_FUNCTION, 4, printk(
- "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n",
- (unsigned)allocated_pages));
- return -ENOMEM;
- }
-
- /* Use all the pages allocated, fragsize 4k. */
- /* Use 'pbuf' for S/G page map table. */
- dmabuf->SGok = 1; /* Use S/G. */
-
- nSGpages = allocated_bytes/4096; /* S/G pages always 4k. */
-
- /* Set up S/G variables. */
- *ptmp = virt_to_bus(dmabuf->rawbuf);
- *(ptmp + 1) = 0x00000008;
- for (tmp1 = 1; tmp1 < nSGpages; tmp1++) {
- *(ptmp + 2 * tmp1) = virt_to_bus((dmabuf->rawbuf) + 4096 * tmp1);
- if (tmp1 == nSGpages - 1)
- tmp2 = 0xbfff0000;
- else
- tmp2 = 0x80000000 + 8 * (tmp1 + 1);
- *(ptmp + 2 * tmp1 + 1) = tmp2;
- }
- SGarray[0] = 0x82c0200d;
- SGarray[1] = 0xffff0000;
- SGarray[2] = *ptmp;
- SGarray[3] = 0x00010600;
- SGarray[4] = *(ptmp+2);
- SGarray[5] = 0x80000010;
- SGarray[6] = *ptmp;
- SGarray[7] = *(ptmp+2);
- SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;
-
- if (dmabuf->SGok) {
- dmabuf->numfrag = nSGpages;
- dmabuf->fragsize = 4096;
- dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];
- dmabuf->fragshift = 12;
- dmabuf->dmasize = dmabuf->numfrag * 4096;
- } else {
- SGarray[0] = 0xf2c0000f;
- SGarray[1] = 0x00000200;
- SGarray[2] = 0;
- SGarray[3] = 0x00010600;
- SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0;
- dmabuf->numfrag = 2;
- dmabuf->fragsize = 2048;
- dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt];
- dmabuf->dmasize = 4096;
- dmabuf->fragshift = 11;
- }
- for (tmp1 = 0; tmp1 < sizeof(SGarray) / 4; tmp1++)
- cs461x_poke(state->card, BA1_PDTC+tmp1 * 4, SGarray[tmp1]);
-
- memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
- dmabuf->dmasize);
-
- /*
- * Now set up the ring
- */
-
- spin_lock_irqsave(&state->card->lock, flags);
- cs_play_setup(state);
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* set the ready flag for the dma buffer */
- dmabuf->ready = 1;
-
- CS_DBGOUT(CS_PARMS, 4, printk(
- "cs46xx: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d "
- "fragsize=%d dmasize=%d\n",
- dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
- dmabuf->fragsize, dmabuf->dmasize) );
-
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n"));
- return 0;
- } else {
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n",
- dmabuf->type));
- }
- return 1;
-}
-
-static int prog_dmabuf(struct cs_state *state)
-{
- int ret;
-
- mutex_lock(&state->sem);
- ret = __prog_dmabuf(state);
- mutex_unlock(&state->sem);
-
- return ret;
-}
-
-static void cs_clear_tail(struct cs_state *state)
-{
-}
-
-static int drain_dac(struct cs_state *state, int nonblock)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct dmabuf *dmabuf = &state->dmabuf;
- struct cs_card *card=state->card;
- unsigned long flags;
- unsigned long tmo;
- int count;
-
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n"));
- if (dmabuf->mapped || !dmabuf->ready)
- {
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n"));
- return 0;
- }
-
- add_wait_queue(&dmabuf->wait, &wait);
- for (;;) {
- /* It seems that we have to set the current state to TASK_INTERRUPTIBLE
- every time to make the process really go to sleep */
- current->state = TASK_INTERRUPTIBLE;
-
- spin_lock_irqsave(&state->card->lock, flags);
- count = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (count <= 0)
- break;
-
- if (signal_pending(current))
- break;
-
- if (nonblock) {
- remove_wait_queue(&dmabuf->wait, &wait);
- current->state = TASK_RUNNING;
- return -EBUSY;
- }
-
- tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
- tmo >>= sample_shift[dmabuf->fmt];
- tmo += (2048*HZ)/dmabuf->rate;
-
- if (!schedule_timeout(tmo ? tmo : 1) && tmo){
- printk(KERN_ERR "cs46xx: drain_dac, dma timeout? %d\n", count);
- break;
- }
- }
- remove_wait_queue(&dmabuf->wait, &wait);
- current->state = TASK_RUNNING;
- if (signal_pending(current)) {
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n"));
- /*
- * set to silence and let that clear the fifos.
- */
- cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC);
- return -ERESTARTSYS;
- }
-
- CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n"));
- return 0;
-}
-
-
-/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */
-static void cs_update_ptr(struct cs_card *card, int wake)
-{
- struct cs_state *state;
- struct dmabuf *dmabuf;
- unsigned hwptr;
- int diff;
-
- /* error handling and process wake up for ADC */
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- if (dmabuf->enable & ADC_RUNNING) {
- /* update hardware pointer */
- hwptr = cs_get_dma_addr(state);
-
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
- CS_DBGOUT(CS_PARMS, 9, printk(
- "cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n",
- hwptr,diff) );
- dmabuf->hwptr = hwptr;
- dmabuf->total_bytes += diff;
- dmabuf->count += diff;
- if (dmabuf->count > dmabuf->dmasize)
- dmabuf->count = dmabuf->dmasize;
-
- if (dmabuf->mapped) {
- if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- } else {
- if (wake && dmabuf->count > 0)
- wake_up(&dmabuf->wait);
- }
- }
- }
-
-/*
- * Now the DAC
- */
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- /* error handling and process wake up for DAC */
- if (dmabuf->enable & DAC_RUNNING) {
- /* update hardware pointer */
- hwptr = cs_get_dma_addr(state);
-
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
- CS_DBGOUT(CS_PARMS, 9, printk(
- "cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n",
- hwptr,diff) );
- dmabuf->hwptr = hwptr;
- dmabuf->total_bytes += diff;
- if (dmabuf->mapped) {
- dmabuf->count += diff;
- if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- /*
- * other drivers use fragsize, but don't see any sense
- * in that, since dmasize is the buffer asked for
- * via mmap.
- */
- if (dmabuf->count > dmabuf->dmasize)
- dmabuf->count &= dmabuf->dmasize-1;
- } else {
- dmabuf->count -= diff;
- /*
- * backfill with silence and clear out the last
- * "diff" number of bytes.
- */
- if (hwptr >= diff) {
- memset(dmabuf->rawbuf + hwptr - diff,
- (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff);
- } else {
- memset(dmabuf->rawbuf,
- (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
- (unsigned)hwptr);
- memset((char *)dmabuf->rawbuf +
- dmabuf->dmasize + hwptr - diff,
- (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
- diff - hwptr);
- }
-
- if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
- "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",
- dmabuf->count));
- /*
- * buffer underrun or buffer overrun, reset the
- * count of bytes written back to 0.
- */
- if (dmabuf->count < 0)
- dmabuf->underrun = 1;
- dmabuf->count = 0;
- dmabuf->error++;
- }
- if (wake && dmabuf->count < (signed)dmabuf->dmasize / 2)
- wake_up(&dmabuf->wait);
- }
- }
- }
-}
-
-
-/* hold spinlock for the following! */
-static void cs_handle_midi(struct cs_card *card)
-{
- unsigned char ch;
- int wake;
- unsigned temp1;
-
- wake = 0;
- while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_RBE)) {
- ch = cs461x_peekBA0(card, BA0_MIDRP);
- if (card->midi.icnt < CS_MIDIINBUF) {
- card->midi.ibuf[card->midi.iwr] = ch;
- card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF;
- card->midi.icnt++;
- }
- wake = 1;
- }
- if (wake)
- wake_up(&card->midi.iwait);
- wake = 0;
- while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) {
- temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff;
- cs461x_pokeBA0(card, BA0_MIDWP,temp1);
- card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF;
- card->midi.ocnt--;
- if (card->midi.ocnt < CS_MIDIOUTBUF-16)
- wake = 1;
- }
- if (wake)
- wake_up(&card->midi.owait);
-}
-
-static irqreturn_t cs_interrupt(int irq, void *dev_id)
-{
- struct cs_card *card = (struct cs_card *)dev_id;
- /* Single channel card */
- struct cs_state *recstate = card->channel[0].state;
- struct cs_state *playstate = card->channel[1].state;
- u32 status;
-
- CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n"));
-
- spin_lock(&card->lock);
-
- status = cs461x_peekBA0(card, BA0_HISR);
-
- if ((status & 0x7fffffff) == 0) {
- cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
- spin_unlock(&card->lock);
- return IRQ_HANDLED; /* Might be IRQ_NONE.. */
- }
-
- /*
- * check for playback or capture interrupt only
- */
- if (((status & HISR_VC0) && playstate && playstate->dmabuf.ready) ||
- (((status & HISR_VC1) && recstate && recstate->dmabuf.ready))) {
- CS_DBGOUT(CS_INTERRUPT, 8, printk(
- "cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));
- cs_update_ptr(card, CS_TRUE);
- }
-
- if (status & HISR_MIDI)
- cs_handle_midi(card);
-
- /* clear 'em */
- cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
- spin_unlock(&card->lock);
- CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n"));
- return IRQ_HANDLED;
-}
-
-
-/**********************************************************************/
-
-static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct cs_card *card = file->private_data;
- ssize_t ret;
- unsigned long flags;
- unsigned ptr;
- int cnt;
-
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
- ret = 0;
- while (count > 0) {
- spin_lock_irqsave(&card->lock, flags);
- ptr = card->midi.ird;
- cnt = CS_MIDIINBUF - ptr;
- if (card->midi.icnt < cnt)
- cnt = card->midi.icnt;
- spin_unlock_irqrestore(&card->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&card->midi.iwait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
- continue;
- }
- if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt))
- return ret ? ret : -EFAULT;
- ptr = (ptr + cnt) % CS_MIDIINBUF;
- spin_lock_irqsave(&card->lock, flags);
- card->midi.ird = ptr;
- card->midi.icnt -= cnt;
- spin_unlock_irqrestore(&card->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- }
- return ret;
-}
-
-
-static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
- struct cs_card *card = file->private_data;
- ssize_t ret;
- unsigned long flags;
- unsigned ptr;
- int cnt;
-
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
- ret = 0;
- while (count > 0) {
- spin_lock_irqsave(&card->lock, flags);
- ptr = card->midi.owr;
- cnt = CS_MIDIOUTBUF - ptr;
- if (card->midi.ocnt + cnt > CS_MIDIOUTBUF)
- cnt = CS_MIDIOUTBUF - card->midi.ocnt;
- if (cnt <= 0)
- cs_handle_midi(card);
- spin_unlock_irqrestore(&card->lock, flags);
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&card->midi.owait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
- continue;
- }
- if (copy_from_user(card->midi.obuf + ptr, buffer, cnt))
- return ret ? ret : -EFAULT;
- ptr = (ptr + cnt) % CS_MIDIOUTBUF;
- spin_lock_irqsave(&card->lock, flags);
- card->midi.owr = ptr;
- card->midi.ocnt += cnt;
- spin_unlock_irqrestore(&card->lock, flags);
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- spin_lock_irqsave(&card->lock, flags);
- cs_handle_midi(card);
- spin_unlock_irqrestore(&card->lock, flags);
- }
- return ret;
-}
-
-
-static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct cs_card *card = file->private_data;
- unsigned long flags;
- unsigned int mask = 0;
-
- if (file->f_flags & FMODE_WRITE)
- poll_wait(file, &card->midi.owait, wait);
- if (file->f_flags & FMODE_READ)
- poll_wait(file, &card->midi.iwait, wait);
- spin_lock_irqsave(&card->lock, flags);
- if (file->f_flags & FMODE_READ) {
- if (card->midi.icnt > 0)
- mask |= POLLIN | POLLRDNORM;
- }
- if (file->f_flags & FMODE_WRITE) {
- if (card->midi.ocnt < CS_MIDIOUTBUF)
- mask |= POLLOUT | POLLWRNORM;
- }
- spin_unlock_irqrestore(&card->lock, flags);
- return mask;
-}
-
-
-static int cs_midi_open(struct inode *inode, struct file *file)
-{
- unsigned int minor = iminor(inode);
- struct cs_card *card = NULL;
- unsigned long flags;
- struct list_head *entry;
-
- list_for_each(entry, &cs46xx_devs) {
- card = list_entry(entry, struct cs_card, list);
- if (card->dev_midi == minor)
- break;
- }
-
- if (entry == &cs46xx_devs)
- return -ENODEV;
- if (!card) {
- CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
- "cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n"));
- return -ENODEV;
- }
-
- file->private_data = card;
- /* wait for device to become free */
- mutex_lock(&card->midi.open_mutex);
- while (card->midi.open_mode & file->f_mode) {
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&card->midi.open_mutex);
- return -EBUSY;
- }
- mutex_unlock(&card->midi.open_mutex);
- interruptible_sleep_on(&card->midi.open_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- mutex_lock(&card->midi.open_mutex);
- }
- spin_lock_irqsave(&card->midi.lock, flags);
- if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) {
- card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
- card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
- card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
- cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f); /* Enable xmit, rcv. */
- cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); /* Enable interrupts */
- }
- if (file->f_mode & FMODE_READ)
- card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
- if (file->f_mode & FMODE_WRITE)
- card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
- spin_unlock_irqrestore(&card->midi.lock, flags);
- card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));
- mutex_unlock(&card->midi.open_mutex);
- return 0;
-}
-
-
-static int cs_midi_release(struct inode *inode, struct file *file)
-{
- struct cs_card *card = file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- unsigned count, tmo;
-
- if (file->f_mode & FMODE_WRITE) {
- current->state = TASK_INTERRUPTIBLE;
- add_wait_queue(&card->midi.owait, &wait);
- for (;;) {
- spin_lock_irqsave(&card->midi.lock, flags);
- count = card->midi.ocnt;
- spin_unlock_irqrestore(&card->midi.lock, flags);
- if (count <= 0)
- break;
- if (signal_pending(current))
- break;
- if (file->f_flags & O_NONBLOCK)
- break;
- tmo = (count * HZ) / 3100;
- if (!schedule_timeout(tmo ? : 1) && tmo)
- printk(KERN_DEBUG "cs46xx: midi timed out??\n");
- }
- remove_wait_queue(&card->midi.owait, &wait);
- current->state = TASK_RUNNING;
- }
- mutex_lock(&card->midi.open_mutex);
- card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE)));
- mutex_unlock(&card->midi.open_mutex);
- wake_up(&card->midi.open_wait);
- return 0;
-}
-
-/*
- * Midi file operations struct.
- */
-static /*const*/ struct file_operations cs_midi_fops = {
- CS_OWNER CS_THIS_MODULE
- .llseek = no_llseek,
- .read = cs_midi_read,
- .write = cs_midi_write,
- .poll = cs_midi_poll,
- .open = cs_midi_open,
- .release = cs_midi_release,
-};
-
-/*
- *
- * CopySamples copies 16-bit stereo signed samples from the source to the
- * destination, possibly converting down to unsigned 8-bit and/or mono.
- * count specifies the number of output bytes to write.
- *
- * Arguments:
- *
- * dst - Pointer to a destination buffer.
- * src - Pointer to a source buffer
- * count - The number of bytes to copy into the destination buffer.
- * fmt - CS_FMT_16BIT and/or CS_FMT_STEREO bits
- * dmabuf - pointer to the dma buffer structure
- *
- * NOTES: only call this routine if the output desired is not 16 Signed Stereo
- *
- *
- */
-static void CopySamples(char *dst, char *src, int count, unsigned fmt,
- struct dmabuf *dmabuf)
-{
- s32 s32AudioSample;
- s16 *psSrc = (s16 *)src;
- s16 *psDst = (s16 *)dst;
- u8 *pucDst = (u8 *)dst;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") );
- CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
- " dst=%p src=%p count=%d fmt=0x%x\n",
- dst,src,count,fmt) );
-
- /*
- * See if the data should be output as 8-bit unsigned stereo.
- */
- if ((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
- /*
- * Convert each 16-bit signed stereo sample to 8-bit unsigned
- * stereo using rounding.
- */
- psSrc = (s16 *)src;
- count = count / 2;
- while (count--)
- *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);
- }
- /*
- * See if the data should be output at 8-bit unsigned mono.
- */
- else if (!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
- /*
- * Convert each 16-bit signed stereo sample to 8-bit unsigned
- * mono using averaging and rounding.
- */
- psSrc = (s16 *)src;
- count = count / 2;
- while (count--) {
- s32AudioSample = ((*psSrc) + (*(psSrc + 1))) / 2 + (s32)0x80;
- if (s32AudioSample > 0x7fff)
- s32AudioSample = 0x7fff;
- *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);
- psSrc += 2;
- }
- }
- /*
- * See if the data should be output at 16-bit signed mono.
- */
- else if (!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) {
- /*
- * Convert each 16-bit signed stereo sample to 16-bit signed
- * mono using averaging.
- */
- psSrc = (s16 *)src;
- count = count / 2;
- while (count--) {
- *(psDst++) = (s16)((*psSrc) + (*(psSrc + 1))) / 2;
- psSrc += 2;
- }
- }
-}
-
-/*
- * cs_copy_to_user()
- * replacement for the standard copy_to_user, to allow for a conversion from
- * 16 bit to 8 bit and from stereo to mono, if the record conversion is active.
- * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo,
- * so we convert from any of the other format combinations.
- */
-static unsigned cs_copy_to_user(
- struct cs_state *s,
- void __user *dest,
- void *hwsrc,
- unsigned cnt,
- unsigned *copied)
-{
- struct dmabuf *dmabuf = &s->dmabuf;
- void *src = hwsrc; /* default to the standard destination buffer addr */
-
- CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO
- "cs_copy_to_user()+ fmt=0x%x cnt=%d dest=%p\n",
- dmabuf->fmt,(unsigned)cnt,dest) );
-
- if (cnt > dmabuf->dmasize)
- cnt = dmabuf->dmasize;
- if (!cnt) {
- *copied = 0;
- return 0;
- }
- if (dmabuf->divisor != 1) {
- if (!dmabuf->tmpbuff) {
- *copied = cnt / dmabuf->divisor;
- return 0;
- }
-
- CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt,
- dmabuf->fmt, dmabuf);
- src = dmabuf->tmpbuff;
- cnt = cnt/dmabuf->divisor;
- }
- if (copy_to_user(dest, src, cnt)) {
- CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR
- "cs46xx: cs_copy_to_user()- fault dest=%p src=%p cnt=%d\n",
- dest,src,cnt));
- *copied = 0;
- return -EFAULT;
- }
- *copied = cnt;
- CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO
- "cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt));
- return 0;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
- the user's buffer. it is filled by the dma machine and drained by this loop. */
-static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct cs_card *card = file->private_data;
- struct cs_state *state;
- DECLARE_WAITQUEUE(wait, current);
- struct dmabuf *dmabuf;
- ssize_t ret = 0;
- unsigned long flags;
- unsigned swptr;
- int cnt;
- unsigned copied = 0;
-
- CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4,
- printk("cs46xx: cs_read()+ %zd\n",count) );
- state = card->states[0];
- if (!state)
- return -ENODEV;
- dmabuf = &state->dmabuf;
-
- if (dmabuf->mapped)
- return -ENXIO;
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
-
- mutex_lock(&state->sem);
- if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
- goto out2;
-
- add_wait_queue(&state->dmabuf.wait, &wait);
- while (count > 0) {
- while (!(card->pm.flags & CS46XX_PM_IDLE)) {
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out;
- }
- }
- spin_lock_irqsave(&state->card->lock, flags);
- swptr = dmabuf->swptr;
- cnt = dmabuf->dmasize - swptr;
- if (dmabuf->count < cnt)
- cnt = dmabuf->count;
- if (cnt <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (cnt > (count * dmabuf->divisor))
- cnt = count * dmabuf->divisor;
- if (cnt <= 0) {
- /* buffer is empty, start the dma machine and wait for data to be
- recorded */
- start_adc(state);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- mutex_unlock(&state->sem);
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out;
- }
- mutex_lock(&state->sem);
- if (dmabuf->mapped) {
- if (!ret)
- ret = -ENXIO;
- goto out;
- }
- continue;
- }
-
- CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO
- "_read() copy_to cnt=%d count=%zd ", cnt,count) );
- CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
- " .dmasize=%d .count=%d buffer=%p ret=%zd\n",
- dmabuf->dmasize,dmabuf->count,buffer,ret));
-
- if (cs_copy_to_user(state, buffer,
- (char *)dmabuf->rawbuf + swptr, cnt, &copied)) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
- swptr = (swptr + cnt) % dmabuf->dmasize;
- spin_lock_irqsave(&card->lock, flags);
- dmabuf->swptr = swptr;
- dmabuf->count -= cnt;
- spin_unlock_irqrestore(&card->lock, flags);
- count -= copied;
- buffer += copied;
- ret += copied;
- start_adc(state);
- }
-out:
- remove_wait_queue(&state->dmabuf.wait, &wait);
-out2:
- mutex_unlock(&state->sem);
- set_current_state(TASK_RUNNING);
- CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4,
- printk("cs46xx: cs_read()- %zd\n",ret) );
- return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
- the soundcard. it is drained by the dma machine and filled by this loop. */
-static ssize_t cs_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
- struct cs_card *card = file->private_data;
- struct cs_state *state;
- DECLARE_WAITQUEUE(wait, current);
- struct dmabuf *dmabuf;
- ssize_t ret;
- unsigned long flags;
- unsigned swptr;
- int cnt;
-
- CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
- printk("cs46xx: cs_write called, count = %zd\n", count) );
- state = card->states[1];
- if (!state)
- return -ENODEV;
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
- dmabuf = &state->dmabuf;
-
- mutex_lock(&state->sem);
- if (dmabuf->mapped) {
- ret = -ENXIO;
- goto out;
- }
-
- if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
- goto out;
- add_wait_queue(&state->dmabuf.wait, &wait);
- ret = 0;
-/*
-* Start the loop to read from the user's buffer and write to the dma buffer.
-* check for PM events and underrun/overrun in the loop.
-*/
- while (count > 0) {
- while (!(card->pm.flags & CS46XX_PM_IDLE)) {
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out;
- }
- }
- spin_lock_irqsave(&state->card->lock, flags);
- if (dmabuf->count < 0) {
- /* buffer underrun, we are recovering from sleep_on_timeout,
- resync hwptr and swptr */
- dmabuf->count = 0;
- dmabuf->swptr = dmabuf->hwptr;
- }
- if (dmabuf->underrun) {
- dmabuf->underrun = 0;
- dmabuf->hwptr = cs_get_dma_addr(state);
- dmabuf->swptr = dmabuf->hwptr;
- }
-
- swptr = dmabuf->swptr;
- cnt = dmabuf->dmasize - swptr;
- if (dmabuf->count + cnt > dmabuf->dmasize)
- cnt = dmabuf->dmasize - dmabuf->count;
- if (cnt <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- /* buffer is full, start the dma machine and wait for data to be
- played */
- start_dac(state);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- mutex_unlock(&state->sem);
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out;
- }
- mutex_lock(&state->sem);
- if (dmabuf->mapped) {
- if (!ret)
- ret = -ENXIO;
- goto out;
- }
- continue;
- }
- if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
- spin_lock_irqsave(&state->card->lock, flags);
- swptr = (swptr + cnt) % dmabuf->dmasize;
- dmabuf->swptr = swptr;
- dmabuf->count += cnt;
- if (dmabuf->count > dmabuf->dmasize) {
- CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk(
- "cs46xx: cs_write() d->count > dmasize - resetting\n"));
- dmabuf->count = dmabuf->dmasize;
- }
- dmabuf->endcleared = 0;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- start_dac(state);
- }
-out:
- mutex_unlock(&state->sem);
- remove_wait_queue(&state->dmabuf.wait, &wait);
- set_current_state(TASK_RUNNING);
-
- CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2,
- printk("cs46xx: cs_write()- ret=%zd\n", ret));
- return ret;
-}
-
-static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct cs_card *card = file->private_data;
- struct dmabuf *dmabuf;
- struct cs_state *state;
- unsigned long flags;
- unsigned int mask = 0;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n"));
- if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) {
- return -EINVAL;
- }
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- poll_wait(file, &dmabuf->wait, wait);
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- poll_wait(file, &dmabuf->wait, wait);
- }
- }
-
- spin_lock_irqsave(&card->lock, flags);
- cs_update_ptr(card, CS_FALSE);
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- mask |= POLLIN | POLLRDNORM;
- }
- }
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- if (dmabuf->mapped) {
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed)dmabuf->dmasize >= dmabuf->count
- + (signed)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
- }
- }
- spin_unlock_irqrestore(&card->lock, flags);
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- (0x%x) \n",
- mask));
- return mask;
-}
-
-/*
- * We let users mmap the ring buffer. Its not the real DMA buffer but
- * that side of the code is hidden in the IRQ handling. We do a software
- * emulation of DMA from a 64K or so buffer into a 2K FIFO.
- * (the hardware probably deserves a moan here but Crystal send me nice
- * toys ;)).
- */
-
-static int cs_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct cs_card *card = file->private_data;
- struct cs_state *state;
- struct dmabuf *dmabuf;
- int ret = 0;
- unsigned long size;
-
- CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=%p %s %s\n",
- file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "",
- vma->vm_flags & VM_READ ? "VM_READ" : "") );
-
- if (vma->vm_flags & VM_WRITE) {
- state = card->states[1];
- if (state) {
- CS_DBGOUT(CS_OPEN, 2, printk(
- "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
- if ((ret = prog_dmabuf(state)) != 0)
- return ret;
- }
- } else if (vma->vm_flags & VM_READ) {
- state = card->states[0];
- if (state) {
- CS_DBGOUT(CS_OPEN, 2, printk(
- "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
- if ((ret = prog_dmabuf(state)) != 0)
- return ret;
- }
- } else {
- CS_DBGOUT(CS_ERROR, 2, printk(
- "cs46xx: cs_mmap() return -EINVAL\n") );
- return -EINVAL;
- }
-
-/*
- * For now ONLY support playback, but seems like the only way to use
- * mmap() is to open an FD with RDWR, just read or just write access
- * does not function, get an error back from the kernel.
- * Also, QuakeIII opens with RDWR! So, there must be something
- * to needing read/write access mapping. So, allow read/write but
- * use the DAC only.
- */
- state = card->states[1];
- if (!state) {
- ret = -EINVAL;
- goto out;
- }
-
- mutex_lock(&state->sem);
- dmabuf = &state->dmabuf;
- if (cs4x_pgoff(vma) != 0) {
- ret = -EINVAL;
- goto out;
- }
- size = vma->vm_end - vma->vm_start;
-
- CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) );
-
- if (size > (PAGE_SIZE << dmabuf->buforder)) {
- ret = -EINVAL;
- goto out;
- }
- if (remap_pfn_range(vma, vma->vm_start,
- virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
- size, vma->vm_page_prot)) {
- ret = -EAGAIN;
- goto out;
- }
- dmabuf->mapped = 1;
-
- CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") );
-out:
- mutex_unlock(&state->sem);
- return ret;
-}
-
-static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct cs_card *card = file->private_data;
- struct cs_state *state;
- struct dmabuf *dmabuf = NULL;
- unsigned long flags;
- audio_buf_info abinfo;
- count_info cinfo;
- int val, valsave, ret;
- int mapped = 0;
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
-
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped;
- }
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped;
- }
-
-#if CSDEBUG
- printioctl(cmd);
-#endif
-
- switch (cmd) {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, p);
- case SNDCTL_DSP_RESET:
- /* FIXME: spin_lock ? */
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_dac(state);
- synchronize_irq(card->irq);
- dmabuf->ready = 0;
- resync_dma_ptrs(state);
- dmabuf->swptr = dmabuf->hwptr = 0;
- dmabuf->count = dmabuf->total_bytes = 0;
- dmabuf->blocks = 0;
- dmabuf->SGok = 0;
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_adc(state);
- synchronize_irq(card->irq);
- resync_dma_ptrs(state);
- dmabuf->ready = 0;
- dmabuf->swptr = dmabuf->hwptr = 0;
- dmabuf->count = dmabuf->total_bytes = 0;
- dmabuf->blocks = 0;
- dmabuf->SGok = 0;
- }
- }
- CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") );
- return 0;
- case SNDCTL_DSP_SYNC:
- if (file->f_mode & FMODE_WRITE)
- return drain_dac(state, file->f_flags & O_NONBLOCK);
- return 0;
- case SNDCTL_DSP_SPEED: /* set sample rate */
- if (get_user(val, p))
- return -EFAULT;
- if (val >= 0) {
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_adc(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- cs_set_adc_rate(state, val);
- cs_set_divisor(dmabuf);
- }
- }
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_dac(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- cs_set_dac_rate(state, val);
- cs_set_divisor(dmabuf);
- }
- }
- CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
- "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n",
- file->f_mode & FMODE_WRITE ? "DAC" : "",
- file->f_mode & FMODE_READ ? "ADC" : "",
- dmabuf->rate ) );
- return put_user(dmabuf->rate, p);
- }
- return put_user(0, p);
- case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_dac(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- if (val)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
- cs_set_divisor(dmabuf);
- CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
- "cs46xx: DSP_STEREO() DAC %s\n",
- (dmabuf->fmt & CS_FMT_STEREO) ?
- "STEREO":"MONO") );
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_adc(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- if (val)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
- cs_set_divisor(dmabuf);
- CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
- "cs46xx: DSP_STEREO() ADC %s\n",
- (dmabuf->fmt & CS_FMT_STEREO) ?
- "STEREO":"MONO") );
- }
- }
- return 0;
- case SNDCTL_DSP_GETBLKSIZE:
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- if ((val = prog_dmabuf(state)))
- return val;
- return put_user(dmabuf->fragsize, p);
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- if ((val = prog_dmabuf(state)))
- return val;
- return put_user(dmabuf->fragsize/dmabuf->divisor,
- p);
- }
- }
- return put_user(0, p);
- case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
- return put_user(AFMT_S16_LE | AFMT_U8, p);
- case SNDCTL_DSP_SETFMT: /* Select sample format */
- if (get_user(val, p))
- return -EFAULT;
- CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
- "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n",
- file->f_mode & FMODE_WRITE ? "DAC" : "",
- file->f_mode & FMODE_READ ? "ADC" : "",
- val == AFMT_S16_LE ? "16Bit Signed" : "",
- val == AFMT_U8 ? "8Bit Unsigned" : "") );
- valsave = val;
- if (val != AFMT_QUERY) {
- if (val==AFMT_S16_LE || val==AFMT_U8) {
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_dac(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- if (val == AFMT_S16_LE)
- dmabuf->fmt |= CS_FMT_16BIT;
- else
- dmabuf->fmt &= ~CS_FMT_16BIT;
- cs_set_divisor(dmabuf);
- if ((ret = prog_dmabuf(state)))
- return ret;
- }
- }
- if (file->f_mode & FMODE_READ) {
- val = valsave;
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_adc(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- if (val == AFMT_S16_LE)
- dmabuf->fmt |= CS_FMT_16BIT;
- else
- dmabuf->fmt &= ~CS_FMT_16BIT;
- cs_set_divisor(dmabuf);
- if ((ret = prog_dmabuf(state)))
- return ret;
- }
- }
- } else {
- CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk(
- "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n",
- valsave) );
- }
- } else {
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state)
- dmabuf = &state->dmabuf;
- } else if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state)
- dmabuf = &state->dmabuf;
- }
- }
- if (dmabuf) {
- if (dmabuf->fmt & CS_FMT_16BIT)
- return put_user(AFMT_S16_LE, p);
- else
- return put_user(AFMT_U8, p);
- }
- return put_user(0, p);
- case SNDCTL_DSP_CHANNELS:
- if (get_user(val, p))
- return -EFAULT;
- if (val != 0) {
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_dac(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- if (val > 1)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
- cs_set_divisor(dmabuf);
- if (prog_dmabuf(state))
- return 0;
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- stop_adc(state);
- dmabuf->ready = 0;
- dmabuf->SGok = 0;
- if (val > 1)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
- cs_set_divisor(dmabuf);
- if (prog_dmabuf(state))
- return 0;
- }
- }
- }
- return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
- p);
- case SNDCTL_DSP_POST:
- /*
- * There will be a longer than normal pause in the data.
- * so... do nothing, because there is nothing that we can do.
- */
- return 0;
- case SNDCTL_DSP_SUBDIVIDE:
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- if (dmabuf->subdivision)
- return -EINVAL;
- if (get_user(val, p))
- return -EFAULT;
- if (val != 1 && val != 2)
- return -EINVAL;
- dmabuf->subdivision = val;
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- if (dmabuf->subdivision)
- return -EINVAL;
- if (get_user(val, p))
- return -EFAULT;
- if (val != 1 && val != 2)
- return -EINVAL;
- dmabuf->subdivision = val;
- }
- }
- return 0;
- case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- dmabuf->ossfragshift = val & 0xffff;
- dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
- }
- }
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- dmabuf->ossfragshift = val & 0xffff;
- dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
- }
- }
- return 0;
- case SNDCTL_DSP_GETOSPACE:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(card, CS_TRUE);
- abinfo.fragsize = dmabuf->fragsize;
- abinfo.fragstotal = dmabuf->numfrag;
- /*
- * for mmap we always have total space available
- */
- if (dmabuf->mapped)
- abinfo.bytes = dmabuf->dmasize;
- else
- abinfo.bytes = dmabuf->dmasize - dmabuf->count;
-
- abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
- return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
- }
- return -ENODEV;
- case SNDCTL_DSP_GETISPACE:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(card, CS_TRUE);
- abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor;
- abinfo.bytes = dmabuf->count/dmabuf->divisor;
- abinfo.fragstotal = dmabuf->numfrag;
- abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
- return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
- }
- return -ENODEV;
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- return 0;
- case SNDCTL_DSP_GETCAPS:
- return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
- p);
- case SNDCTL_DSP_GETTRIGGER:
- val = 0;
- CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") );
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- if (dmabuf->enable & DAC_RUNNING)
- val |= PCM_ENABLE_INPUT;
- }
- }
- if (file->f_mode & FMODE_READ) {
- if (state) {
- state = card->states[0];
- dmabuf = &state->dmabuf;
- if (dmabuf->enable & ADC_RUNNING)
- val |= PCM_ENABLE_OUTPUT;
- }
- }
- CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) );
- return put_user(val, p);
- case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, p))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- if (val & PCM_ENABLE_INPUT) {
- if (!dmabuf->ready && (ret = prog_dmabuf(state)))
- return ret;
- start_adc(state);
- } else
- stop_adc(state);
- }
- }
- if (file->f_mode & FMODE_WRITE) {
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- if (val & PCM_ENABLE_OUTPUT) {
- if (!dmabuf->ready && (ret = prog_dmabuf(state)))
- return ret;
- start_dac(state);
- } else
- stop_dac(state);
- }
- }
- return 0;
- case SNDCTL_DSP_GETIPTR:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- state = card->states[0];
- if (state) {
- dmabuf = &state->dmabuf;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(card, CS_TRUE);
- cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor;
- cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift;
- cinfo.ptr = dmabuf->hwptr/dmabuf->divisor;
- spin_unlock_irqrestore(&state->card->lock, flags);
- if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- return 0;
- }
- return -ENODEV;
- case SNDCTL_DSP_GETOPTR:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(card, CS_TRUE);
- cinfo.bytes = dmabuf->total_bytes;
- if (dmabuf->mapped) {
- cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift)
- - dmabuf->blocks;
- CS_DBGOUT(CS_PARMS, 8,
- printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n",
- cinfo.bytes,cinfo.blocks,dmabuf->blocks) );
- dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift;
- } else {
- cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
- }
- cinfo.ptr = dmabuf->hwptr;
-
- CS_DBGOUT(CS_PARMS, 4, printk(
- "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n",
- cinfo.bytes,cinfo.blocks,cinfo.ptr) );
- spin_unlock_irqrestore(&state->card->lock, flags);
- if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- return 0;
- }
- return -ENODEV;
- case SNDCTL_DSP_SETDUPLEX:
- return 0;
- case SNDCTL_DSP_GETODELAY:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(card, CS_TRUE);
- val = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
- } else
- val = 0;
- return put_user(val, p);
- case SOUND_PCM_READ_RATE:
- if (file->f_mode & FMODE_READ)
- state = card->states[0];
- else
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- return put_user(dmabuf->rate, p);
- }
- return put_user(0, p);
- case SOUND_PCM_READ_CHANNELS:
- if (file->f_mode & FMODE_READ)
- state = card->states[0];
- else
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
- p);
- }
- return put_user(0, p);
- case SOUND_PCM_READ_BITS:
- if (file->f_mode & FMODE_READ)
- state = card->states[0];
- else
- state = card->states[1];
- if (state) {
- dmabuf = &state->dmabuf;
- return put_user((dmabuf->fmt & CS_FMT_16BIT) ?
- AFMT_S16_LE : AFMT_U8, p);
-
- }
- return put_user(0, p);
- case SNDCTL_DSP_MAPINBUF:
- case SNDCTL_DSP_MAPOUTBUF:
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_WRITE_FILTER:
- case SOUND_PCM_READ_FILTER:
- return -EINVAL;
- }
- return -EINVAL;
-}
-
-
-/*
- * AMP control - null AMP
- */
-
-static void amp_none(struct cs_card *card, int change)
-{
-}
-
-/*
- * Crystal EAPD mode
- */
-
-static void amp_voyetra(struct cs_card *card, int change)
-{
- /* Manage the EAPD bit on the Crystal 4297
- and the Analog AD1885 */
-
- int old = card->amplifier;
-
- card->amplifier+=change;
- if (card->amplifier && !old) {
- /* Turn the EAPD amp on */
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL,
- cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) |
- 0x8000);
- } else if(old && !card->amplifier) {
- /* Turn the EAPD amp off */
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL,
- cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- ~0x8000);
- }
-}
-
-
-/*
- * Game Theatre XP card - EGPIO[2] is used to enable the external amp.
- */
-
-static void amp_hercules(struct cs_card *card, int change)
-{
- int old = card->amplifier;
- if (!card) {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
- "cs46xx: amp_hercules() called before initialized.\n"));
- return;
- }
- card->amplifier+=change;
- if ((card->amplifier && !old) && !(hercules_egpio_disable)) {
- CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO
- "cs46xx: amp_hercules() external amp enabled\n"));
- cs461x_pokeBA0(card, BA0_EGPIODR,
- EGPIODR_GPOE2); /* enable EGPIO2 output */
- cs461x_pokeBA0(card, BA0_EGPIOPTR,
- EGPIOPTR_GPPT2); /* open-drain on output */
- } else if (old && !card->amplifier) {
- CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO
- "cs46xx: amp_hercules() external amp disabled\n"));
- cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */
- cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */
- }
-}
-
-/*
- * Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
- * whenever we need to beat on the chip.
- *
- * The original idea and code for this hack comes from David Kaiser at
- * Linuxcare. Perhaps one day Crystal will document their chips well
- * enough to make them useful.
- */
-
-static void clkrun_hack(struct cs_card *card, int change)
-{
- struct pci_dev *acpi_dev;
- u16 control;
- u8 pp;
- unsigned long port;
- int old = card->active;
-
- card->active+=change;
-
- acpi_dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
- if (acpi_dev == NULL)
- return; /* Not a thinkpad thats for sure */
-
- /* Find the control port */
- pci_read_config_byte(acpi_dev, 0x41, &pp);
- port = pp << 8;
-
- /* Read ACPI port */
- control = inw(port + 0x10);
-
- /* Flip CLKRUN off while running */
- if (!card->active && old) {
- CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
- "cs46xx: clkrun() enable clkrun - change=%d active=%d\n",
- change,card->active));
- outw(control|0x2000, port+0x10);
- } else {
- /*
- * sometimes on a resume the bit is set, so always reset the bit.
- */
- CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
- "cs46xx: clkrun() disable clkrun - change=%d active=%d\n",
- change,card->active));
- outw(control&~0x2000, port+0x10);
- }
- pci_dev_put(acpi_dev);
-}
-
-
-static int cs_open(struct inode *inode, struct file *file)
-{
- struct cs_card *card = file->private_data;
- struct cs_state *state = NULL;
- struct dmabuf *dmabuf = NULL;
- struct list_head *entry;
- unsigned int minor = iminor(inode);
- int ret = 0;
- unsigned int tmp;
-
- CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=%p %s %s\n",
- file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
- file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
-
- list_for_each(entry, &cs46xx_devs) {
- card = list_entry(entry, struct cs_card, list);
-
- if (!((card->dev_audio ^ minor) & ~0xf))
- break;
- }
- if (entry == &cs46xx_devs)
- return -ENODEV;
- if (!card) {
- CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
- "cs46xx: cs_open(): Error - unable to find audio card struct\n"));
- return -ENODEV;
- }
-
- /*
- * hardcode state[0] for capture, [1] for playback
- */
- if (file->f_mode & FMODE_READ) {
- CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
- if (card->states[0] == NULL) {
- state = card->states[0] =
- kzalloc(sizeof(struct cs_state), GFP_KERNEL);
- if (state == NULL)
- return -ENOMEM;
- mutex_init(&state->sem);
- dmabuf = &state->dmabuf;
- dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (dmabuf->pbuf == NULL) {
- kfree(state);
- card->states[0] = NULL;
- return -ENOMEM;
- }
- } else {
- state = card->states[0];
- if (state->open_mode & FMODE_READ)
- return -EBUSY;
- }
- dmabuf->channel = card->alloc_rec_pcm_channel(card);
-
- if (dmabuf->channel == NULL) {
- kfree(card->states[0]);
- card->states[0] = NULL;
- return -ENODEV;
- }
-
- /* Now turn on external AMP if needed */
- state->card = card;
- state->card->active_ctrl(state->card, 1);
- state->card->amplifier_ctrl(state->card, 1);
-
- if ((tmp = cs46xx_powerup(card, CS_POWER_ADC))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs46xx_powerup of ADC failed (0x%x)\n", tmp));
- return -EIO;
- }
-
- dmabuf->channel->state = state;
- /* initialize the virtual channel */
- state->virt = 0;
- state->magic = CS_STATE_MAGIC;
- init_waitqueue_head(&dmabuf->wait);
- mutex_init(&state->open_mutex);
- file->private_data = card;
-
- mutex_lock(&state->open_mutex);
-
- /* set default sample format. According to OSS Programmer's Guide /dev/dsp
- should be default to unsigned 8-bits, mono, with sample rate 8kHz and
- /dev/dspW will accept 16-bits sample */
-
- /* Default input is 8bit mono */
- dmabuf->fmt &= ~CS_FMT_MASK;
- dmabuf->type = CS_TYPE_ADC;
- dmabuf->ossfragshift = 0;
- dmabuf->ossmaxfrags = 0;
- dmabuf->subdivision = 0;
- cs_set_adc_rate(state, 8000);
- cs_set_divisor(dmabuf);
-
- state->open_mode |= FMODE_READ;
- mutex_unlock(&state->open_mutex);
- }
- if (file->f_mode & FMODE_WRITE) {
- CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
- if (card->states[1] == NULL) {
- state = card->states[1] =
- kzalloc(sizeof(struct cs_state), GFP_KERNEL);
- if (state == NULL)
- return -ENOMEM;
- mutex_init(&state->sem);
- dmabuf = &state->dmabuf;
- dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (dmabuf->pbuf == NULL) {
- kfree(state);
- card->states[1] = NULL;
- return -ENOMEM;
- }
- } else {
- state = card->states[1];
- if (state->open_mode & FMODE_WRITE)
- return -EBUSY;
- }
- dmabuf->channel = card->alloc_pcm_channel(card);
-
- if (dmabuf->channel == NULL) {
- kfree(card->states[1]);
- card->states[1] = NULL;
- return -ENODEV;
- }
-
- /* Now turn on external AMP if needed */
- state->card = card;
- state->card->active_ctrl(state->card, 1);
- state->card->amplifier_ctrl(state->card, 1);
-
- if ((tmp = cs46xx_powerup(card, CS_POWER_DAC))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs46xx_powerup of DAC failed (0x%x)\n", tmp));
- return -EIO;
- }
-
- dmabuf->channel->state = state;
- /* initialize the virtual channel */
- state->virt = 1;
- state->magic = CS_STATE_MAGIC;
- init_waitqueue_head(&dmabuf->wait);
- mutex_init(&state->open_mutex);
- file->private_data = card;
-
- mutex_lock(&state->open_mutex);
-
- /* set default sample format. According to OSS Programmer's Guide /dev/dsp
- should be default to unsigned 8-bits, mono, with sample rate 8kHz and
- /dev/dspW will accept 16-bits sample */
-
- /* Default output is 8bit mono. */
- dmabuf->fmt &= ~CS_FMT_MASK;
- dmabuf->type = CS_TYPE_DAC;
- dmabuf->ossfragshift = 0;
- dmabuf->ossmaxfrags = 0;
- dmabuf->subdivision = 0;
- cs_set_dac_rate(state, 8000);
- cs_set_divisor(dmabuf);
-
- state->open_mode |= FMODE_WRITE;
- mutex_unlock(&state->open_mutex);
- if ((ret = prog_dmabuf(state)))
- return ret;
- }
- CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n"));
- return nonseekable_open(inode, file);
-}
-
-static int cs_release(struct inode *inode, struct file *file)
-{
- struct cs_card *card = file->private_data;
- struct dmabuf *dmabuf;
- struct cs_state *state;
- unsigned int tmp;
- CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=%p %s %s\n",
- file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
- file->f_mode & FMODE_READ ? "FMODE_READ" : ""));
-
- if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
- return -EINVAL;
- state = card->states[1];
- if (state) {
- if ((state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE)) {
- CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n"));
- dmabuf = &state->dmabuf;
- cs_clear_tail(state);
- drain_dac(state, file->f_flags & O_NONBLOCK);
- /* stop DMA state machine and free DMA buffers/channels */
- mutex_lock(&state->open_mutex);
- stop_dac(state);
- dealloc_dmabuf(state);
- state->card->free_pcm_channel(state->card, dmabuf->channel->num);
- free_page((unsigned long)state->dmabuf.pbuf);
-
- /* we're covered by the open_mutex */
- mutex_unlock(&state->open_mutex);
- state->card->states[state->virt] = NULL;
- state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-
- if ((tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE))) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
- "cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) );
- }
-
- /* Now turn off external AMP if needed */
- state->card->amplifier_ctrl(state->card, -1);
- state->card->active_ctrl(state->card, -1);
- kfree(state);
- }
- }
-
- state = card->states[0];
- if (state) {
- if ((state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ)) {
- CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n"));
- dmabuf = &state->dmabuf;
- mutex_lock(&state->open_mutex);
- stop_adc(state);
- dealloc_dmabuf(state);
- state->card->free_pcm_channel(state->card, dmabuf->channel->num);
- free_page((unsigned long)state->dmabuf.pbuf);
-
- /* we're covered by the open_mutex */
- mutex_unlock(&state->open_mutex);
- state->card->states[state->virt] = NULL;
- state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-
- if ((tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE))) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
- "cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) );
- }
-
- /* Now turn off external AMP if needed */
- state->card->amplifier_ctrl(state->card, -1);
- state->card->active_ctrl(state->card, -1);
- kfree(state);
- }
- }
-
- CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n"));
- return 0;
-}
-
-static void printpm(struct cs_card *s)
-{
- CS_DBGOUT(CS_PM, 9, printk("pm struct:\n"));
- CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n",
- (unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue));
- CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n",
- s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue));
- CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n",
- s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue));
- CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n",
- s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue));
- CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n",
- s->pm.u32SSCR,s->pm.u32SRCSA));
- CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n",
- s->pm.u32DacASR,s->pm.u32AdcASR));
- CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n",
- s->pm.u32DacSR,s->pm.u32AdcSR));
- CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n",
- s->pm.u32MIDCR_Save));
- CS_DBGOUT(CS_PM, 9, printk("u32AC97_powerdown: 0x%x _general_purpose 0x%x\n",
- s->pm.u32AC97_powerdown,s->pm.u32AC97_general_purpose));
- CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume: 0x%x\n",
- s->pm.u32AC97_master_volume));
- CS_DBGOUT(CS_PM, 9, printk("u32AC97_headphone_volume: 0x%x\n",
- s->pm.u32AC97_headphone_volume));
- CS_DBGOUT(CS_PM, 9, printk("u32AC97_master_volume_mono: 0x%x\n",
- s->pm.u32AC97_master_volume_mono));
- CS_DBGOUT(CS_PM, 9, printk("u32AC97_pcm_out_volume: 0x%x\n",
- s->pm.u32AC97_pcm_out_volume));
- CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_play: 0x%x dmabuf_count_play: %d\n",
- s->pm.dmabuf_swptr_play,s->pm.dmabuf_count_play));
- CS_DBGOUT(CS_PM, 9, printk("dmabuf_swptr_capture: 0x%x dmabuf_count_capture: %d\n",
- s->pm.dmabuf_swptr_capture,s->pm.dmabuf_count_capture));
-
-}
-
-/****************************************************************************
-*
-* Suspend - save the ac97 regs, mute the outputs and power down the part.
-*
-****************************************************************************/
-static void cs46xx_ac97_suspend(struct cs_card *card)
-{
- int Count,i;
- struct ac97_codec *dev=card->ac97_codec[0];
- unsigned int tmp;
-
- CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n"));
-
- if (card->states[1]) {
- stop_dac(card->states[1]);
- resync_dma_ptrs(card->states[1]);
- }
- if (card->states[0]) {
- stop_adc(card->states[0]);
- resync_dma_ptrs(card->states[0]);
- }
-
- for (Count = 0x2, i = 0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE)
- && (i < CS46XX_AC97_NUMBER_RESTORE_REGS);
- Count += 2, i++) {
- card->pm.ac97[i] = cs_ac97_get(dev, BA0_AC97_RESET + Count);
- }
-/*
-* Save the ac97 volume registers as well as the current powerdown state.
-* Now, mute the all the outputs (master, headphone, and mono), as well
-* as the PCM volume, in preparation for powering down the entire part.
- card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev,
- (u8)BA0_AC97_MASTER_VOLUME);
- card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev,
- (u8)BA0_AC97_HEADPHONE_VOLUME);
- card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev,
- (u8)BA0_AC97_MASTER_VOLUME_MONO);
- card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev,
- (u8)BA0_AC97_PCM_OUT_VOLUME);
-*/
-/*
-* mute the outputs
-*/
- cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
- cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
- cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
- cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-
-/*
-* save the registers that cause pops
-*/
- card->pm.u32AC97_powerdown = (u32)cs_ac97_get(dev, (u8)AC97_POWER_CONTROL);
- card->pm.u32AC97_general_purpose = (u32)cs_ac97_get(dev, (u8)BA0_AC97_GENERAL_PURPOSE);
-/*
-* And power down everything on the AC97 codec.
-* well, for now, only power down the DAC/ADC and MIXER VREFON components.
-* trouble with removing VREF.
-*/
- if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
- CS_POWER_MIXVON, CS_TRUE))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp));
- }
-
- CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n"));
-}
-
-/****************************************************************************
-*
-* Resume - power up the part and restore its registers..
-*
-****************************************************************************/
-static void cs46xx_ac97_resume(struct cs_card *card)
-{
- int Count,i;
- struct ac97_codec *dev=card->ac97_codec[0];
-
- CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n"));
-
-/*
-* First, we restore the state of the general purpose register. This
-* contains the mic select (mic1 or mic2) and if we restore this after
-* we restore the mic volume/boost state and mic2 was selected at
-* suspend time, we will end up with a brief period of time where mic1
-* is selected with the volume/boost settings for mic2, causing
-* acoustic feedback. So we restore the general purpose register
-* first, thereby getting the correct mic selected before we restore
-* the mic volume/boost.
-*/
- cs_ac97_set(dev, (u8)BA0_AC97_GENERAL_PURPOSE,
- (u16)card->pm.u32AC97_general_purpose);
-/*
-* Now, while the outputs are still muted, restore the state of power
-* on the AC97 part.
-*/
- cs_ac97_set(dev, (u8)BA0_AC97_POWERDOWN, (u16)card->pm.u32AC97_powerdown);
- mdelay(5 * cs_laptop_wait);
-/*
-* Restore just the first set of registers, from register number
-* 0x02 to the register number that ulHighestRegToRestore specifies.
-*/
- for (Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) &&
- (i < CS46XX_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) {
- cs_ac97_set(dev, (u8)(BA0_AC97_RESET + Count), (u16)card->pm.ac97[i]);
- }
-
- /* Check if we have to init the amplifier */
- if (card->amp_init)
- card->amp_init(card);
-
- CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n"));
-}
-
-
-static int cs46xx_restart_part(struct cs_card *card)
-{
- struct dmabuf *dmabuf;
-
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk( "cs46xx: cs46xx_restart_part()+\n"));
- if (card->states[1]) {
- dmabuf = &card->states[1]->dmabuf;
- dmabuf->ready = 0;
- resync_dma_ptrs(card->states[1]);
- cs_set_divisor(dmabuf);
- if (__prog_dmabuf(card->states[1])) {
- CS_DBGOUT(CS_PM | CS_ERROR, 1,
- printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n"));
- return -1;
- }
- cs_set_dac_rate(card->states[1], dmabuf->rate);
- }
- if (card->states[0]) {
- dmabuf = &card->states[0]->dmabuf;
- dmabuf->ready = 0;
- resync_dma_ptrs(card->states[0]);
- cs_set_divisor(dmabuf);
- if (__prog_dmabuf(card->states[0])) {
- CS_DBGOUT(CS_PM | CS_ERROR, 1,
- printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n"));
- return -1;
- }
- cs_set_adc_rate(card->states[0], dmabuf->rate);
- }
- card->pm.flags |= CS46XX_PM_RESUMED;
- if (card->states[0])
- start_adc(card->states[0]);
- if (card->states[1])
- start_dac(card->states[1]);
-
- card->pm.flags |= CS46XX_PM_IDLE;
- card->pm.flags &= ~(CS46XX_PM_SUSPENDING | CS46XX_PM_SUSPENDED
- | CS46XX_PM_RESUMING | CS46XX_PM_RESUMED);
- if (card->states[0])
- wake_up(&card->states[0]->dmabuf.wait);
- if (card->states[1])
- wake_up(&card->states[1]->dmabuf.wait);
-
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk( "cs46xx: cs46xx_restart_part()-\n"));
- return 0;
-}
-
-static void cs461x_reset(struct cs_card *card);
-static void cs461x_proc_stop(struct cs_card *card);
-static int cs46xx_suspend(struct cs_card *card, pm_message_t state)
-{
- unsigned int tmp;
-
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=%p\n",
- (unsigned)card->pm.flags,card));
-/*
-* check the current state, only suspend if IDLE
-*/
- if (!(card->pm.flags & CS46XX_PM_IDLE)) {
- CS_DBGOUT(CS_PM | CS_ERROR, 2,
- printk("cs46xx: cs46xx_suspend() unable to suspend, not IDLE\n"));
- return 1;
- }
- card->pm.flags &= ~CS46XX_PM_IDLE;
- card->pm.flags |= CS46XX_PM_SUSPENDING;
-
- card->active_ctrl(card,1);
-
- tmp = cs461x_peek(card, BA1_PFIE);
- tmp &= ~0x0000f03f;
- tmp |= 0x00000010;
- cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt disable */
-
- tmp = cs461x_peek(card, BA1_CIE);
- tmp &= ~0x0000003f;
- tmp |= 0x00000011;
- cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt disable */
-
- /*
- * Stop playback DMA.
- */
- tmp = cs461x_peek(card, BA1_PCTL);
- cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
- /*
- * Stop capture DMA.
- */
- tmp = cs461x_peek(card, BA1_CCTL);
- cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
- if (card->states[1]) {
- card->pm.dmabuf_swptr_play = card->states[1]->dmabuf.swptr;
- card->pm.dmabuf_count_play = card->states[1]->dmabuf.count;
- }
- if (card->states[0]) {
- card->pm.dmabuf_swptr_capture = card->states[0]->dmabuf.swptr;
- card->pm.dmabuf_count_capture = card->states[0]->dmabuf.count;
- }
-
- cs46xx_ac97_suspend(card);
-
- /*
- * Reset the processor.
- */
- cs461x_reset(card);
-
- cs461x_proc_stop(card);
-
- /*
- * Power down the DAC and ADC. For now leave the other areas on.
- */
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, 0x0300);
-
- /*
- * Power down the PLL.
- */
- cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-
- /*
- * Turn off the Processor by turning off the software clock enable flag in
- * the clock control register.
- */
- tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE;
- cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
- card->active_ctrl(card,-1);
-
- card->pm.flags &= ~CS46XX_PM_SUSPENDING;
- card->pm.flags |= CS46XX_PM_SUSPENDED;
-
- printpm(card);
-
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk("cs46xx: cs46xx_suspend()- flags=0x%x\n",
- (unsigned)card->pm.flags));
- return 0;
-}
-
-static int cs46xx_resume(struct cs_card *card)
-{
- int i;
-
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n",
- (unsigned)card->pm.flags));
- if (!(card->pm.flags & CS46XX_PM_SUSPENDED)) {
- CS_DBGOUT(CS_PM | CS_ERROR, 2,
- printk("cs46xx: cs46xx_resume() unable to resume, not SUSPENDED\n"));
- return 1;
- }
- card->pm.flags |= CS46XX_PM_RESUMING;
- card->pm.flags &= ~CS46XX_PM_SUSPENDED;
- printpm(card);
- card->active_ctrl(card, 1);
-
- for (i = 0; i < 5; i++) {
- if (cs_hardware_init(card) != 0) {
- CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
- "cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n"));
- mdelay(10 * cs_laptop_wait);
- cs461x_reset(card);
- continue;
- }
- break;
- }
- if (i >= 4) {
- CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
- "cs46xx: cs46xx_resume()- cs_hardware_init() failed, retried %d times.\n",i));
- return 0;
- }
-
- if (cs46xx_restart_part(card)) {
- CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
- "cs46xx: cs46xx_resume(): cs46xx_restart_part() returned error\n"));
- }
-
- card->active_ctrl(card, -1);
-
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n",
- (unsigned)card->pm.flags));
- return 0;
-}
-
-static /*const*/ struct file_operations cs461x_fops = {
- CS_OWNER CS_THIS_MODULE
- .llseek = no_llseek,
- .read = cs_read,
- .write = cs_write,
- .poll = cs_poll,
- .ioctl = cs_ioctl,
- .mmap = cs_mmap,
- .open = cs_open,
- .release = cs_release,
-};
-
-/* Write AC97 codec registers */
-
-
-static u16 _cs_ac97_get(struct ac97_codec *dev, u8 reg)
-{
- struct cs_card *card = dev->private_data;
- int count,loopcnt;
- unsigned int tmp;
- u16 ret;
-
- /*
- * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
- * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97
- * 3. Write ACCTL = Control Register = 460h for initiating the write
- * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
- * 5. if DCV not cleared, break and return error
- * 6. Read ACSTS = Status Register = 464h, check VSTS bit
- */
-
- cs461x_peekBA0(card, BA0_ACSDA);
-
- /*
- * Setup the AC97 control registers on the CS461x to send the
- * appropriate command to the AC97 to perform the read.
- * ACCAD = Command Address Register = 46Ch
- * ACCDA = Command Data Register = 470h
- * ACCTL = Control Register = 460h
- * set DCV - will clear when process completed
- * set CRW - Read command
- * set VFRM - valid frame enabled
- * set ESYN - ASYNC generation enabled
- * set RSTN - ARST# inactive, AC97 codec not reset
- */
-
- cs461x_pokeBA0(card, BA0_ACCAD, reg);
- cs461x_pokeBA0(card, BA0_ACCDA, 0);
- cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
- ACCTL_VFRM | ACCTL_ESYN |
- ACCTL_RSTN);
-
-
- /*
- * Wait for the read to occur.
- */
- if (!(card->pm.flags & CS46XX_PM_IDLE))
- loopcnt = 2000;
- else
- loopcnt = 500 * cs_laptop_wait;
- loopcnt *= cs_laptop_wait;
- for (count = 0; count < loopcnt; count++) {
- /*
- * First, we want to wait for a short time.
- */
- udelay(10 * cs_laptop_wait);
- /*
- * Now, check to see if the read has completed.
- * ACCTL = 460h, DCV should be reset by now and 460h = 17h
- */
- if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV))
- break;
- }
-
- /*
- * Make sure the read completed.
- */
- if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: AC'97 read problem (ACCTL_DCV), reg = 0x%x returning 0xffff\n", reg));
- return 0xffff;
- }
-
- /*
- * Wait for the valid status bit to go active.
- */
-
- if (!(card->pm.flags & CS46XX_PM_IDLE))
- loopcnt = 2000;
- else
- loopcnt = 1000;
- loopcnt *= cs_laptop_wait;
- for (count = 0; count < loopcnt; count++) {
- /*
- * Read the AC97 status register.
- * ACSTS = Status Register = 464h
- * VSTS - Valid Status
- */
- if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_VSTS)
- break;
- udelay(10 * cs_laptop_wait);
- }
-
- /*
- * Make sure we got valid status.
- */
- if (!((tmp = cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING
- "cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n",
- reg, tmp));
- return 0xffff;
- }
-
- /*
- * Read the data returned from the AC97 register.
- * ACSDA = Status Data Register = 474h
- */
- CS_DBGOUT(CS_FUNCTION, 9, printk(KERN_INFO
- "cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n",
- reg, cs461x_peekBA0(card, BA0_ACSDA),
- cs461x_peekBA0(card, BA0_ACCAD)));
- ret = cs461x_peekBA0(card, BA0_ACSDA);
- return ret;
-}
-
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg)
-{
- u16 ret;
- struct cs_card *card = dev->private_data;
-
- spin_lock(&card->ac97_lock);
- ret = _cs_ac97_get(dev, reg);
- spin_unlock(&card->ac97_lock);
- return ret;
-}
-
-static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
-{
- struct cs_card *card = dev->private_data;
- int count;
- int val2 = 0;
-
- spin_lock(&card->ac97_lock);
-
- if (reg == AC97_CD_VOL)
- val2 = _cs_ac97_get(dev, AC97_CD_VOL);
-
- /*
- * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
- * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97
- * 3. Write ACCTL = Control Register = 460h for initiating the write
- * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
- * 5. if DCV not cleared, break and return error
- */
-
- /*
- * Setup the AC97 control registers on the CS461x to send the
- * appropriate command to the AC97 to perform the read.
- * ACCAD = Command Address Register = 46Ch
- * ACCDA = Command Data Register = 470h
- * ACCTL = Control Register = 460h
- * set DCV - will clear when process completed
- * reset CRW - Write command
- * set VFRM - valid frame enabled
- * set ESYN - ASYNC generation enabled
- * set RSTN - ARST# inactive, AC97 codec not reset
- */
- cs461x_pokeBA0(card, BA0_ACCAD, reg);
- cs461x_pokeBA0(card, BA0_ACCDA, val);
- cs461x_peekBA0(card, BA0_ACCTL);
- cs461x_pokeBA0(card, BA0_ACCTL, 0 | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
- cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
- ACCTL_ESYN | ACCTL_RSTN);
- for (count = 0; count < 1000; count++) {
- /*
- * First, we want to wait for a short time.
- */
- udelay(10 * cs_laptop_wait);
- /*
- * Now, check to see if the write has completed.
- * ACCTL = 460h, DCV should be reset by now and 460h = 07h
- */
- if (!(cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV))
- break;
- }
- /*
- * Make sure the write completed.
- */
- if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val));
- }
-
- spin_unlock(&card->ac97_lock);
-
- /*
- * Adjust power if the mixer is selected/deselected according
- * to the CD.
- *
- * IF the CD is a valid input source (mixer or direct) AND
- * the CD is not muted THEN power is needed
- *
- * We do two things. When record select changes the input to
- * add/remove the CD we adjust the power count if the CD is
- * unmuted.
- *
- * When the CD mute changes we adjust the power level if the
- * CD was a valid input.
- *
- * We also check for CD volume != 0, as the CD mute isn't
- * normally tweaked from userspace.
- */
-
- /* CD mute change ? */
-
- if (reg == AC97_CD_VOL) {
- /* Mute bit change ? */
- if ((val2^val) & 0x8000 ||
- ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) {
- /* This is a hack but its cleaner than the alternatives.
- Right now card->ac97_codec[0] might be NULL as we are
- still doing codec setup. This does an early assignment
- to avoid the problem if it occurs */
-
- if (card->ac97_codec[0] == NULL)
- card->ac97_codec[0] = dev;
-
- /* Mute on */
- if (val & 0x8000 || val == 0x1f1f)
- card->amplifier_ctrl(card, -1);
- else { /* Mute off power on */
- if (card->amp_init)
- card->amp_init(card);
- card->amplifier_ctrl(card, 1);
- }
- }
- }
-}
-
-/* OSS /dev/mixer file operation methods */
-
-static int cs_open_mixdev(struct inode *inode, struct file *file)
-{
- int i = 0;
- unsigned int minor = iminor(inode);
- struct cs_card *card = NULL;
- struct list_head *entry;
- unsigned int tmp;
-
- CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
- printk(KERN_INFO "cs46xx: cs_open_mixdev()+\n"));
-
- list_for_each(entry, &cs46xx_devs) {
- card = list_entry(entry, struct cs_card, list);
- for (i = 0; i < NR_AC97; i++)
- if (card->ac97_codec[i] != NULL &&
- card->ac97_codec[i]->dev_mixer == minor)
- goto match;
- }
- if (!card) {
- CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
- printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
- return -ENODEV;
- }
- match:
- if (!card->ac97_codec[i])
- return -ENODEV;
- file->private_data = card->ac97_codec[i];
-
- card->active_ctrl(card,1);
- if (!CS_IN_USE(&card->mixer_use_cnt)) {
- if ((tmp = cs46xx_powerup(card, CS_POWER_MIXVON))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs_open_mixdev() powerup failure (0x%x)\n", tmp));
- return -EIO;
- }
- }
- card->amplifier_ctrl(card, 1);
- CS_INC_USE_COUNT(&card->mixer_use_cnt);
- CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
- printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n"));
- return nonseekable_open(inode, file);
-}
-
-static int cs_release_mixdev(struct inode *inode, struct file *file)
-{
- unsigned int minor = iminor(inode);
- struct cs_card *card = NULL;
- struct list_head *entry;
- int i;
- unsigned int tmp;
-
- CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
- printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n"));
- list_for_each(entry, &cs46xx_devs)
- {
- card = list_entry(entry, struct cs_card, list);
- for (i = 0; i < NR_AC97; i++)
- if (card->ac97_codec[i] != NULL &&
- card->ac97_codec[i]->dev_mixer == minor)
- goto match;
- }
- if (!card) {
- CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
- printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
- return -ENODEV;
- }
-match:
- if (!CS_DEC_AND_TEST(&card->mixer_use_cnt)) {
- CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
- printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n"));
- card->active_ctrl(card, -1);
- card->amplifier_ctrl(card, -1);
- return 0;
- }
-/*
-* ok, no outstanding mixer opens, so powerdown.
-*/
- if ((tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n", tmp));
- card->active_ctrl(card, -1);
- card->amplifier_ctrl(card, -1);
- return -EIO;
- }
- card->active_ctrl(card, -1);
- card->amplifier_ctrl(card, -1);
- CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
- printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n"));
- return 0;
-}
-
-static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct ac97_codec *codec = file->private_data;
- struct cs_card *card = NULL;
- struct list_head *entry;
- unsigned long __user *p = (long __user *)arg;
-#if CSDEBUG_INTERFACE
- int val;
-
- if ( (cmd == SOUND_MIXER_CS_GETDBGMASK) ||
- (cmd == SOUND_MIXER_CS_SETDBGMASK) ||
- (cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
- (cmd == SOUND_MIXER_CS_SETDBGLEVEL) ||
- (cmd == SOUND_MIXER_CS_APM)) {
- switch (cmd) {
- case SOUND_MIXER_CS_GETDBGMASK:
- return put_user(cs_debugmask, p);
- case SOUND_MIXER_CS_GETDBGLEVEL:
- return put_user(cs_debuglevel, p);
- case SOUND_MIXER_CS_SETDBGMASK:
- if (get_user(val, p))
- return -EFAULT;
- cs_debugmask = val;
- return 0;
- case SOUND_MIXER_CS_SETDBGLEVEL:
- if (get_user(val, p))
- return -EFAULT;
- cs_debuglevel = val;
- return 0;
- case SOUND_MIXER_CS_APM:
- if (get_user(val, p))
- return -EFAULT;
- if (val == CS_IOCTL_CMD_SUSPEND) {
- list_for_each(entry, &cs46xx_devs) {
- card = list_entry(entry, struct cs_card, list);
- cs46xx_suspend(card, PMSG_ON);
- }
-
- } else if (val == CS_IOCTL_CMD_RESUME) {
- list_for_each(entry, &cs46xx_devs) {
- card = list_entry(entry, struct cs_card, list);
- cs46xx_resume(card);
- }
- } else {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
- "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n",
- val));
- }
- return 0;
- default:
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
- "cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n"));
- return 0;
- }
- }
-#endif
- return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static /*const*/ struct file_operations cs_mixer_fops = {
- CS_OWNER CS_THIS_MODULE
- .llseek = no_llseek,
- .ioctl = cs_ioctl_mixdev,
- .open = cs_open_mixdev,
- .release = cs_release_mixdev,
-};
-
-/* AC97 codec initialisation. */
-static int __init cs_ac97_init(struct cs_card *card)
-{
- int num_ac97 = 0;
- int ready_2nd = 0;
- struct ac97_codec *codec;
- u16 eid;
-
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_ac97_init()+\n") );
-
- for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
- if ((codec = ac97_alloc_codec()) == NULL)
- return -ENOMEM;
-
- /* initialize some basic codec information, other fields will be filled
- in ac97_probe_codec */
- codec->private_data = card;
- codec->id = num_ac97;
-
- codec->codec_read = cs_ac97_get;
- codec->codec_write = cs_ac97_set;
-
- if (ac97_probe_codec(codec) == 0) {
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_ac97_init()- codec number %d not found\n",
- num_ac97) );
- card->ac97_codec[num_ac97] = NULL;
- break;
- }
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_ac97_init() found codec %d\n",num_ac97));
-
- eid = cs_ac97_get(codec, AC97_EXTENDED_ID);
-
- if (eid == 0xFFFF) {
- printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97);
- ac97_release_codec(codec);
- break;
- }
-
- card->ac97_features = eid;
-
- if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) {
- printk(KERN_ERR "cs46xx: couldn't register mixer!\n");
- ac97_release_codec(codec);
- break;
- }
- card->ac97_codec[num_ac97] = codec;
-
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_ac97_init() ac97_codec[%d] set to %p\n",
- (unsigned int)num_ac97,
- codec));
- /* if there is no secondary codec at all, don't probe any more */
- if (!ready_2nd)
- {
- num_ac97 += 1;
- break;
- }
- }
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_ac97_init()- %d\n", (unsigned int)num_ac97));
- return num_ac97;
-}
-
-/*
- * load the static image into the DSP
- */
-#include "cs461x_image.h"
-static void cs461x_download_image(struct cs_card *card)
-{
- unsigned i, j, temp1, temp2, offset, count;
- unsigned char __iomem *pBA1 = ioremap(card->ba1_addr, 0x40000);
- for (i = 0; i < CLEAR__COUNT; i++) {
- offset = ClrStat[i].BA1__DestByteOffset;
- count = ClrStat[i].BA1__SourceSize;
- for (temp1 = offset; temp1 < (offset + count); temp1 += 4)
- writel(0, pBA1+temp1);
- }
-
- for (i = 0; i < FILL__COUNT; i++) {
- temp2 = FillStat[i].Offset;
- for (j = 0; j < (FillStat[i].Size) / 4; j++) {
- temp1 = (FillStat[i]).pFill[j];
- writel(temp1, pBA1+temp2 + j * 4);
- }
- }
- iounmap(pBA1);
-}
-
-/*
- * Chip reset
- */
-
-static void cs461x_reset(struct cs_card *card)
-{
- int idx;
-
- /*
- * Write the reset bit of the SP control register.
- */
- cs461x_poke(card, BA1_SPCR, SPCR_RSTSP);
-
- /*
- * Write the control register.
- */
- cs461x_poke(card, BA1_SPCR, SPCR_DRQEN);
-
- /*
- * Clear the trap registers.
- */
- for (idx = 0; idx < 8; idx++) {
- cs461x_poke(card, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
- cs461x_poke(card, BA1_TWPR, 0xFFFF);
- }
- cs461x_poke(card, BA1_DREG, 0);
-
- /*
- * Set the frame timer to reflect the number of cycles per frame.
- */
- cs461x_poke(card, BA1_FRMT, 0xadf);
-}
-
-static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type)
-{
- int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0;
- unsigned int tmp;
-
- /*
- * See if the devices are powered down. If so, we must power them up first
- * or they will not respond.
- */
- if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) {
- cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE);
- powerdown1 = 1;
- }
-
- /*
- * We want to clear out the serial port FIFOs so we don't end up playing
- * whatever random garbage happens to be in them. We fill the sample FIFOS
- * with zero (silence).
- */
- cs461x_pokeBA0(card, BA0_SERBWP, 0);
-
- /*
- * Check for which FIFO locations to clear, if we are currently
- * playing or capturing then we don't want to put in 128 bytes of
- * "noise".
- */
- if (type & CS_TYPE_DAC) {
- startfifo = 128;
- endfifo = 256;
- }
- if (type & CS_TYPE_ADC) {
- startfifo = 0;
- if (!endfifo)
- endfifo = 128;
- }
- /*
- * Fill sample FIFO locations (256 locations total).
- */
- for (idx = startfifo; idx < endfifo; idx++) {
- /*
- * Make sure the previous FIFO write operation has completed.
- */
- for (loop = 0; loop < 5; loop++) {
- udelay(50);
- if (!(cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY))
- break;
- }
- if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) {
- if (powerdown1)
- cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
- }
- /*
- * Write the serial port FIFO index.
- */
- cs461x_pokeBA0(card, BA0_SERBAD, idx);
- /*
- * Tell the serial port to load the new value into the FIFO location.
- */
- cs461x_pokeBA0(card, BA0_SERBCM, SERBCM_WRC);
- }
- /*
- * Now, if we powered up the devices, then power them back down again.
- * This is kinda ugly, but should never happen.
- */
- if (powerdown1)
- cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-}
-
-
-static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag)
-{
- int count;
- unsigned int tmp=0,muted=0;
-
- CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
- "cs46xx: cs461x_powerdown()+ type=0x%x\n",type));
- if (!cs_powerdown && !suspendflag) {
- CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO
- "cs46xx: cs461x_powerdown() DISABLED exiting\n"));
- return 0;
- }
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO
- "cs46xx: cs461x_powerdown() powerdown reg=0x%x\n",tmp));
-/*
-* if powering down only the VREF, and not powering down the DAC/ADC,
-* then do not power down the VREF, UNLESS both the DAC and ADC are not
-* currently powered down. If powering down DAC and ADC, then
-* it is possible to power down the VREF (ON).
-*/
- if (((type & CS_POWER_MIXVON) &&
- (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC))))
- &&
- ((tmp & CS_AC97_POWER_CONTROL_ADC_ON) ||
- (tmp & CS_AC97_POWER_CONTROL_DAC_ON))) {
- CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO
- "cs46xx: cs461x_powerdown()- 0 unable to powerdown. tmp=0x%x\n",tmp));
- return 0;
- }
-/*
-* for now, always keep power to the mixer block.
-* not sure why it's a problem but it seems to be if we power off.
-*/
- type &= ~CS_POWER_MIXVON;
- type &= ~CS_POWER_MIXVOFF;
-
- /*
- * Power down indicated areas.
- */
- if (type & CS_POWER_MIXVOFF) {
-
- CS_DBGOUT(CS_FUNCTION, 4,
- printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVOFF\n"));
- /*
- * Power down the MIXER (VREF ON) on the AC97 card.
- */
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp |= CS_AC97_POWER_CONTROL_MIXVOFF;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVOFF_ON))
- break;
- }
-
- /*
- * Check the status..
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerdown MIXVOFF failed\n"));
- return 1;
- }
- }
- }
- if (type & CS_POWER_MIXVON) {
-
- CS_DBGOUT(CS_FUNCTION, 4,
- printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVON\n"));
- /*
- * Power down the MIXER (VREF ON) on the AC97 card.
- */
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp |= CS_AC97_POWER_CONTROL_MIXVON;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVON_ON))
- break;
- }
-
- /*
- * Check the status..
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVON_ON) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerdown MIXVON failed\n"));
- return 1;
- }
- }
- }
- if (type & CS_POWER_ADC) {
- /*
- * Power down the ADC on the AC97 card.
- */
- CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ ADC\n"));
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp |= CS_AC97_POWER_CONTROL_ADC;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
-
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_ADC_ON))
- break;
- }
-
- /*
- * Check the status..
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_ADC_ON) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerdown ADC failed\n"));
- return 1;
- }
- }
- }
- if (type & CS_POWER_DAC) {
- /*
- * Power down the DAC on the AC97 card.
- */
-
- CS_DBGOUT(CS_FUNCTION, 4,
- printk(KERN_INFO "cs46xx: cs461x_powerdown()+ DAC\n"));
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp |= CS_AC97_POWER_CONTROL_DAC;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_DAC_ON))
- break;
- }
-
- /*
- * Check the status..
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_DAC_ON) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerdown DAC failed\n"));
- return 1;
- }
- }
- }
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (muted)
- cs_mute(card, CS_FALSE);
- CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
- "cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp));
- return 0;
-}
-
-static int cs46xx_powerup(struct cs_card *card, unsigned int type)
-{
- int count;
- unsigned int tmp = 0, muted = 0;
-
- CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO
- "cs46xx: cs46xx_powerup()+ type=0x%x\n",type));
- /*
- * check for VREF and powerup if need to.
- */
- if (type & CS_POWER_MIXVON)
- type |= CS_POWER_MIXVOFF;
- if (type & (CS_POWER_DAC | CS_POWER_ADC))
- type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF;
-
- /*
- * Power up indicated areas.
- */
- if (type & CS_POWER_MIXVOFF) {
-
- CS_DBGOUT(CS_FUNCTION, 4,
- printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVOFF\n"));
- /*
- * Power up the MIXER (VREF ON) on the AC97 card.
- */
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVOFF_ON)
- break;
- }
-
- /*
- * Check the status..
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerup MIXVOFF failed\n"));
- return 1;
- }
- }
- }
- if(type & CS_POWER_MIXVON) {
-
- CS_DBGOUT(CS_FUNCTION, 4,
- printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVON\n"));
- /*
- * Power up the MIXER (VREF ON) on the AC97 card.
- */
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp &= ~CS_AC97_POWER_CONTROL_MIXVON;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVON_ON)
- break;
- }
-
- /*
- * Check the status..
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_MIXVON_ON)) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerup MIXVON failed\n"));
- return 1;
- }
- }
- }
- if (type & CS_POWER_ADC) {
- /*
- * Power up the ADC on the AC97 card.
- */
- CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ ADC\n"));
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp &= ~CS_AC97_POWER_CONTROL_ADC;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
-
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_ADC_ON)
- break;
- }
-
- /*
- * Check the status..
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_ADC_ON)) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerup ADC failed\n"));
- return 1;
- }
- }
- }
- if (type & CS_POWER_DAC) {
- /*
- * Power up the DAC on the AC97 card.
- */
-
- CS_DBGOUT(CS_FUNCTION, 4,
- printk(KERN_INFO "cs46xx: cs46xx_powerup()+ DAC\n"));
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) {
- if (!muted) {
- cs_mute(card, CS_TRUE);
- muted = 1;
- }
- tmp &= ~CS_AC97_POWER_CONTROL_DAC;
- cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
- /*
- * Now, we wait until we sample a ready state.
- */
- for (count = 0; count < 32; count++) {
- /*
- * First, lets wait a short while to let things settle out a
- * bit, and to prevent retrying the read too quickly.
- */
- udelay(500);
-
- /*
- * Read the current state of the power control register.
- */
- if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_DAC_ON)
- break;
- }
-
- /*
- * Check the status..
- */
- if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
- CS_AC97_POWER_CONTROL_DAC_ON)) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING
- "cs46xx: powerup DAC failed\n"));
- return 1;
- }
- }
- }
- tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
- if (muted)
- cs_mute(card, CS_FALSE);
- CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
- "cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp));
- return 0;
-}
-
-static void cs461x_proc_start(struct cs_card *card)
-{
- int cnt;
-
- /*
- * Set the frame timer to reflect the number of cycles per frame.
- */
- cs461x_poke(card, BA1_FRMT, 0xadf);
- /*
- * Turn on the run, run at frame, and DMA enable bits in the local copy of
- * the SP control register.
- */
- cs461x_poke(card, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
- /*
- * Wait until the run at frame bit resets itself in the SP control
- * register.
- */
- for (cnt = 0; cnt < 25; cnt++) {
- udelay(50);
- if (!(cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR))
- break;
- }
-
- if (cs461x_peek(card, BA1_SPCR) & SPCR_RUNFR)
- printk(KERN_WARNING "cs46xx: SPCR_RUNFR never reset\n");
-}
-
-static void cs461x_proc_stop(struct cs_card *card)
-{
- /*
- * Turn off the run, run at frame, and DMA enable bits in the local copy of
- * the SP control register.
- */
- cs461x_poke(card, BA1_SPCR, 0);
-}
-
-static int cs_hardware_init(struct cs_card *card)
-{
- unsigned long end_time;
- unsigned int tmp,count;
-
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_hardware_init()+\n") );
- /*
- * First, blast the clock control register to zero so that the PLL starts
- * out in a known state, and blast the master serial port control register
- * to zero so that the serial ports also start out in a known state.
- */
- cs461x_pokeBA0(card, BA0_CLKCR1, 0);
- cs461x_pokeBA0(card, BA0_SERMC1, 0);
-
- /*
- * If we are in AC97 mode, then we must set the part to a host controlled
- * AC-link. Otherwise, we won't be able to bring up the link.
- */
- cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 card */
- /* cs461x_pokeBA0(card, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); */ /* 2.00 card */
-
- /*
- * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
- * spec) and then drive it high. This is done for non AC97 modes since
- * there might be logic external to the CS461x that uses the ARST# line
- * for a reset.
- */
- cs461x_pokeBA0(card, BA0_ACCTL, 1);
- udelay(50);
- cs461x_pokeBA0(card, BA0_ACCTL, 0);
- udelay(50);
- cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_RSTN);
-
- /*
- * The first thing we do here is to enable sync generation. As soon
- * as we start receiving bit clock, we'll start producing the SYNC
- * signal.
- */
- cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
-
- /*
- * Now wait for a short while to allow the AC97 part to start
- * generating bit clock (so we don't try to start the PLL without an
- * input clock).
- */
- mdelay(5 * cs_laptop_wait); /* 1 should be enough ?? (and pigs might fly) */
-
- /*
- * Set the serial port timing configuration, so that
- * the clock control circuit gets its clock from the correct place.
- */
- cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97);
-
- /*
- * The part seems to not be ready for a while after a resume.
- * so, if we are resuming, then wait for 700 mils. Note that 600 mils
- * is not enough for some platforms! tested on an IBM Thinkpads and
- * reference cards.
- */
- if (!(card->pm.flags & CS46XX_PM_IDLE))
- mdelay(initdelay);
- /*
- * Write the selected clock control setup to the hardware. Do not turn on
- * SWCE yet (if requested), so that the devices clocked by the output of
- * PLL are not clocked until the PLL is stable.
- */
- cs461x_pokeBA0(card, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
- cs461x_pokeBA0(card, BA0_PLLM, 0x3a);
- cs461x_pokeBA0(card, BA0_CLKCR2, CLKCR2_PDIVS_8);
-
- /*
- * Power up the PLL.
- */
- cs461x_pokeBA0(card, BA0_CLKCR1, CLKCR1_PLLP);
-
- /*
- * Wait until the PLL has stabilized.
- */
- mdelay(5 * cs_laptop_wait); /* Again 1 should be enough ?? */
-
- /*
- * Turn on clocking of the core so that we can setup the serial ports.
- */
- tmp = cs461x_peekBA0(card, BA0_CLKCR1) | CLKCR1_SWCE;
- cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
- /*
- * Fill the serial port FIFOs with silence.
- */
- cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC);
-
- /*
- * Set the serial port FIFO pointer to the first sample in the FIFO.
- */
- /* cs461x_pokeBA0(card, BA0_SERBSP, 0); */
-
- /*
- * Write the serial port configuration to the part. The master
- * enable bit is not set until all other values have been written.
- */
- cs461x_pokeBA0(card, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
- cs461x_pokeBA0(card, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
- cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
-
-
- mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */
-
-/*
-* If we are resuming under 2.2.x then we cannot schedule a timeout,
-* so just spin the CPU.
-*/
- if (card->pm.flags & CS46XX_PM_IDLE) {
- /*
- * Wait for the card ready signal from the AC97 card.
- */
- end_time = jiffies + 3 * (HZ >> 2);
- do {
- /*
- * Read the AC97 status register to see if we've seen a CODEC READY
- * signal from the AC97 card.
- */
- if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)
- break;
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(1);
- } while (time_before(jiffies, end_time));
- } else {
- for (count = 0; count < 100; count++) {
- // First, we want to wait for a short time.
- udelay(25 * cs_laptop_wait);
-
- if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)
- break;
- }
- }
-
- /*
- * Make sure CODEC is READY.
- */
- if (!(cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY)) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING
- "cs46xx: create - never read card ready from AC'97\n"));
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING
- "cs46xx: probably not a bug, try using the CS4232 driver,\n"));
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_WARNING
- "cs46xx: or turn off any automatic Power Management support in the BIOS.\n"));
- return -EIO;
- }
-
- /*
- * Assert the vaid frame signal so that we can start sending commands
- * to the AC97 card.
- */
- cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
-
- if (card->pm.flags & CS46XX_PM_IDLE) {
- /*
- * Wait until we've sampled input slots 3 and 4 as valid, meaning that
- * the card is pumping ADC data across the AC-link.
- */
- end_time = jiffies + 3 * (HZ >> 2);
- do {
- /*
- * Read the input slot valid register and see if input slots 3 and
- * 4 are valid yet.
- */
- if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
- break;
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(1);
- } while (time_before(jiffies, end_time));
- } else {
- for (count = 0; count < 100; count++) {
- // First, we want to wait for a short time.
- udelay(25 * cs_laptop_wait);
-
- if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
- break;
- }
- }
- /*
- * Make sure input slots 3 and 4 are valid. If not, then return
- * an error.
- */
- if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) {
- printk(KERN_WARNING "cs46xx: create - never read ISV3 & ISV4 from AC'97\n");
- return -EIO;
- }
-
- /*
- * Now, assert valid frame and the slot 3 and 4 valid bits. This will
- * commense the transfer of digital audio data to the AC97 card.
- */
- cs461x_pokeBA0(card, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
-
- /*
- * Turn off the Processor by turning off the software clock enable flag in
- * the clock control register.
- */
- /* tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE; */
- /* cs461x_pokeBA0(card, BA0_CLKCR1, tmp); */
-
- /*
- * Reset the processor.
- */
- cs461x_reset(card);
-
- /*
- * Download the image to the processor.
- */
-
- cs461x_download_image(card);
-
- /*
- * Stop playback DMA.
- */
- tmp = cs461x_peek(card, BA1_PCTL);
- card->pctl = tmp & 0xffff0000;
- cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
- /*
- * Stop capture DMA.
- */
- tmp = cs461x_peek(card, BA1_CCTL);
- card->cctl = tmp & 0x0000ffff;
- cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
- /* initialize AC97 codec and register /dev/mixer */
- if (card->pm.flags & CS46XX_PM_IDLE) {
- if (cs_ac97_init(card) <= 0) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs_ac97_init() failure\n"));
- return -EIO;
- }
- } else {
- cs46xx_ac97_resume(card);
- }
-
- cs461x_proc_start(card);
-
- /*
- * Enable interrupts on the part.
- */
- cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);
-
- tmp = cs461x_peek(card, BA1_PFIE);
- tmp &= ~0x0000f03f;
- cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt enable */
-
- tmp = cs461x_peek(card, BA1_CIE);
- tmp &= ~0x0000003f;
- tmp |= 0x00000001;
- cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt enable */
-
- /*
- * If IDLE then Power down the part. We will power components up
- * when we need them.
- */
- if (card->pm.flags & CS46XX_PM_IDLE) {
- if (!cs_powerdown) {
- if ((tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
- CS_POWER_MIXVON))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) );
- return -EIO;
- }
- } else {
- if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
- CS_POWER_MIXVON, CS_FALSE))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
- return -EIO;
- }
- }
- }
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
- "cs46xx: cs_hardware_init()- 0\n"));
- return 0;
-}
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
- until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-
-/*
- * Card subid table
- */
-
-struct cs_card_type
-{
- u16 vendor;
- u16 id;
- char *name;
- void (*amp)(struct cs_card *, int);
- void (*amp_init)(struct cs_card *);
- void (*active)(struct cs_card *, int);
-};
-
-static struct cs_card_type cards[] = {
- {
- .vendor = 0x1489,
- .id = 0x7001,
- .name = "Genius Soundmaker 128 value",
- .amp = amp_none,
- },
- {
- .vendor = 0x5053,
- .id = 0x3357,
- .name = "Voyetra",
- .amp = amp_voyetra,
- },
- {
- .vendor = 0x1071,
- .id = 0x6003,
- .name = "Mitac MI6020/21",
- .amp = amp_voyetra,
- },
- {
- .vendor = 0x14AF,
- .id = 0x0050,
- .name = "Hercules Game Theatre XP",
- .amp = amp_hercules,
- },
- {
- .vendor = 0x1681,
- .id = 0x0050,
- .name = "Hercules Game Theatre XP",
- .amp = amp_hercules,
- },
- {
- .vendor = 0x1681,
- .id = 0x0051,
- .name = "Hercules Game Theatre XP",
- .amp = amp_hercules,
- },
- {
- .vendor = 0x1681,
- .id = 0x0052,
- .name = "Hercules Game Theatre XP",
- .amp = amp_hercules,
- },
- {
- .vendor = 0x1681,
- .id = 0x0053,
- .name = "Hercules Game Theatre XP",
- .amp = amp_hercules,
- },
- {
- .vendor = 0x1681,
- .id = 0x0054,
- .name = "Hercules Game Theatre XP",
- .amp = amp_hercules,
- },
- {
- .vendor = 0x1681,
- .id = 0xa010,
- .name = "Hercules Fortissimo II",
- .amp = amp_none,
- },
- /* Not sure if the 570 needs the clkrun hack */
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .id = 0x0132,
- .name = "Thinkpad 570",
- .amp = amp_none,
- .active = clkrun_hack,
- },
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .id = 0x0153,
- .name = "Thinkpad 600X/A20/T20",
- .amp = amp_none,
- .active = clkrun_hack,
- },
- {
- .vendor = PCI_VENDOR_ID_IBM,
- .id = 0x1010,
- .name = "Thinkpad 600E (unsupported)",
- },
- {
- .name = "Card without SSID set",
- },
- { 0, },
-};
-
-MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <pcaudio@crystal.cirrus.com>");
-MODULE_DESCRIPTION("Crystal SoundFusion Audio Support");
-MODULE_LICENSE("GPL");
-
-static const char cs46xx_banner[] = KERN_INFO "Crystal 4280/46xx + AC97 Audio, version " CS46XX_MAJOR_VERSION "." CS46XX_MINOR_VERSION "." CS46XX_ARCH ", " __TIME__ " " __DATE__ "\n";
-static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n";
-
-static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pciid)
-{
- int i, j;
- u16 ss_card, ss_vendor;
- struct cs_card *card;
- dma_addr_t dma_mask;
- struct cs_card_type *cp = &cards[0];
-
- CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
- printk(KERN_INFO "cs46xx: probe()+\n"));
-
- dma_mask = 0xffffffff; /* this enables playback and recording */
- if (pci_enable_device(pci_dev)) {
- CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
- "cs46xx: pci_enable_device() failed\n"));
- return -1;
- }
- if (!RSRCISMEMORYREGION(pci_dev, 0) ||
- !RSRCISMEMORYREGION(pci_dev, 1)) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
- "cs46xx: probe()- Memory region not assigned\n"));
- return -1;
- }
- if (pci_dev->irq == 0) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
- "cs46xx: probe() IRQ not assigned\n"));
- return -1;
- }
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
- CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
- "cs46xx: probe() architecture does not support 32bit PCI busmaster DMA\n"));
- return -1;
- }
- pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
- pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card);
-
- if ((card = kzalloc(sizeof(struct cs_card), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "cs46xx: out of memory\n");
- return -ENOMEM;
- }
- card->ba0_addr = RSRCADDRESS(pci_dev, 0);
- card->ba1_addr = RSRCADDRESS(pci_dev, 1);
- card->pci_dev = pci_dev;
- card->irq = pci_dev->irq;
- card->magic = CS_CARD_MAGIC;
- spin_lock_init(&card->lock);
- spin_lock_init(&card->ac97_lock);
-
- pci_set_master(pci_dev);
-
- printk(cs46xx_banner);
- printk(KERN_INFO "cs46xx: Card found at 0x%08lx and 0x%08lx, IRQ %d\n",
- card->ba0_addr, card->ba1_addr, card->irq);
-
- card->alloc_pcm_channel = cs_alloc_pcm_channel;
- card->alloc_rec_pcm_channel = cs_alloc_rec_pcm_channel;
- card->free_pcm_channel = cs_free_pcm_channel;
- card->amplifier_ctrl = amp_none;
- card->active_ctrl = amp_none;
-
- while (cp->name)
- {
- if (cp->vendor == ss_vendor && cp->id == ss_card) {
- card->amplifier_ctrl = cp->amp;
- if (cp->active)
- card->active_ctrl = cp->active;
- if (cp->amp_init)
- card->amp_init = cp->amp_init;
- break;
- }
- cp++;
- }
- if (cp->name == NULL) {
- printk(KERN_INFO "cs46xx: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
- ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
- } else {
- printk(KERN_INFO "cs46xx: %s (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
- cp->name, ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
- }
-
- if (card->amplifier_ctrl == NULL) {
- card->amplifier_ctrl = amp_none;
- card->active_ctrl = clkrun_hack;
- }
-
- if (external_amp == 1) {
- printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n");
- card->amplifier_ctrl = amp_voyetra;
- }
-
- if (thinkpad == 1) {
- printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n");
- card->active_ctrl = clkrun_hack;
- }
-/*
-* The thinkpads don't work well without runtime updating on their kernel
-* delay values (or any laptop with variable CPU speeds really).
-* so, just to be safe set the init delay to 2100. Eliminates
-* failures on T21 Thinkpads. remove this code when the udelay
-* and mdelay kernel code is replaced by a pm timer, or the delays
-* work well for battery and/or AC power both.
-*/
- if (card->active_ctrl == clkrun_hack) {
- initdelay = 2100;
- cs_laptop_wait = 5;
- }
- if ((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) {
-/*
-* for some currently unknown reason, powering down the DAC and ADC component
-* blocks on thinkpads causes some funky behavior... distoorrrtion and ac97
-* codec access problems. probably the serial clock becomes unsynced.
-* added code to sync the chips back up, but only helped about 70% the time.
-*/
- cs_powerdown = 0;
- }
- if (powerdown == 0)
- cs_powerdown = 0;
- card->active_ctrl(card, 1);
-
- /* claim our iospace and irq */
-
- card->ba0 = ioremap_nocache(card->ba0_addr, CS461X_BA0_SIZE);
- card->ba1.name.data0 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
- card->ba1.name.data1 = ioremap_nocache(card->ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
- card->ba1.name.pmem = ioremap_nocache(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
- card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
-
- CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO
- "cs46xx: card=%p card->ba0=%p\n",card,card->ba0) );
- CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO
- "cs46xx: card->ba1=%p %p %p %p\n",
- card->ba1.name.data0,
- card->ba1.name.data1,
- card->ba1.name.pmem,
- card->ba1.name.reg) );
-
- if (card->ba0 == 0 || card->ba1.name.data0 == 0 ||
- card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 ||
- card->ba1.name.reg == 0)
- goto fail2;
-
- if (request_irq(card->irq, &cs_interrupt, IRQF_SHARED, "cs46xx", card)) {
- printk(KERN_ERR "cs46xx: unable to allocate irq %d\n", card->irq);
- goto fail2;
- }
- /* register /dev/dsp */
- if ((card->dev_audio = register_sound_dsp(&cs461x_fops, -1)) < 0) {
- printk(KERN_ERR "cs46xx: unable to register dsp\n");
- goto fail;
- }
-
- /* register /dev/midi */
- if ((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0)
- printk(KERN_ERR "cs46xx: unable to register midi\n");
-
- card->pm.flags |= CS46XX_PM_IDLE;
- for (i = 0; i < 5; i++) {
- if (cs_hardware_init(card) != 0) {
- CS_DBGOUT(CS_ERROR, 4, printk(
- "cs46xx: ERROR in cs_hardware_init()... retrying\n"));
- for (j = 0; j < NR_AC97; j++)
- if (card->ac97_codec[j] != NULL) {
- unregister_sound_mixer(card->ac97_codec[j]->dev_mixer);
- ac97_release_codec(card->ac97_codec[j]);
- }
- mdelay(10 * cs_laptop_wait);
- continue;
- }
- break;
- }
- if(i >= 4) {
- CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
- "cs46xx: cs46xx_probe()- cs_hardware_init() failed, retried %d times.\n",i));
- unregister_sound_dsp(card->dev_audio);
- if (card->dev_midi)
- unregister_sound_midi(card->dev_midi);
- goto fail;
- }
-
- init_waitqueue_head(&card->midi.open_wait);
- mutex_init(&card->midi.open_mutex);
- init_waitqueue_head(&card->midi.iwait);
- init_waitqueue_head(&card->midi.owait);
- cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST);
- cs461x_pokeBA0(card, BA0_MIDCR, 0);
-
- /*
- * Check if we have to init the amplifier, but probably already done
- * since the CD logic in the ac97 init code will turn on the ext amp.
- */
- if (cp->amp_init)
- cp->amp_init(card);
- card->active_ctrl(card, -1);
-
- PCI_SET_DRIVER_DATA(pci_dev, card);
- PCI_SET_DMA_MASK(pci_dev, dma_mask);
- list_add(&card->list, &cs46xx_devs);
-
- CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n",
- (unsigned)card->pm.flags,card));
-
- CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
- "cs46xx: probe()- device allocated successfully\n"));
- return 0;
-
-fail:
- free_irq(card->irq, card);
-fail2:
- if (card->ba0)
- iounmap(card->ba0);
- if (card->ba1.name.data0)
- iounmap(card->ba1.name.data0);
- if (card->ba1.name.data1)
- iounmap(card->ba1.name.data1);
- if (card->ba1.name.pmem)
- iounmap(card->ba1.name.pmem);
- if (card->ba1.name.reg)
- iounmap(card->ba1.name.reg);
- kfree(card);
- CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO
- "cs46xx: probe()- no device allocated\n"));
- return -ENODEV;
-} // probe_cs46xx
-
-// ---------------------------------------------------------------------
-
-static void __devexit cs46xx_remove(struct pci_dev *pci_dev)
-{
- struct cs_card *card = PCI_GET_DRIVER_DATA(pci_dev);
- int i;
- unsigned int tmp;
-
- CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
- "cs46xx: cs46xx_remove()+\n"));
-
- card->active_ctrl(card,1);
-
- tmp = cs461x_peek(card, BA1_PFIE);
- tmp &= ~0x0000f03f;
- tmp |= 0x00000010;
- cs461x_poke(card, BA1_PFIE, tmp); /* playback interrupt disable */
-
- tmp = cs461x_peek(card, BA1_CIE);
- tmp &= ~0x0000003f;
- tmp |= 0x00000011;
- cs461x_poke(card, BA1_CIE, tmp); /* capture interrupt disable */
-
- /*
- * Stop playback DMA.
- */
- tmp = cs461x_peek(card, BA1_PCTL);
- cs461x_poke(card, BA1_PCTL, tmp & 0x0000ffff);
-
- /*
- * Stop capture DMA.
- */
- tmp = cs461x_peek(card, BA1_CCTL);
- cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
-
- /*
- * Reset the processor.
- */
- cs461x_reset(card);
-
- cs461x_proc_stop(card);
-
- /*
- * Power down the DAC and ADC. We will power them up (if) when we need
- * them.
- */
- if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
- CS_POWER_MIXVON, CS_TRUE))) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
- }
-
- /*
- * Power down the PLL.
- */
- cs461x_pokeBA0(card, BA0_CLKCR1, 0);
-
- /*
- * Turn off the Processor by turning off the software clock enable flag in
- * the clock control register.
- */
- tmp = cs461x_peekBA0(card, BA0_CLKCR1) & ~CLKCR1_SWCE;
- cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
-
- card->active_ctrl(card,-1);
-
- /* free hardware resources */
- free_irq(card->irq, card);
- iounmap(card->ba0);
- iounmap(card->ba1.name.data0);
- iounmap(card->ba1.name.data1);
- iounmap(card->ba1.name.pmem);
- iounmap(card->ba1.name.reg);
-
- /* unregister audio devices */
- for (i = 0; i < NR_AC97; i++)
- if (card->ac97_codec[i] != NULL) {
- unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
- ac97_release_codec(card->ac97_codec[i]);
- }
- unregister_sound_dsp(card->dev_audio);
- if (card->dev_midi)
- unregister_sound_midi(card->dev_midi);
- list_del(&card->list);
- kfree(card);
- PCI_SET_DRIVER_DATA(pci_dev,NULL);
-
- CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
- "cs46xx: cs46xx_remove()-: remove successful\n"));
-}
-
-enum {
- CS46XX_4610 = 0,
- CS46XX_4612, /* same as 4630 */
- CS46XX_4615, /* same as 4624 */
-};
-
-static struct pci_device_id cs46xx_pci_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_CIRRUS,
- .device = PCI_DEVICE_ID_CIRRUS_4610,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = CS46XX_4610,
- },
- {
- .vendor = PCI_VENDOR_ID_CIRRUS,
- .device = PCI_DEVICE_ID_CIRRUS_4612,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = CS46XX_4612,
- },
- {
- .vendor = PCI_VENDOR_ID_CIRRUS,
- .device = PCI_DEVICE_ID_CIRRUS_4615,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = CS46XX_4615,
- },
- { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, cs46xx_pci_tbl);
-
-static struct pci_driver cs46xx_pci_driver = {
- .name = "cs46xx",
- .id_table = cs46xx_pci_tbl,
- .probe = cs46xx_probe,
- .remove = __devexit_p(cs46xx_remove),
-#ifdef CONFIG_PM
- .suspend = cs46xx_suspend_tbl,
- .resume = cs46xx_resume_tbl,
-#endif
-};
-
-static int __init cs46xx_init_module(void)
-{
- int rtn = 0;
- CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
- "cs46xx: cs46xx_init_module()+ \n"));
- rtn = pci_register_driver(&cs46xx_pci_driver);
-
- if (rtn == -ENODEV) {
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(
- "cs46xx: Unable to detect valid cs46xx device\n"));
- }
-
- CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
- printk(KERN_INFO "cs46xx: cs46xx_init_module()- (%d)\n",rtn));
- return rtn;
-}
-
-static void __exit cs46xx_cleanup_module(void)
-{
- pci_unregister_driver(&cs46xx_pci_driver);
- CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
- printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n"));
-}
-
-module_init(cs46xx_init_module);
-module_exit(cs46xx_cleanup_module);
-
-#ifdef CONFIG_PM
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
-{
- struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
- CS_DBGOUT(CS_PM | CS_FUNCTION, 2,
- printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n"));
- cs46xx_suspend(s, state);
- return 0;
-}
-
-static int cs46xx_resume_tbl(struct pci_dev *pcidev)
-{
- struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
- CS_DBGOUT(CS_PM | CS_FUNCTION, 2,
- printk(KERN_INFO "cs46xx: cs46xx_resume_tbl request\n"));
- cs46xx_resume(s);
- return 0;
-}
-#endif
diff --git a/sound/oss/cs46xx_wrapper-24.h b/sound/oss/cs46xx_wrapper-24.h
deleted file mode 100644
index f68e01181a7c..000000000000
--- a/sound/oss/cs46xx_wrapper-24.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
-*
-* "cs46xx_wrapper.c" -- Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-* Copyright (C) 2000,2001 Cirrus Logic Corp.
-* -- tom woller (twoller@crystal.cirrus.com) or
-* (pcaudio@crystal.cirrus.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.
-*
-* 01/11/2001 trw - new file from cs4281 wrapper code.
-*
-*******************************************************************************/
-#ifndef __CS46XX_WRAPPER24_H
-#define __CS46XX_WRAPPER24_H
-
-#include <linux/spinlock.h>
-
-#define CS_OWNER .owner =
-#define CS_THIS_MODULE THIS_MODULE,
-static inline void cs46xx_null(struct pci_dev *pcidev) { return; }
-#define cs4x_mem_map_reserve(page) SetPageReserved(page)
-#define cs4x_mem_map_unreserve(page) ClearPageReserved(page)
-
-#define free_dmabuf(card, dmabuf) \
- pci_free_consistent((card)->pci_dev, \
- PAGE_SIZE << (dmabuf)->buforder, \
- (dmabuf)->rawbuf, (dmabuf)->dmaaddr);
-#define free_dmabuf2(card, dmabuf) \
- pci_free_consistent((card)->pci_dev, \
- PAGE_SIZE << (dmabuf)->buforder_tmpbuff, \
- (dmabuf)->tmpbuff, (dmabuf)->dmaaddr_tmpbuff);
-#define cs4x_pgoff(vma) ((vma)->vm_pgoff)
-
-#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
- ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
-#define RSRCISMEMORYREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
- ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
-#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
-#define PCI_GET_DRIVER_DATA pci_get_drvdata
-#define PCI_SET_DRIVER_DATA pci_set_drvdata
-#define PCI_SET_DMA_MASK(pcidev,mask) pcidev->dma_mask = mask
-
-#endif
diff --git a/sound/oss/cs46xxpm.h b/sound/oss/cs46xxpm.h
deleted file mode 100644
index 2932b6e0e0bb..000000000000
--- a/sound/oss/cs46xxpm.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
-*
-* "cs46xxpm.h" -- Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-* Copyright (C) 2000,2001 Cirrus Logic Corp.
-* -- tom woller (twoller@crystal.cirrus.com) or
-* (pcaudio@crystal.cirrus.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.
-*
-* 12/22/00 trw - new file.
-*
-*******************************************************************************/
-#ifndef __CS46XXPM_H
-#define __CS46XXPM_H
-
-#define CS46XX_AC97_HIGHESTREGTORESTORE 0x26
-#define CS46XX_AC97_NUMBER_RESTORE_REGS (CS46XX_AC97_HIGHESTREGTORESTORE/2-1)
-
-/* PM state defintions */
-#define CS46XX_PM_NOT_REGISTERED 0x1000
-#define CS46XX_PM_IDLE 0x0001
-#define CS46XX_PM_SUSPENDING 0x0002
-#define CS46XX_PM_SUSPENDED 0x0004
-#define CS46XX_PM_RESUMING 0x0008
-#define CS46XX_PM_RESUMED 0x0010
-
-#define CS_POWER_DAC 0x0001
-#define CS_POWER_ADC 0x0002
-#define CS_POWER_MIXVON 0x0004
-#define CS_POWER_MIXVOFF 0x0008
-#define CS_AC97_POWER_CONTROL_ON 0xf000 /* always on bits (inverted) */
-#define CS_AC97_POWER_CONTROL_ADC 0x0100
-#define CS_AC97_POWER_CONTROL_DAC 0x0200
-#define CS_AC97_POWER_CONTROL_MIXVON 0x0400
-#define CS_AC97_POWER_CONTROL_MIXVOFF 0x0800
-#define CS_AC97_POWER_CONTROL_ADC_ON 0x0001
-#define CS_AC97_POWER_CONTROL_DAC_ON 0x0002
-#define CS_AC97_POWER_CONTROL_MIXVON_ON 0x0004
-#define CS_AC97_POWER_CONTROL_MIXVOFF_ON 0x0008
-
-struct cs46xx_pm {
- unsigned long flags;
- u32 u32CLKCR1_SAVE,u32SSPMValue,u32PPLVCvalue,u32PPRVCvalue;
- u32 u32FMLVCvalue,u32FMRVCvalue,u32GPIORvalue,u32JSCTLvalue,u32SSCR;
- u32 u32SRCSA,u32DacASR,u32AdcASR,u32DacSR,u32AdcSR,u32MIDCR_Save;
- u32 u32SSPM_BITS;
- u32 ac97[CS46XX_AC97_NUMBER_RESTORE_REGS];
- u32 u32AC97_master_volume, u32AC97_headphone_volume, u32AC97_master_volume_mono;
- u32 u32AC97_pcm_out_volume, u32AC97_powerdown, u32AC97_general_purpose;
- u32 u32hwptr_playback,u32hwptr_capture;
- unsigned dmabuf_swptr_play;
- int dmabuf_count_play;
- unsigned dmabuf_swptr_capture;
- int dmabuf_count_capture;
-};
-
-#endif
diff --git a/sound/oss/emu10k1/8010.h b/sound/oss/emu10k1/8010.h
deleted file mode 100644
index 61c6c42bbc36..000000000000
--- a/sound/oss/emu10k1/8010.h
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- **********************************************************************
- * 8010.h
- * Copyright 1999-2001 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox Cleaned of 8bit chars, DOS
- * line endings
- * December 8, 1999 Jon Taylor Added lots of new register info
- * May 16, 2001 Daniel Bertrand Added unofficial DBG register info
- * Oct-Nov 2001 D.B. Added unofficial Audigy registers
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- *
- **********************************************************************
- */
-
-
-#ifndef _8010_H
-#define _8010_H
-
-#include <linux/types.h>
-
-// Driver version:
-#define MAJOR_VER 0
-#define MINOR_VER 20
-#define DRIVER_VERSION "0.20a"
-
-
-// Audigy specify registers are prefixed with 'A_'
-
-/************************************************************************************************/
-/* PCI function 0 registers, address = <val> + PCIBASE0 */
-/************************************************************************************************/
-
-#define PTR 0x00 /* Indexed register set pointer register */
- /* NOTE: The CHANNELNUM and ADDRESS words can */
- /* be modified independently of each other. */
-#define PTR_CHANNELNUM_MASK 0x0000003f /* For each per-channel register, indicates the */
- /* channel number of the register to be */
- /* accessed. For non per-channel registers the */
- /* value should be set to zero. */
-#define PTR_ADDRESS_MASK 0x07ff0000 /* Register index */
-
-#define DATA 0x04 /* Indexed register set data register */
-
-#define IPR 0x08 /* Global interrupt pending register */
- /* Clear pending interrupts by writing a 1 to */
- /* the relevant bits and zero to the other bits */
-
-/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */
-#define A_IPR_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */
-#define A_IPR_MIDIRECVBUFEMPTY2 0x08000000 /* MIDI UART receive buffer empty */
-
-#define IPR_SAMPLERATETRACKER 0x01000000 /* Sample rate tracker lock status change */
-#define IPR_FXDSP 0x00800000 /* Enable FX DSP interrupts */
-#define IPR_FORCEINT 0x00400000 /* Force Sound Blaster interrupt */
-#define IPR_PCIERROR 0x00200000 /* PCI bus error */
-#define IPR_VOLINCR 0x00100000 /* Volume increment button pressed */
-#define IPR_VOLDECR 0x00080000 /* Volume decrement button pressed */
-#define IPR_MUTE 0x00040000 /* Mute button pressed */
-#define IPR_MICBUFFULL 0x00020000 /* Microphone buffer full */
-#define IPR_MICBUFHALFFULL 0x00010000 /* Microphone buffer half full */
-#define IPR_ADCBUFFULL 0x00008000 /* ADC buffer full */
-#define IPR_ADCBUFHALFFULL 0x00004000 /* ADC buffer half full */
-#define IPR_EFXBUFFULL 0x00002000 /* Effects buffer full */
-#define IPR_EFXBUFHALFFULL 0x00001000 /* Effects buffer half full */
-#define IPR_GPSPDIFSTATUSCHANGE 0x00000800 /* GPSPDIF channel status change */
-#define IPR_CDROMSTATUSCHANGE 0x00000400 /* CD-ROM channel status change */
-#define IPR_INTERVALTIMER 0x00000200 /* Interval timer terminal count */
-#define IPR_MIDITRANSBUFEMPTY 0x00000100 /* MIDI UART transmit buffer empty */
-#define IPR_MIDIRECVBUFEMPTY 0x00000080 /* MIDI UART receive buffer empty */
-#define IPR_CHANNELLOOP 0x00000040 /* One or more channel loop interrupts pending */
-#define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */
- /* Highest set channel in CLIPL or CLIPH. When */
- /* IP is written with CL set, the bit in CLIPL */
- /* or CLIPH corresponding to the CIN value */
- /* written will be cleared. */
-#define A_IPR_MIDITRANSBUFEMPTY1 IPR_MIDITRANSBUFEMPTY /* MIDI UART transmit buffer empty */
-#define A_IPR_MIDIRECVBUFEMPTY1 IPR_MIDIRECVBUFEMPTY /* MIDI UART receive buffer empty */
-
-
-
-#define INTE 0x0c /* Interrupt enable register */
-#define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */
-#define INTE_VIRTUALSB_220 0x00000000 /* Capture at I/O base address 0x220-0x22f */
-#define INTE_VIRTUALSB_240 0x40000000 /* Capture at I/O base address 0x240 */
-#define INTE_VIRTUALSB_260 0x80000000 /* Capture at I/O base address 0x260 */
-#define INTE_VIRTUALSB_280 0xc0000000 /* Capture at I/O base address 0x280 */
-#define INTE_VIRTUALMPU_MASK 0x30000000 /* Virtual MPU I/O port capture */
-#define INTE_VIRTUALMPU_300 0x00000000 /* Capture at I/O base address 0x300-0x301 */
-#define INTE_VIRTUALMPU_310 0x10000000 /* Capture at I/O base address 0x310 */
-#define INTE_VIRTUALMPU_320 0x20000000 /* Capture at I/O base address 0x320 */
-#define INTE_VIRTUALMPU_330 0x30000000 /* Capture at I/O base address 0x330 */
-#define INTE_MASTERDMAENABLE 0x08000000 /* Master DMA emulation at 0x000-0x00f */
-#define INTE_SLAVEDMAENABLE 0x04000000 /* Slave DMA emulation at 0x0c0-0x0df */
-#define INTE_MASTERPICENABLE 0x02000000 /* Master PIC emulation at 0x020-0x021 */
-#define INTE_SLAVEPICENABLE 0x01000000 /* Slave PIC emulation at 0x0a0-0x0a1 */
-#define INTE_VSBENABLE 0x00800000 /* Enable virtual Soundblaster */
-#define INTE_ADLIBENABLE 0x00400000 /* Enable AdLib emulation at 0x388-0x38b */
-#define INTE_MPUENABLE 0x00200000 /* Enable virtual MPU */
-#define INTE_FORCEINT 0x00100000 /* Continuously assert INTAN */
-
-#define INTE_MRHANDENABLE 0x00080000 /* Enable the "Mr. Hand" logic */
- /* NOTE: There is no reason to use this under */
- /* Linux, and it will cause odd hardware */
- /* behavior and possibly random segfaults and */
- /* lockups if enabled. */
-
-/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */
-#define A_INTE_MIDITXENABLE2 0x00020000 /* Enable MIDI transmit-buffer-empty interrupts */
-#define A_INTE_MIDIRXENABLE2 0x00010000 /* Enable MIDI receive-buffer-empty interrupts */
-
-
-#define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */
- /* NOTE: This bit must always be enabled */
-#define INTE_FXDSPENABLE 0x00001000 /* Enable FX DSP interrupts */
-#define INTE_PCIERRORENABLE 0x00000800 /* Enable PCI bus error interrupts */
-#define INTE_VOLINCRENABLE 0x00000400 /* Enable volume increment button interrupts */
-#define INTE_VOLDECRENABLE 0x00000200 /* Enable volume decrement button interrupts */
-#define INTE_MUTEENABLE 0x00000100 /* Enable mute button interrupts */
-#define INTE_MICBUFENABLE 0x00000080 /* Enable microphone buffer interrupts */
-#define INTE_ADCBUFENABLE 0x00000040 /* Enable ADC buffer interrupts */
-#define INTE_EFXBUFENABLE 0x00000020 /* Enable Effects buffer interrupts */
-#define INTE_GPSPDIFENABLE 0x00000010 /* Enable GPSPDIF status interrupts */
-#define INTE_CDSPDIFENABLE 0x00000008 /* Enable CDSPDIF status interrupts */
-#define INTE_INTERVALTIMERENB 0x00000004 /* Enable interval timer interrupts */
-#define INTE_MIDITXENABLE 0x00000002 /* Enable MIDI transmit-buffer-empty interrupts */
-#define INTE_MIDIRXENABLE 0x00000001 /* Enable MIDI receive-buffer-empty interrupts */
-
-/* The next two interrupts are for the midi port on the Audigy (A_MPU2) */
-#define A_INTE_MIDITXENABLE1 INTE_MIDITXENABLE
-#define A_INTE_MIDIRXENABLE1 INTE_MIDIRXENABLE
-
-#define WC 0x10 /* Wall Clock register */
-#define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */
-#define WC_SAMPLECOUNTER 0x14060010
-#define WC_CURRENTCHANNEL 0x0000003F /* Channel [0..63] currently being serviced */
- /* NOTE: Each channel takes 1/64th of a sample */
- /* period to be serviced. */
-
-#define HCFG 0x14 /* Hardware config register */
- /* NOTE: There is no reason to use the legacy */
- /* SoundBlaster emulation stuff described below */
- /* under Linux, and all kinds of weird hardware */
- /* behavior can result if you try. Don't. */
-#define HCFG_LEGACYFUNC_MASK 0xe0000000 /* Legacy function number */
-#define HCFG_LEGACYFUNC_MPU 0x00000000 /* Legacy MPU */
-#define HCFG_LEGACYFUNC_SB 0x40000000 /* Legacy SB */
-#define HCFG_LEGACYFUNC_AD 0x60000000 /* Legacy AD */
-#define HCFG_LEGACYFUNC_MPIC 0x80000000 /* Legacy MPIC */
-#define HCFG_LEGACYFUNC_MDMA 0xa0000000 /* Legacy MDMA */
-#define HCFG_LEGACYFUNC_SPCI 0xc0000000 /* Legacy SPCI */
-#define HCFG_LEGACYFUNC_SDMA 0xe0000000 /* Legacy SDMA */
-#define HCFG_IOCAPTUREADDR 0x1f000000 /* The 4 LSBs of the captured I/O address. */
-#define HCFG_LEGACYWRITE 0x00800000 /* 1 = write, 0 = read */
-#define HCFG_LEGACYWORD 0x00400000 /* 1 = word, 0 = byte */
-#define HCFG_LEGACYINT 0x00200000 /* 1 = legacy event captured. Write 1 to clear. */
- /* NOTE: The rest of the bits in this register */
- /* _are_ relevant under Linux. */
-#define HCFG_CODECFORMAT_MASK 0x00070000 /* CODEC format */
-#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */
-#define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */
-#define HCFG_GPINPUT0 0x00004000 /* External pin112 */
-#define HCFG_GPINPUT1 0x00002000 /* External pin110 */
-
-#define HCFG_GPOUTPUT_MASK 0x00001c00 /* External pins which may be controlled */
-#define HCFG_GPOUT0 0x00001000 /* set to enable digital out on 5.1 cards */
-
-#define HCFG_JOYENABLE 0x00000200 /* Internal joystick enable */
-#define HCFG_PHASETRACKENABLE 0x00000100 /* Phase tracking enable */
- /* 1 = Force all 3 async digital inputs to use */
- /* the same async sample rate tracker (ZVIDEO) */
-#define HCFG_AC3ENABLE_MASK 0x0x0000e0 /* AC3 async input control - Not implemented */
-#define HCFG_AC3ENABLE_ZVIDEO 0x00000080 /* Channels 0 and 1 replace ZVIDEO */
-#define HCFG_AC3ENABLE_CDSPDIF 0x00000040 /* Channels 0 and 1 replace CDSPDIF */
-#define HCFG_AC3ENABLE_GPSPDIF 0x00000020 /* Channels 0 and 1 replace GPSPDIF */
-#define HCFG_AUTOMUTE 0x00000010 /* When set, the async sample rate convertors */
- /* will automatically mute their output when */
- /* they are not rate-locked to the external */
- /* async audio source */
-#define HCFG_LOCKSOUNDCACHE 0x00000008 /* 1 = Cancel bustmaster accesses to soundcache */
- /* NOTE: This should generally never be used. */
-#define HCFG_LOCKTANKCACHE_MASK 0x00000004 /* 1 = Cancel bustmaster accesses to tankcache */
- /* NOTE: This should generally never be used. */
-#define HCFG_LOCKTANKCACHE 0x01020014
-#define HCFG_MUTEBUTTONENABLE 0x00000002 /* 1 = Master mute button sets AUDIOENABLE = 0. */
- /* NOTE: This is a 'cheap' way to implement a */
- /* master mute function on the mute button, and */
- /* in general should not be used unless a more */
- /* sophisticated master mute function has not */
- /* been written. */
-#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */
- /* Should be set to 1 when the EMU10K1 is */
- /* completely initialized. */
-
-//For Audigy, MPU port move to 0x70-0x74 ptr register
-
-#define MUDATA 0x18 /* MPU401 data register (8 bits) */
-
-#define MUCMD 0x19 /* MPU401 command register (8 bits) */
-#define MUCMD_RESET 0xff /* RESET command */
-#define MUCMD_ENTERUARTMODE 0x3f /* Enter_UART_mode command */
- /* NOTE: All other commands are ignored */
-
-#define MUSTAT MUCMD /* MPU401 status register (8 bits) */
-#define MUSTAT_IRDYN 0x80 /* 0 = MIDI data or command ACK */
-#define MUSTAT_ORDYN 0x40 /* 0 = MUDATA can accept a command or data */
-
-#define A_IOCFG 0x18 /* GPIO on Audigy card (16bits) */
-#define A_GPINPUT_MASK 0xff00
-#define A_GPOUTPUT_MASK 0x00ff
-
-#define TIMER 0x1a /* Timer terminal count register (16-bit) */
- /* NOTE: After the rate is changed, a maximum */
- /* of 1024 sample periods should be allowed */
- /* before the new rate is guaranteed accurate. */
-#define TIMER_RATE_MASK 0x03ff /* Timer interrupt rate in sample periods */
- /* 0 == 1024 periods, [1..4] are not useful */
-
-#define AC97DATA 0x1c /* AC97 register set data register (16 bit) */
-
-#define AC97ADDRESS 0x1e /* AC97 register set address register (8 bit) */
-#define AC97ADDRESS_READY 0x80 /* Read-only bit, reflects CODEC READY signal */
-#define AC97ADDRESS_ADDRESS 0x7f /* Address of indexed AC97 register */
-
-/********************************************************************************************************/
-/* Emu10k1 pointer-offset register set, accessed through the PTR and DATA registers */
-/********************************************************************************************************/
-
-#define CPF 0x00 /* Current pitch and fraction register */
-#define CPF_CURRENTPITCH_MASK 0xffff0000 /* Current pitch (linear, 0x4000 == unity pitch shift) */
-#define CPF_CURRENTPITCH 0x10100000
-#define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */
-#define CPF_STOP_MASK 0x00004000 /* 1 = Current pitch forced to 0 */
-#define CPF_FRACADDRESS_MASK 0x00003fff /* Linear fractional address of the current channel */
-
-#define PTRX 0x01 /* Pitch target and send A/B amounts register */
-#define PTRX_PITCHTARGET_MASK 0xffff0000 /* Pitch target of specified channel */
-#define PTRX_PITCHTARGET 0x10100001
-#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00 /* Linear level of channel output sent to FX send bus A */
-#define PTRX_FXSENDAMOUNT_A 0x08080001
-#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff /* Linear level of channel output sent to FX send bus B */
-#define PTRX_FXSENDAMOUNT_B 0x08000001
-
-#define CVCF 0x02 /* Current volume and filter cutoff register */
-#define CVCF_CURRENTVOL_MASK 0xffff0000 /* Current linear volume of specified channel */
-#define CVCF_CURRENTVOL 0x10100002
-#define CVCF_CURRENTFILTER_MASK 0x0000ffff /* Current filter cutoff frequency of specified channel */
-#define CVCF_CURRENTFILTER 0x10000002
-
-#define VTFT 0x03 /* Volume target and filter cutoff target register */
-#define VTFT_VOLUMETARGET_MASK 0xffff0000 /* Volume target of specified channel */
-#define VTFT_FILTERTARGET_MASK 0x0000ffff /* Filter cutoff target of specified channel */
-
-#define Z1 0x05 /* Filter delay memory 1 register */
-
-#define Z2 0x04 /* Filter delay memory 2 register */
-
-#define PSST 0x06 /* Send C amount and loop start address register */
-#define PSST_FXSENDAMOUNT_C_MASK 0xff000000 /* Linear level of channel output sent to FX send bus C */
-
-#define PSST_FXSENDAMOUNT_C 0x08180006
-
-#define PSST_LOOPSTARTADDR_MASK 0x00ffffff /* Loop start address of the specified channel */
-#define PSST_LOOPSTARTADDR 0x18000006
-
-#define DSL 0x07 /* Send D amount and loop start address register */
-#define DSL_FXSENDAMOUNT_D_MASK 0xff000000 /* Linear level of channel output sent to FX send bus D */
-
-#define DSL_FXSENDAMOUNT_D 0x08180007
-
-#define DSL_LOOPENDADDR_MASK 0x00ffffff /* Loop end address of the specified channel */
-#define DSL_LOOPENDADDR 0x18000007
-
-#define CCCA 0x08 /* Filter Q, interp. ROM, byte size, cur. addr register */
-#define CCCA_RESONANCE 0xf0000000 /* Lowpass filter resonance (Q) height */
-#define CCCA_INTERPROMMASK 0x0e000000 /* Selects passband of interpolation ROM */
- /* 1 == full band, 7 == lowpass */
- /* ROM 0 is used when pitch shifting downward or less */
- /* then 3 semitones upward. Increasingly higher ROM */
- /* numbers are used, typically in steps of 3 semitones, */
- /* as upward pitch shifting is performed. */
-#define CCCA_INTERPROM_0 0x00000000 /* Select interpolation ROM 0 */
-#define CCCA_INTERPROM_1 0x02000000 /* Select interpolation ROM 1 */
-#define CCCA_INTERPROM_2 0x04000000 /* Select interpolation ROM 2 */
-#define CCCA_INTERPROM_3 0x06000000 /* Select interpolation ROM 3 */
-#define CCCA_INTERPROM_4 0x08000000 /* Select interpolation ROM 4 */
-#define CCCA_INTERPROM_5 0x0a000000 /* Select interpolation ROM 5 */
-#define CCCA_INTERPROM_6 0x0c000000 /* Select interpolation ROM 6 */
-#define CCCA_INTERPROM_7 0x0e000000 /* Select interpolation ROM 7 */
-#define CCCA_8BITSELECT 0x01000000 /* 1 = Sound memory for this channel uses 8-bit samples */
-#define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */
-#define CCCA_CURRADDR 0x18000008
-
-#define CCR 0x09 /* Cache control register */
-#define CCR_CACHEINVALIDSIZE 0x07190009
-#define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */
-#define CCR_CACHELOOPFLAG 0x01000000 /* 1 = Cache has a loop service pending */
-#define CCR_INTERLEAVEDSAMPLES 0x00800000 /* 1 = A cache service will fetch interleaved samples */
-#define CCR_WORDSIZEDSAMPLES 0x00400000 /* 1 = A cache service will fetch word sized samples */
-#define CCR_READADDRESS 0x06100009
-#define CCR_READADDRESS_MASK 0x003f0000 /* Location of cache just beyond current cache service */
-#define CCR_LOOPINVALSIZE 0x0000fe00 /* Number of invalid samples in cache prior to loop */
- /* NOTE: This is valid only if CACHELOOPFLAG is set */
-#define CCR_LOOPFLAG 0x00000100 /* Set for a single sample period when a loop occurs */
-#define CCR_CACHELOOPADDRHI 0x000000ff /* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set */
-
-#define CLP 0x0a /* Cache loop register (valid if CCR_CACHELOOPFLAG = 1) */
- /* NOTE: This register is normally not used */
-#define CLP_CACHELOOPADDR 0x0000ffff /* Cache loop address (DSL_LOOPSTARTADDR [0..15]) */
-
-#define FXRT 0x0b /* Effects send routing register */
- /* NOTE: It is illegal to assign the same routing to */
- /* two effects sends. */
-#define FXRT_CHANNELA 0x000f0000 /* Effects send bus number for channel's effects send A */
-#define FXRT_CHANNELB 0x00f00000 /* Effects send bus number for channel's effects send B */
-#define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */
-#define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */
-
-#define MAPA 0x0c /* Cache map A */
-
-#define MAPB 0x0d /* Cache map B */
-
-#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */
-#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */
-
-#define ENVVOL 0x10 /* Volume envelope register */
-#define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */
- /* 0x8000-n == 666*n usec delay */
-
-#define ATKHLDV 0x11 /* Volume envelope hold and attack register */
-#define ATKHLDV_PHASE0 0x00008000 /* 0 = Begin attack phase */
-#define ATKHLDV_HOLDTIME_MASK 0x00007f00 /* Envelope hold time (127-n == n*88.2msec) */
-#define ATKHLDV_ATTACKTIME_MASK 0x0000007f /* Envelope attack time, log encoded */
- /* 0 = infinite, 1 = 10.9msec, ... 0x7f = 5.5msec */
-
-#define DCYSUSV 0x12 /* Volume envelope sustain and decay register */
-#define DCYSUSV_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */
-#define DCYSUSV_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */
-#define DCYSUSV_CHANNELENABLE_MASK 0x00000080 /* 1 = Inhibit envelope engine from writing values in */
- /* this channel and from writing to pitch, filter and */
- /* volume targets. */
-#define DCYSUSV_DECAYTIME_MASK 0x0000007f /* Volume envelope decay time, log encoded */
- /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */
-
-#define LFOVAL1 0x13 /* Modulation LFO value */
-#define LFOVAL_MASK 0x0000ffff /* Current value of modulation LFO state variable */
- /* 0x8000-n == 666*n usec delay */
-
-#define ENVVAL 0x14 /* Modulation envelope register */
-#define ENVVAL_MASK 0x0000ffff /* Current value of modulation envelope state variable */
- /* 0x8000-n == 666*n usec delay */
-
-#define ATKHLDM 0x15 /* Modulation envelope hold and attack register */
-#define ATKHLDM_PHASE0 0x00008000 /* 0 = Begin attack phase */
-#define ATKHLDM_HOLDTIME 0x00007f00 /* Envelope hold time (127-n == n*42msec) */
-#define ATKHLDM_ATTACKTIME 0x0000007f /* Envelope attack time, log encoded */
- /* 0 = infinite, 1 = 11msec, ... 0x7f = 5.5msec */
-
-#define DCYSUSM 0x16 /* Modulation envelope decay and sustain register */
-#define DCYSUSM_PHASE1_MASK 0x00008000 /* 0 = Begin attack phase, 1 = begin release phase */
-#define DCYSUSM_SUSTAINLEVEL_MASK 0x00007f00 /* 127 = full, 0 = off, 0.75dB increments */
-#define DCYSUSM_DECAYTIME_MASK 0x0000007f /* Envelope decay time, log encoded */
- /* 0 = 43.7msec, 1 = 21.8msec, 0x7f = 22msec */
-
-#define LFOVAL2 0x17 /* Vibrato LFO register */
-#define LFOVAL2_MASK 0x0000ffff /* Current value of vibrato LFO state variable */
- /* 0x8000-n == 666*n usec delay */
-
-#define IP 0x18 /* Initial pitch register */
-#define IP_MASK 0x0000ffff /* Exponential initial pitch shift */
- /* 4 bits of octave, 12 bits of fractional octave */
-#define IP_UNITY 0x0000e000 /* Unity pitch shift */
-
-#define IFATN 0x19 /* Initial filter cutoff and attenuation register */
-#define IFATN_FILTERCUTOFF_MASK 0x0000ff00 /* Initial filter cutoff frequency in exponential units */
- /* 6 most significant bits are semitones */
- /* 2 least significant bits are fractions */
-#define IFATN_FILTERCUTOFF 0x08080019
-#define IFATN_ATTENUATION_MASK 0x000000ff /* Initial attenuation in 0.375dB steps */
-#define IFATN_ATTENUATION 0x08000019
-
-
-#define PEFE 0x1a /* Pitch envelope and filter envelope amount register */
-#define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */
- /* Signed 2's complement, +/- one octave peak extremes */
-#define PEFE_PITCHAMOUNT 0x0808001a
-#define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */
- /* Signed 2's complement, +/- six octaves peak extremes */
-#define PEFE_FILTERAMOUNT 0x0800001a
-#define FMMOD 0x1b /* Vibrato/filter modulation from LFO register */
-#define FMMOD_MODVIBRATO 0x0000ff00 /* Vibrato LFO modulation depth */
- /* Signed 2's complement, +/- one octave extremes */
-#define FMMOD_MOFILTER 0x000000ff /* Filter LFO modulation depth */
- /* Signed 2's complement, +/- three octave extremes */
-
-
-#define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */
-#define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */
- /* Signed 2's complement, with +/- 12dB extremes */
-#define TREMFRQ_FREQUENCY 0x000000ff /* Tremolo LFO frequency */
- /* ??Hz steps, maximum of ?? Hz. */
-
-#define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */
-#define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */
- /* Signed 2's complement, +/- one octave extremes */
-#define FM2FRQ2_FREQUENCY 0x000000ff /* Vibrato LFO frequency */
- /* 0.039Hz steps, maximum of 9.85 Hz. */
-
-#define TEMPENV 0x1e /* Tempory envelope register */
-#define TEMPENV_MASK 0x0000ffff /* 16-bit value */
- /* NOTE: All channels contain internal variables; do */
- /* not write to these locations. */
-
-#define CD0 0x20 /* Cache data 0 register */
-#define CD1 0x21 /* Cache data 1 register */
-#define CD2 0x22 /* Cache data 2 register */
-#define CD3 0x23 /* Cache data 3 register */
-#define CD4 0x24 /* Cache data 4 register */
-#define CD5 0x25 /* Cache data 5 register */
-#define CD6 0x26 /* Cache data 6 register */
-#define CD7 0x27 /* Cache data 7 register */
-#define CD8 0x28 /* Cache data 8 register */
-#define CD9 0x29 /* Cache data 9 register */
-#define CDA 0x2a /* Cache data A register */
-#define CDB 0x2b /* Cache data B register */
-#define CDC 0x2c /* Cache data C register */
-#define CDD 0x2d /* Cache data D register */
-#define CDE 0x2e /* Cache data E register */
-#define CDF 0x2f /* Cache data F register */
-
-#define PTB 0x40 /* Page table base register */
-#define PTB_MASK 0xfffff000 /* Physical address of the page table in host memory */
-
-#define TCB 0x41 /* Tank cache base register */
-#define TCB_MASK 0xfffff000 /* Physical address of the bottom of host based TRAM */
-
-#define ADCCR 0x42 /* ADC sample rate/stereo control register */
-#define ADCCR_RCHANENABLE 0x00000010 /* Enables right channel for writing to the host */
-#define ADCCR_LCHANENABLE 0x00000008 /* Enables left channel for writing to the host */
- /* NOTE: To guarantee phase coherency, both channels */
- /* must be disabled prior to enabling both channels. */
-#define A_ADCCR_RCHANENABLE 0x00000020
-#define A_ADCCR_LCHANENABLE 0x00000010
-
-#define A_ADCCR_SAMPLERATE_MASK 0x0000000F /* Audigy sample rate convertor output rate */
-#define ADCCR_SAMPLERATE_MASK 0x00000007 /* Sample rate convertor output rate */
-
-#define ADCCR_SAMPLERATE_48 0x00000000 /* 48kHz sample rate */
-#define ADCCR_SAMPLERATE_44 0x00000001 /* 44.1kHz sample rate */
-#define ADCCR_SAMPLERATE_32 0x00000002 /* 32kHz sample rate */
-#define ADCCR_SAMPLERATE_24 0x00000003 /* 24kHz sample rate */
-#define ADCCR_SAMPLERATE_22 0x00000004 /* 22.05kHz sample rate */
-#define ADCCR_SAMPLERATE_16 0x00000005 /* 16kHz sample rate */
-#define ADCCR_SAMPLERATE_11 0x00000006 /* 11.025kHz sample rate */
-#define ADCCR_SAMPLERATE_8 0x00000007 /* 8kHz sample rate */
-
-#define A_ADCCR_SAMPLERATE_12 0x00000006 /* 12kHz sample rate */
-#define A_ADCCR_SAMPLERATE_11 0x00000007 /* 11.025kHz sample rate */
-#define A_ADCCR_SAMPLERATE_8 0x00000008 /* 8kHz sample rate */
-
-#define FXWC 0x43 /* FX output write channels register */
- /* When set, each bit enables the writing of the */
- /* corresponding FX output channel (internal registers */
- /* 0x20-0x3f) into host memory. This mode of recording */
- /* is 16bit, 48KHz only. All 32 channels can be enabled */
- /* simultaneously. */
-#define TCBS 0x44 /* Tank cache buffer size register */
-#define TCBS_MASK 0x00000007 /* Tank cache buffer size field */
-#define TCBS_BUFFSIZE_16K 0x00000000
-#define TCBS_BUFFSIZE_32K 0x00000001
-#define TCBS_BUFFSIZE_64K 0x00000002
-#define TCBS_BUFFSIZE_128K 0x00000003
-#define TCBS_BUFFSIZE_256K 0x00000004
-#define TCBS_BUFFSIZE_512K 0x00000005
-#define TCBS_BUFFSIZE_1024K 0x00000006
-#define TCBS_BUFFSIZE_2048K 0x00000007
-
-#define MICBA 0x45 /* AC97 microphone buffer address register */
-#define MICBA_MASK 0xfffff000 /* 20 bit base address */
-
-#define ADCBA 0x46 /* ADC buffer address register */
-#define ADCBA_MASK 0xfffff000 /* 20 bit base address */
-
-#define FXBA 0x47 /* FX Buffer Address */
-#define FXBA_MASK 0xfffff000 /* 20 bit base address */
-
-#define MICBS 0x49 /* Microphone buffer size register */
-
-#define ADCBS 0x4a /* ADC buffer size register */
-
-#define FXBS 0x4b /* FX buffer size register */
-
-/* The following mask values define the size of the ADC, MIX and FX buffers in bytes */
-#define ADCBS_BUFSIZE_NONE 0x00000000
-#define ADCBS_BUFSIZE_384 0x00000001
-#define ADCBS_BUFSIZE_448 0x00000002
-#define ADCBS_BUFSIZE_512 0x00000003
-#define ADCBS_BUFSIZE_640 0x00000004
-#define ADCBS_BUFSIZE_768 0x00000005
-#define ADCBS_BUFSIZE_896 0x00000006
-#define ADCBS_BUFSIZE_1024 0x00000007
-#define ADCBS_BUFSIZE_1280 0x00000008
-#define ADCBS_BUFSIZE_1536 0x00000009
-#define ADCBS_BUFSIZE_1792 0x0000000a
-#define ADCBS_BUFSIZE_2048 0x0000000b
-#define ADCBS_BUFSIZE_2560 0x0000000c
-#define ADCBS_BUFSIZE_3072 0x0000000d
-#define ADCBS_BUFSIZE_3584 0x0000000e
-#define ADCBS_BUFSIZE_4096 0x0000000f
-#define ADCBS_BUFSIZE_5120 0x00000010
-#define ADCBS_BUFSIZE_6144 0x00000011
-#define ADCBS_BUFSIZE_7168 0x00000012
-#define ADCBS_BUFSIZE_8192 0x00000013
-#define ADCBS_BUFSIZE_10240 0x00000014
-#define ADCBS_BUFSIZE_12288 0x00000015
-#define ADCBS_BUFSIZE_14366 0x00000016
-#define ADCBS_BUFSIZE_16384 0x00000017
-#define ADCBS_BUFSIZE_20480 0x00000018
-#define ADCBS_BUFSIZE_24576 0x00000019
-#define ADCBS_BUFSIZE_28672 0x0000001a
-#define ADCBS_BUFSIZE_32768 0x0000001b
-#define ADCBS_BUFSIZE_40960 0x0000001c
-#define ADCBS_BUFSIZE_49152 0x0000001d
-#define ADCBS_BUFSIZE_57344 0x0000001e
-#define ADCBS_BUFSIZE_65536 0x0000001f
-
-
-#define CDCS 0x50 /* CD-ROM digital channel status register */
-
-#define GPSCS 0x51 /* General Purpose SPDIF channel status register*/
-
-#define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
-
-/* definitions for debug register - taken from the alsa drivers */
-#define DBG_ZC 0x80000000 /* zero tram counter */
-#define DBG_SATURATION_OCCURED 0x02000000 /* saturation control */
-#define DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */
-#define DBG_SINGLE_STEP 0x00008000 /* single step mode */
-#define DBG_STEP 0x00004000 /* start single step */
-#define DBG_CONDITION_CODE 0x00003e00 /* condition code */
-#define DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */
-
-
-#define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
-
-#define A_DBG 0x53
-#define A_DBG_SINGLE_STEP 0x00020000 /* Set to zero to start dsp */
-#define A_DBG_ZC 0x40000000 /* zero tram counter */
-#define A_DBG_STEP_ADDR 0x000003ff
-#define A_DBG_SATURATION_OCCURED 0x20000000
-#define A_DBG_SATURATION_ADDR 0x0ffc0000
-
-#define SPCS0 0x54 /* SPDIF output Channel Status 0 register */
-
-#define SPCS1 0x55 /* SPDIF output Channel Status 1 register */
-
-#define SPCS2 0x56 /* SPDIF output Channel Status 2 register */
-
-#define SPCS_CLKACCYMASK 0x30000000 /* Clock accuracy */
-#define SPCS_CLKACCY_1000PPM 0x00000000 /* 1000 parts per million */
-#define SPCS_CLKACCY_50PPM 0x10000000 /* 50 parts per million */
-#define SPCS_CLKACCY_VARIABLE 0x20000000 /* Variable accuracy */
-#define SPCS_SAMPLERATEMASK 0x0f000000 /* Sample rate */
-#define SPCS_SAMPLERATE_44 0x00000000 /* 44.1kHz sample rate */
-#define SPCS_SAMPLERATE_48 0x02000000 /* 48kHz sample rate */
-#define SPCS_SAMPLERATE_32 0x03000000 /* 32kHz sample rate */
-#define SPCS_CHANNELNUMMASK 0x00f00000 /* Channel number */
-#define SPCS_CHANNELNUM_UNSPEC 0x00000000 /* Unspecified channel number */
-#define SPCS_CHANNELNUM_LEFT 0x00100000 /* Left channel */
-#define SPCS_CHANNELNUM_RIGHT 0x00200000 /* Right channel */
-#define SPCS_SOURCENUMMASK 0x000f0000 /* Source number */
-#define SPCS_SOURCENUM_UNSPEC 0x00000000 /* Unspecified source number */
-#define SPCS_GENERATIONSTATUS 0x00008000 /* Originality flag (see IEC-958 spec) */
-#define SPCS_CATEGORYCODEMASK 0x00007f00 /* Category code (see IEC-958 spec) */
-#define SPCS_MODEMASK 0x000000c0 /* Mode (see IEC-958 spec) */
-#define SPCS_EMPHASISMASK 0x00000038 /* Emphasis */
-#define SPCS_EMPHASIS_NONE 0x00000000 /* No emphasis */
-#define SPCS_EMPHASIS_50_15 0x00000008 /* 50/15 usec 2 channel */
-#define SPCS_COPYRIGHT 0x00000004 /* Copyright asserted flag -- do not modify */
-#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */
-#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */
-
-/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status */
-#define CLIEL 0x58 /* Channel loop interrupt enable low register */
-
-#define CLIEH 0x59 /* Channel loop interrupt enable high register */
-
-#define CLIPL 0x5a /* Channel loop interrupt pending low register */
-
-#define CLIPH 0x5b /* Channel loop interrupt pending high register */
-
-#define SOLEL 0x5c /* Stop on loop enable low register */
-
-#define SOLEH 0x5d /* Stop on loop enable high register */
-
-#define SPBYPASS 0x5e /* SPDIF BYPASS mode register */
-#define SPBYPASS_ENABLE 0x00000001 /* Enable SPDIF bypass mode */
-
-#define AC97SLOT 0x5f /* additional AC97 slots enable bits */
-#define AC97SLOT_CNTR 0x10 /* Center enable */
-#define AC97SLOT_LFE 0x20 /* LFE enable */
-
-#define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */
-
-#define GPSRCS 0x61 /* General Purpose SPDIF sample rate cvt status */
-
-#define ZVSRCS 0x62 /* ZVideo sample rate converter status */
- /* NOTE: This one has no SPDIFLOCKED field */
- /* Assumes sample lock */
-
-/* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS. */
-#define SRCS_SPDIFLOCKED 0x02000000 /* SPDIF stream locked */
-#define SRCS_RATELOCKED 0x01000000 /* Sample rate locked */
-#define SRCS_ESTSAMPLERATE 0x0007ffff /* Do not modify this field. */
-
-
-/* Note that these values can vary +/- by a small amount */
-#define SRCS_SPDIFRATE_44 0x0003acd9
-#define SRCS_SPDIFRATE_48 0x00040000
-#define SRCS_SPDIFRATE_96 0x00080000
-
-#define MICIDX 0x63 /* Microphone recording buffer index register */
-#define MICIDX_MASK 0x0000ffff /* 16-bit value */
-#define MICIDX_IDX 0x10000063
-
-#define A_ADCIDX 0x63
-#define A_ADCIDX_IDX 0x10000063
-
-#define ADCIDX 0x64 /* ADC recording buffer index register */
-#define ADCIDX_MASK 0x0000ffff /* 16 bit index field */
-#define ADCIDX_IDX 0x10000064
-
-#define FXIDX 0x65 /* FX recording buffer index register */
-#define FXIDX_MASK 0x0000ffff /* 16-bit value */
-#define FXIDX_IDX 0x10000065
-
-/* This is the MPU port on the card (via the game port) */
-#define A_MUDATA1 0x70
-#define A_MUCMD1 0x71
-#define A_MUSTAT1 A_MUCMD1
-
-/* This is the MPU port on the Audigy Drive */
-#define A_MUDATA2 0x72
-#define A_MUCMD2 0x73
-#define A_MUSTAT2 A_MUCMD2
-
-/* The next two are the Audigy equivalent of FXWC */
-/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) */
-/* Each bit selects a channel for recording */
-#define A_FXWC1 0x74 /* Selects 0x7f-0x60 for FX recording */
-#define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */
-
-#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */
-#define A_SPDIF_48000 0x00000080
-#define A_SPDIF_44100 0x00000000
-#define A_SPDIF_96000 0x00000040
-
-#define A_FXRT2 0x7c
-#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */
-#define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */
-#define A_FXRT_CHANNELG 0x003f0000 /* Effects send bus number for channel's effects send G */
-#define A_FXRT_CHANNELH 0x3f000000 /* Effects send bus number for channel's effects send H */
-
-#define A_SENDAMOUNTS 0x7d
-#define A_FXSENDAMOUNT_E_MASK 0xff000000
-#define A_FXSENDAMOUNT_F_MASK 0x00ff0000
-#define A_FXSENDAMOUNT_G_MASK 0x0000ff00
-#define A_FXSENDAMOUNT_H_MASK 0x000000ff
-
-/* The send amounts for this one are the same as used with the emu10k1 */
-#define A_FXRT1 0x7e
-#define A_FXRT_CHANNELA 0x0000003f
-#define A_FXRT_CHANNELB 0x00003f00
-#define A_FXRT_CHANNELC 0x003f0000
-#define A_FXRT_CHANNELD 0x3f000000
-
-
-/* Each FX general purpose register is 32 bits in length, all bits are used */
-#define FXGPREGBASE 0x100 /* FX general purpose registers base */
-#define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */
-/* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is */
-/* decompressed back to 20 bits on a read. There are a total of 160 locations, the last 32 */
-/* locations are for external TRAM. */
-#define TANKMEMDATAREGBASE 0x200 /* Tank memory data registers base */
-#define TANKMEMDATAREG_MASK 0x000fffff /* 20 bit tank audio data field */
-
-/* Combined address field and memory opcode or flag field. 160 locations, last 32 are external */
-#define TANKMEMADDRREGBASE 0x300 /* Tank memory address registers base */
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */
-#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */
-#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */
-#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */
-#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */
-
-#define MICROCODEBASE 0x400 /* Microcode data base address */
-
-/* Each DSP microcode instruction is mapped into 2 doublewords */
-/* NOTE: When writing, always write the LO doubleword first. Reads can be in either order. */
-#define LOWORD_OPX_MASK 0x000ffc00 /* Instruction operand X */
-#define LOWORD_OPY_MASK 0x000003ff /* Instruction operand Y */
-#define HIWORD_OPCODE_MASK 0x00f00000 /* Instruction opcode */
-#define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */
-#define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */
-
-
-/* Audigy Soundcard have a different instruction format */
-#define AUDIGY_CODEBASE 0x600
-#define A_LOWORD_OPY_MASK 0x000007ff
-#define A_LOWORD_OPX_MASK 0x007ff000
-#define A_HIWORD_OPCODE_MASK 0x0f000000
-#define A_HIWORD_RESULT_MASK 0x007ff000
-#define A_HIWORD_OPA_MASK 0x000007ff
-
-
-#endif /* _8010_H */
diff --git a/sound/oss/emu10k1/Makefile b/sound/oss/emu10k1/Makefile
deleted file mode 100644
index b3af9ccb0579..000000000000
--- a/sound/oss/emu10k1/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Makefile for Creative Labs EMU10K1
-#
-# 12 Apr 2000 Rui Sousa
-
-obj-$(CONFIG_SOUND_EMU10K1) += emu10k1.o
-
-emu10k1-objs := audio.o cardmi.o cardmo.o cardwi.o cardwo.o ecard.o \
- efxmgr.o emuadxmg.o hwaccess.o irqmgr.o main.o midi.o \
- mixer.o passthrough.o recmgr.o timer.o voicemgr.o
-
-ifdef DEBUG
- EXTRA_CFLAGS += -DEMU10K1_DEBUG
-endif
-
-ifdef CONFIG_MIDI_EMU10K1
- EXTRA_CFLAGS += -DEMU10K1_SEQUENCER
-endif
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
deleted file mode 100644
index e75ea21eb811..000000000000
--- a/sound/oss/emu10k1/audio.c
+++ /dev/null
@@ -1,1595 +0,0 @@
-/*
- **********************************************************************
- * audio.c -- /dev/dsp interface for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up types/leaks
- *
- **********************************************************************
- *
- * 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/poll.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-
-#include "hwaccess.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "recmgr.h"
-#include "irqmgr.h"
-#include "audio.h"
-#include "8010.h"
-
-static void calculate_ofrag(struct woinst *);
-static void calculate_ifrag(struct wiinst *);
-
-static void emu10k1_waveout_bh(unsigned long refdata);
-static void emu10k1_wavein_bh(unsigned long refdata);
-
-/* Audio file operations */
-static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct wiinst *wiinst = wave_dev->wiinst;
- ssize_t ret = 0;
- unsigned long flags;
-
- DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count);
-
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (wiinst->mmapped) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return -ENXIO;
- }
-
- if (wiinst->state == WAVE_STATE_CLOSED) {
- calculate_ifrag(wiinst);
-
- while (emu10k1_wavein_open(wave_dev) < 0) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
- interruptible_sleep_on(&wave_dev->card->open_wait);
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&wiinst->lock, flags);
- }
- }
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- while (count > 0) {
- u32 bytestocopy;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (!(wiinst->state & WAVE_STATE_STARTED)
- && (wave_dev->enablebits & PCM_ENABLE_INPUT))
- emu10k1_wavein_start(wave_dev);
-
- emu10k1_wavein_update(wave_dev->card, wiinst);
- emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- DPD(3, "bytestocopy --> %d\n", bytestocopy);
-
- if ((bytestocopy >= wiinst->buffer.fragment_size)
- || (bytestocopy >= count)) {
- int rc;
-
- bytestocopy = min_t(u32, bytestocopy, count);
-
- rc = emu10k1_wavein_xferdata(wiinst,
- (u8 __user *)buffer,
- &bytestocopy);
- if (rc)
- return rc;
-
- count -= bytestocopy;
- buffer += bytestocopy;
- ret += bytestocopy;
- }
-
- if (count > 0) {
- if ((file->f_flags & O_NONBLOCK)
- || (!(wave_dev->enablebits & PCM_ENABLE_INPUT)))
- return (ret ? ret : -EAGAIN);
-
- interruptible_sleep_on(&wiinst->wait_queue);
-
- if (signal_pending(current))
- return (ret ? ret : -ERESTARTSYS);
-
- }
- }
-
- DPD(3, "bytes copied -> %d\n", (u32) ret);
-
- return ret;
-}
-
-static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct woinst *woinst = wave_dev->woinst;
- ssize_t ret;
- unsigned long flags;
-
- DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count);
-
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (woinst->mmapped) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return -ENXIO;
- }
- // This is for emu10k1 revs less than 7, we need to go through tram
- if (woinst->format.passthrough == 1) {
- int r;
-
- woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2;
- woinst->buffer.numfrags = PT_BLOCKCOUNT;
- calculate_ofrag(woinst);
-
- r = emu10k1_pt_write(file, buffer, count);
- spin_unlock_irqrestore(&woinst->lock, flags);
- return r;
- }
-
- if (woinst->state == WAVE_STATE_CLOSED) {
- calculate_ofrag(woinst);
-
- while (emu10k1_waveout_open(wave_dev) < 0) {
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
- interruptible_sleep_on(&wave_dev->card->open_wait);
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&woinst->lock, flags);
- }
- }
-
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- ret = 0;
- if (count % woinst->format.bytespersample)
- return -EINVAL;
-
- count /= woinst->num_voices;
-
- while (count > 0) {
- u32 bytestocopy;
-
- spin_lock_irqsave(&woinst->lock, flags);
- emu10k1_waveout_update(woinst);
- emu10k1_waveout_getxfersize(woinst, &bytestocopy);
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- DPD(3, "bytestocopy --> %d\n", bytestocopy);
-
- if ((bytestocopy >= woinst->buffer.fragment_size)
- || (bytestocopy >= count)) {
-
- bytestocopy = min_t(u32, bytestocopy, count);
-
- emu10k1_waveout_xferdata(woinst, (u8 __user *) buffer, &bytestocopy);
-
- count -= bytestocopy;
- buffer += bytestocopy * woinst->num_voices;
- ret += bytestocopy * woinst->num_voices;
-
- spin_lock_irqsave(&woinst->lock, flags);
- woinst->total_copied += bytestocopy;
-
- if (!(woinst->state & WAVE_STATE_STARTED)
- && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
- && (woinst->total_copied >= woinst->buffer.fragment_size))
- emu10k1_waveout_start(wave_dev);
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (count > 0) {
- if ((file->f_flags & O_NONBLOCK)
- || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT)))
- return (ret ? ret : -EAGAIN);
-
- interruptible_sleep_on(&woinst->wait_queue);
-
- if (signal_pending(current))
- return (ret ? ret : -ERESTARTSYS);
- }
- }
-
- DPD(3, "bytes copied -> %d\n", (u32) ret);
-
- return ret;
-}
-
-static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct woinst *woinst = NULL;
- struct wiinst *wiinst = NULL;
- int val = 0;
- u32 bytestocopy;
- unsigned long flags;
- int __user *p = (int __user *)arg;
-
- DPF(4, "emu10k1_audio_ioctl()\n");
-
- if (file->f_mode & FMODE_WRITE)
- woinst = wave_dev->woinst;
-
- if (file->f_mode & FMODE_READ)
- wiinst = wave_dev->wiinst;
-
- switch (cmd) {
- case OSS_GETVERSION:
- DPF(2, "OSS_GETVERSION:\n");
- return put_user(SOUND_VERSION, p);
-
- case SNDCTL_DSP_RESET:
- DPF(2, "SNDCTL_DSP_RESET:\n");
- wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;
-
- if (file->f_mode & FMODE_WRITE) {
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (woinst->state & WAVE_STATE_OPEN) {
- emu10k1_waveout_close(wave_dev);
- }
-
- woinst->mmapped = 0;
- woinst->total_copied = 0;
- woinst->total_played = 0;
- woinst->blocks = 0;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (file->f_mode & FMODE_READ) {
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (wiinst->state & WAVE_STATE_OPEN) {
- emu10k1_wavein_close(wave_dev);
- }
-
- wiinst->mmapped = 0;
- wiinst->total_recorded = 0;
- wiinst->blocks = 0;
- spin_unlock_irqrestore(&wiinst->lock, flags);
- }
-
- break;
-
- case SNDCTL_DSP_SYNC:
- DPF(2, "SNDCTL_DSP_SYNC:\n");
-
- if (file->f_mode & FMODE_WRITE) {
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (woinst->state & WAVE_STATE_OPEN) {
-
- if (woinst->state & WAVE_STATE_STARTED)
- while ((woinst->total_played < woinst->total_copied)
- && !signal_pending(current)) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- interruptible_sleep_on(&woinst->wait_queue);
- spin_lock_irqsave(&woinst->lock, flags);
- }
- emu10k1_waveout_close(wave_dev);
- }
-
- woinst->mmapped = 0;
- woinst->total_copied = 0;
- woinst->total_played = 0;
- woinst->blocks = 0;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (file->f_mode & FMODE_READ) {
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (wiinst->state & WAVE_STATE_OPEN) {
- emu10k1_wavein_close(wave_dev);
- }
-
- wiinst->mmapped = 0;
- wiinst->total_recorded = 0;
- wiinst->blocks = 0;
- spin_unlock_irqrestore(&wiinst->lock, flags);
- }
-
- break;
-
- case SNDCTL_DSP_SETDUPLEX:
- DPF(2, "SNDCTL_DSP_SETDUPLEX:\n");
- break;
-
- case SNDCTL_DSP_GETCAPS:
- DPF(2, "SNDCTL_DSP_GETCAPS:\n");
- return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
- DSP_CAP_TRIGGER | DSP_CAP_MMAP |
- DSP_CAP_COPROC| DSP_CAP_MULTI, p);
- case SNDCTL_DSP_SPEED:
- DPF(2, "SNDCTL_DSP_SPEED:\n");
-
- if (get_user(val, p))
- return -EFAULT;
-
- DPD(2, "val is %d\n", val);
-
- if (val > 0) {
- if (file->f_mode & FMODE_READ) {
- struct wave_format format;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- format = wiinst->format;
- format.samplingrate = val;
-
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return -EINVAL;
- }
-
- val = wiinst->format.samplingrate;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- DPD(2, "set recording sampling rate -> %d\n", val);
- }
-
- if (file->f_mode & FMODE_WRITE) {
- struct wave_format format;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- format = woinst->format;
- format.samplingrate = val;
-
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return -EINVAL;
- }
-
- val = woinst->format.samplingrate;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- DPD(2, "set playback sampling rate -> %d\n", val);
- }
-
- return put_user(val, p);
- } else {
- if (file->f_mode & FMODE_READ)
- val = wiinst->format.samplingrate;
- else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.samplingrate;
-
- return put_user(val, p);
- }
- break;
-
- case SNDCTL_DSP_STEREO:
- DPF(2, "SNDCTL_DSP_STEREO:\n");
-
- if (get_user(val, p))
- return -EFAULT;
-
- DPD(2, " val is %d\n", val);
-
- if (file->f_mode & FMODE_READ) {
- struct wave_format format;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- format = wiinst->format;
- format.channels = val ? 2 : 1;
-
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return -EINVAL;
- }
-
- val = wiinst->format.channels - 1;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- DPD(2, "set recording stereo -> %d\n", val);
- }
-
- if (file->f_mode & FMODE_WRITE) {
- struct wave_format format;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- format = woinst->format;
- format.channels = val ? 2 : 1;
-
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return -EINVAL;
- }
-
- val = woinst->format.channels - 1;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- DPD(2, "set playback stereo -> %d\n", val);
- }
-
- return put_user(val, p);
-
- break;
-
- case SNDCTL_DSP_CHANNELS:
- DPF(2, "SNDCTL_DSP_CHANNELS:\n");
-
- if (get_user(val, p))
- return -EFAULT;
-
- DPD(2, " val is %d\n", val);
-
- if (val > 0) {
- if (file->f_mode & FMODE_READ) {
- struct wave_format format;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- format = wiinst->format;
- format.channels = val;
-
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return -EINVAL;
- }
- val = wiinst->format.channels;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- DPD(2, "set recording number of channels -> %d\n", val);
- }
-
- if (file->f_mode & FMODE_WRITE) {
- struct wave_format format;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- format = woinst->format;
- format.channels = val;
-
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return -EINVAL;
- }
-
- val = woinst->format.channels;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- DPD(2, "set playback number of channels -> %d\n", val);
- }
-
- return put_user(val, p);
- } else {
- if (file->f_mode & FMODE_READ)
- val = wiinst->format.channels;
- else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.channels;
-
- return put_user(val, p);
- }
- break;
-
- case SNDCTL_DSP_GETFMTS:
- DPF(2, "SNDCTL_DSP_GETFMTS:\n");
-
- if (file->f_mode & FMODE_READ)
- val = AFMT_S16_LE;
- else if (file->f_mode & FMODE_WRITE) {
- val = AFMT_S16_LE | AFMT_U8;
- if (emu10k1_find_control_gpr(&wave_dev->card->mgr,
- wave_dev->card->pt.patch_name,
- wave_dev->card->pt.enable_gpr_name) >= 0)
- val |= AFMT_AC3;
- }
- return put_user(val, p);
-
- case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */
- DPF(2, "SNDCTL_DSP_SETFMT:\n");
-
- if (get_user(val, p))
- return -EFAULT;
-
- DPD(2, " val is %d\n", val);
-
- if (val != AFMT_QUERY) {
- if (file->f_mode & FMODE_READ) {
- struct wave_format format;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- format = wiinst->format;
- format.id = val;
-
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return -EINVAL;
- }
-
- val = wiinst->format.id;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- DPD(2, "set recording format -> %d\n", val);
- }
-
- if (file->f_mode & FMODE_WRITE) {
- struct wave_format format;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- format = woinst->format;
- format.id = val;
-
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return -EINVAL;
- }
-
- val = woinst->format.id;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- DPD(2, "set playback format -> %d\n", val);
- }
-
- return put_user(val, p);
- } else {
- if (file->f_mode & FMODE_READ)
- val = wiinst->format.id;
- else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.id;
-
- return put_user(val, p);
- }
- break;
-
- case SOUND_PCM_READ_BITS:
-
- if (file->f_mode & FMODE_READ)
- val = wiinst->format.bitsperchannel;
- else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.bitsperchannel;
-
- return put_user(val, p);
-
- case SOUND_PCM_READ_RATE:
-
- if (file->f_mode & FMODE_READ)
- val = wiinst->format.samplingrate;
- else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.samplingrate;
-
- return put_user(val, p);
-
- case SOUND_PCM_READ_CHANNELS:
-
- if (file->f_mode & FMODE_READ)
- val = wiinst->format.channels;
- else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.channels;
-
- return put_user(val, p);
-
- case SOUND_PCM_WRITE_FILTER:
- DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n");
- break;
-
- case SOUND_PCM_READ_FILTER:
- DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n");
- break;
-
- case SNDCTL_DSP_SETSYNCRO:
- DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n");
- break;
-
- case SNDCTL_DSP_GETTRIGGER:
- DPF(2, "SNDCTL_DSP_GETTRIGGER:\n");
-
- if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT))
- val |= PCM_ENABLE_OUTPUT;
-
- if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT))
- val |= PCM_ENABLE_INPUT;
-
- return put_user(val, p);
-
- case SNDCTL_DSP_SETTRIGGER:
- DPF(2, "SNDCTL_DSP_SETTRIGGER:\n");
-
- if (get_user(val, p))
- return -EFAULT;
-
- if (file->f_mode & FMODE_WRITE) {
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (val & PCM_ENABLE_OUTPUT) {
- wave_dev->enablebits |= PCM_ENABLE_OUTPUT;
- if (woinst->state & WAVE_STATE_OPEN)
- emu10k1_waveout_start(wave_dev);
- } else {
- wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT;
- if (woinst->state & WAVE_STATE_STARTED)
- emu10k1_waveout_stop(wave_dev);
- }
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (file->f_mode & FMODE_READ) {
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (val & PCM_ENABLE_INPUT) {
- wave_dev->enablebits |= PCM_ENABLE_INPUT;
- if (wiinst->state & WAVE_STATE_OPEN)
- emu10k1_wavein_start(wave_dev);
- } else {
- wave_dev->enablebits &= ~PCM_ENABLE_INPUT;
- if (wiinst->state & WAVE_STATE_STARTED)
- emu10k1_wavein_stop(wave_dev);
- }
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- }
- break;
-
- case SNDCTL_DSP_GETOSPACE:
- {
- audio_buf_info info;
-
- DPF(4, "SNDCTL_DSP_GETOSPACE:\n");
-
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (woinst->state & WAVE_STATE_OPEN) {
- emu10k1_waveout_update(woinst);
- emu10k1_waveout_getxfersize(woinst, &bytestocopy);
- info.bytes = bytestocopy;
- } else {
- calculate_ofrag(woinst);
- info.bytes = woinst->buffer.size;
- }
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- info.bytes *= woinst->num_voices;
- info.fragsize = woinst->buffer.fragment_size * woinst->num_voices;
- info.fragstotal = woinst->buffer.numfrags * woinst->num_voices;
- info.fragments = info.bytes / info.fragsize;
-
- if (copy_to_user(p, &info, sizeof(info)))
- return -EFAULT;
- }
- break;
-
- case SNDCTL_DSP_GETISPACE:
- {
- audio_buf_info info;
-
- DPF(4, "SNDCTL_DSP_GETISPACE:\n");
-
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
-
- spin_lock_irqsave(&wiinst->lock, flags);
- if (wiinst->state & WAVE_STATE_OPEN) {
- emu10k1_wavein_update(wave_dev->card, wiinst);
- emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
- info.bytes = bytestocopy;
- } else {
- calculate_ifrag(wiinst);
- info.bytes = 0;
- }
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- info.fragstotal = wiinst->buffer.numfrags;
- info.fragments = info.bytes / wiinst->buffer.fragment_size;
- info.fragsize = wiinst->buffer.fragment_size;
-
- if (copy_to_user(p, &info, sizeof(info)))
- return -EFAULT;
- }
- break;
-
- case SNDCTL_DSP_NONBLOCK:
- DPF(2, "SNDCTL_DSP_NONBLOCK:\n");
-
- file->f_flags |= O_NONBLOCK;
- break;
-
- case SNDCTL_DSP_GETODELAY:
- DPF(4, "SNDCTL_DSP_GETODELAY:\n");
-
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
-
- spin_lock_irqsave(&woinst->lock, flags);
- if (woinst->state & WAVE_STATE_OPEN) {
- emu10k1_waveout_update(woinst);
- emu10k1_waveout_getxfersize(woinst, &bytestocopy);
- val = woinst->buffer.size - bytestocopy;
- } else
- val = 0;
-
- val *= woinst->num_voices;
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- return put_user(val, p);
-
- case SNDCTL_DSP_GETIPTR:
- {
- count_info cinfo;
-
- DPF(4, "SNDCTL_DSP_GETIPTR: \n");
-
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (wiinst->state & WAVE_STATE_OPEN) {
- emu10k1_wavein_update(wave_dev->card, wiinst);
- cinfo.ptr = wiinst->buffer.hw_pos;
- cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size;
- cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks;
- wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size;
- } else {
- cinfo.ptr = 0;
- cinfo.bytes = 0;
- cinfo.blocks = 0;
- }
-
- if (wiinst->mmapped)
- wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- if (copy_to_user(p, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- }
- break;
-
- case SNDCTL_DSP_GETOPTR:
- {
- count_info cinfo;
-
- DPF(4, "SNDCTL_DSP_GETOPTR:\n");
-
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (woinst->state & WAVE_STATE_OPEN ||
- ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) {
- int num_fragments;
-
- if (woinst->format.passthrough == 1) {
- emu10k1_pt_waveout_update(wave_dev);
- cinfo.bytes = woinst->total_played;
- } else {
- emu10k1_waveout_update(woinst);
- cinfo.bytes = woinst->total_played;
- }
-
- cinfo.ptr = woinst->buffer.hw_pos;
- num_fragments = cinfo.bytes / woinst->buffer.fragment_size;
- cinfo.blocks = num_fragments - woinst->blocks;
- woinst->blocks = num_fragments;
-
- cinfo.bytes *= woinst->num_voices;
- cinfo.ptr *= woinst->num_voices;
- } else {
- cinfo.ptr = 0;
- cinfo.bytes = 0;
- cinfo.blocks = 0;
- }
-
- if (woinst->mmapped)
- woinst->buffer.free_bytes %= woinst->buffer.fragment_size;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- if (copy_to_user(p, &cinfo, sizeof(cinfo)))
- return -EFAULT;
- }
- break;
-
- case SNDCTL_DSP_GETBLKSIZE:
- DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n");
-
- if (file->f_mode & FMODE_WRITE) {
- spin_lock_irqsave(&woinst->lock, flags);
-
- calculate_ofrag(woinst);
- val = woinst->buffer.fragment_size * woinst->num_voices;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (file->f_mode & FMODE_READ) {
- spin_lock_irqsave(&wiinst->lock, flags);
-
- calculate_ifrag(wiinst);
- val = wiinst->buffer.fragment_size;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- }
-
- return put_user(val, p);
-
- break;
-
- case SNDCTL_DSP_POST:
- if (file->f_mode & FMODE_WRITE) {
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (!(woinst->state & WAVE_STATE_STARTED)
- && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
- && (woinst->total_copied > 0))
- emu10k1_waveout_start(wave_dev);
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- break;
-
- case SNDCTL_DSP_SUBDIVIDE:
- DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n");
- break;
-
- case SNDCTL_DSP_SETFRAGMENT:
- DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n");
-
- if (get_user(val, p))
- return -EFAULT;
-
- DPD(2, "val is %#x\n", val);
-
- if (val == 0)
- return -EIO;
-
- if (file->f_mode & FMODE_WRITE) {
- /* digital pass-through fragment count and size are fixed values */
- if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1))
- return -EINVAL; /* too late to change */
-
- woinst->buffer.ossfragshift = val & 0xffff;
- woinst->buffer.numfrags = (val >> 16) & 0xffff;
- }
-
- if (file->f_mode & FMODE_READ) {
- if (wiinst->state & WAVE_STATE_OPEN)
- return -EINVAL; /* too late to change */
-
- wiinst->buffer.ossfragshift = val & 0xffff;
- wiinst->buffer.numfrags = (val >> 16) & 0xffff;
- }
-
- break;
-
- case SNDCTL_COPR_LOAD:
- {
- copr_buffer *buf;
- u32 i;
-
- DPF(4, "SNDCTL_COPR_LOAD:\n");
-
- buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- if (copy_from_user(buf, p, sizeof(copr_buffer))) {
- kfree (buf);
- return -EFAULT;
- }
-
- if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) {
- kfree (buf);
- return -EINVAL;
- }
-
- if (buf->command == CMD_WRITE) {
-
-#ifdef DBGEMU
- if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
-#else
- if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000)
- ) && !(
- //any register allowed raw access to users goes here:
- (buf->offs == DBG ||
- buf->offs == A_DBG)
- && (buf->len == 1))) {
-#endif
- kfree(buf);
- return -EINVAL;
- }
- } else {
- if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
- kfree(buf);
- return -EINVAL;
- }
- }
-
- if (((unsigned)buf->flags) > 0x3f)
- buf->flags = 0;
-
- if (buf->command == CMD_READ) {
- for (i = 0; i < buf->len; i++)
- ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags);
-
- if (copy_to_user(p, buf, sizeof(copr_buffer))) {
- kfree(buf);
- return -EFAULT;
- }
- } else {
- for (i = 0; i < buf->len; i++)
- sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]);
- }
-
- kfree (buf);
- break;
- }
-
- default: /* Default is unrecognized command */
- DPD(2, "default: %#x\n", cmd);
- return -EINVAL;
- }
- return 0;
-}
-
-static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type)
-{
- struct emu10k1_wavedevice *wave_dev = vma->vm_private_data;
- struct woinst *woinst = wave_dev->woinst;
- struct wiinst *wiinst = wave_dev->wiinst;
- struct page *dmapage;
- unsigned long pgoff;
- int rd, wr;
-
- DPF(3, "emu10k1_mm_nopage()\n");
- DPD(3, "addr: %#lx\n", address);
-
- if (address > vma->vm_end) {
- DPF(1, "EXIT, returning NOPAGE_SIGBUS\n");
- return NOPAGE_SIGBUS; /* Disallow mremap */
- }
-
- pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
- if (woinst != NULL)
- wr = woinst->mmapped;
- else
- wr = 0;
-
- if (wiinst != NULL)
- rd = wiinst->mmapped;
- else
- rd = 0;
-
- /* if full-duplex (read+write) and we have two sets of bufs,
- * then the playback buffers come first, sez soundcard.c */
- if (wr) {
- if (pgoff >= woinst->buffer.pages) {
- pgoff -= woinst->buffer.pages;
- dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
- } else
- dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]);
- } else {
- dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
- }
-
- get_page (dmapage);
-
- DPD(3, "page: %#lx\n", (unsigned long) dmapage);
- if (type)
- *type = VM_FAULT_MINOR;
- return dmapage;
-}
-
-static struct vm_operations_struct emu10k1_mm_ops = {
- .nopage = emu10k1_mm_nopage,
-};
-
-static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- unsigned long max_pages, n_pages, pgoffset;
- struct woinst *woinst = NULL;
- struct wiinst *wiinst = NULL;
- unsigned long flags;
-
- DPF(2, "emu10k1_audio_mmap()\n");
-
- max_pages = 0;
- if (vma->vm_flags & VM_WRITE) {
- woinst = wave_dev->woinst;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- /* No m'mapping possible for multichannel */
- if (woinst->num_voices > 1) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return -EINVAL;
- }
-
- if (woinst->state == WAVE_STATE_CLOSED) {
- calculate_ofrag(woinst);
-
- if (emu10k1_waveout_open(wave_dev) < 0) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- ERROR();
- return -EINVAL;
- }
- }
-
- woinst->mmapped = 1;
- max_pages += woinst->buffer.pages;
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (vma->vm_flags & VM_READ) {
- wiinst = wave_dev->wiinst;
-
- spin_lock_irqsave(&wiinst->lock, flags);
- if (wiinst->state == WAVE_STATE_CLOSED) {
- calculate_ifrag(wiinst);
-
- if (emu10k1_wavein_open(wave_dev) < 0) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- ERROR();
- return -EINVAL;
- }
- }
-
- wiinst->mmapped = 1;
- max_pages += wiinst->buffer.pages;
- spin_unlock_irqrestore(&wiinst->lock, flags);
- }
-
- n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT;
- pgoffset = vma->vm_pgoff;
-
- DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset);
- DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages);
-
- if (pgoffset + n_pages > max_pages)
- return -EINVAL;
-
- vma->vm_flags |= VM_RESERVED;
- vma->vm_ops = &emu10k1_mm_ops;
- vma->vm_private_data = wave_dev;
- return 0;
-}
-
-static int emu10k1_audio_open(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- struct emu10k1_card *card = NULL;
- struct list_head *entry;
- struct emu10k1_wavedevice *wave_dev;
-
- DPF(2, "emu10k1_audio_open()\n");
-
- /* Check for correct device to open */
-
- list_for_each(entry, &emu10k1_devs) {
- card = list_entry(entry, struct emu10k1_card, list);
-
- if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf))
- goto match;
- }
-
- return -ENODEV;
-
-match:
-
- wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
-
- if (wave_dev == NULL) {
- ERROR();
- return -ENOMEM;
- }
-
- wave_dev->card = card;
- wave_dev->wiinst = NULL;
- wave_dev->woinst = NULL;
- wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; /* Default */
-
- if (file->f_mode & FMODE_READ) {
- /* Recording */
- struct wiinst *wiinst;
-
- if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
- ERROR();
- kfree(wave_dev);
- return -ENOMEM;
- }
-
- wiinst->recsrc = card->wavein.recsrc;
- wiinst->fxwc = card->wavein.fxwc;
-
- switch (wiinst->recsrc) {
- case WAVERECORD_AC97:
- wiinst->format.id = AFMT_S16_LE;
- wiinst->format.samplingrate = 8000;
- wiinst->format.bitsperchannel = 16;
- wiinst->format.channels = 1;
- break;
- case WAVERECORD_MIC:
- wiinst->format.id = AFMT_S16_LE;
- wiinst->format.samplingrate = 8000;
- wiinst->format.bitsperchannel = 16;
- wiinst->format.channels = 1;
- break;
- case WAVERECORD_FX:
- wiinst->format.id = AFMT_S16_LE;
- wiinst->format.samplingrate = 48000;
- wiinst->format.bitsperchannel = 16;
- wiinst->format.channels = hweight32(wiinst->fxwc);
- break;
- default:
- kfree(wave_dev);
- kfree(wiinst);
- BUG();
- break;
- }
-
- wiinst->state = WAVE_STATE_CLOSED;
-
- wiinst->buffer.ossfragshift = 0;
- wiinst->buffer.fragment_size = 0;
- wiinst->buffer.numfrags = 0;
-
- init_waitqueue_head(&wiinst->wait_queue);
-
- wiinst->mmapped = 0;
- wiinst->total_recorded = 0;
- wiinst->blocks = 0;
- spin_lock_init(&wiinst->lock);
- tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev);
- wave_dev->wiinst = wiinst;
- emu10k1_wavein_setformat(wave_dev, &wiinst->format);
- }
-
- if (file->f_mode & FMODE_WRITE) {
- struct woinst *woinst;
- int i;
-
- if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
- ERROR();
- kfree(wave_dev);
- return -ENOMEM;
- }
-
- if (wave_dev->wiinst != NULL) {
- woinst->format = wave_dev->wiinst->format;
- } else {
- woinst->format.id = AFMT_U8;
- woinst->format.samplingrate = 8000;
- woinst->format.bitsperchannel = 8;
- woinst->format.channels = 1;
- }
-
- woinst->state = WAVE_STATE_CLOSED;
-
- woinst->buffer.fragment_size = 0;
- woinst->buffer.ossfragshift = 0;
- woinst->buffer.numfrags = 0;
- woinst->device = (card->audio_dev1 == minor);
- woinst->timer.state = TIMER_STATE_UNINSTALLED;
- woinst->num_voices = 1;
- for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
- woinst->voice[i].usage = VOICE_USAGE_FREE;
- woinst->voice[i].mem.emupageindex = -1;
- }
-
- init_waitqueue_head(&woinst->wait_queue);
-
- woinst->mmapped = 0;
- woinst->total_copied = 0;
- woinst->total_played = 0;
- woinst->blocks = 0;
- spin_lock_init(&woinst->lock);
- tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev);
- wave_dev->woinst = woinst;
- emu10k1_waveout_setformat(wave_dev, &woinst->format);
- }
-
- file->private_data = (void *) wave_dev;
-
- return nonseekable_open(inode, file);
-}
-
-static int emu10k1_audio_release(struct inode *inode, struct file *file)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct emu10k1_card *card;
- unsigned long flags;
-
- card = wave_dev->card;
-
- DPF(2, "emu10k1_audio_release()\n");
-
- if (file->f_mode & FMODE_WRITE) {
- struct woinst *woinst = wave_dev->woinst;
-
- spin_lock_irqsave(&woinst->lock, flags);
- if(woinst->format.passthrough==2)
- card->pt.state=PT_STATE_PLAYING;
- if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){
- spin_lock(&card->pt.lock);
- emu10k1_pt_stop(card);
- spin_unlock(&card->pt.lock);
- }
- if (woinst->state & WAVE_STATE_OPEN) {
- if (woinst->state & WAVE_STATE_STARTED) {
- if (!(file->f_flags & O_NONBLOCK)) {
- while (!signal_pending(current)
- && (woinst->total_played < woinst->total_copied)) {
- DPF(4, "Buffer hasn't been totally played, sleep....\n");
- spin_unlock_irqrestore(&woinst->lock, flags);
- interruptible_sleep_on(&woinst->wait_queue);
- spin_lock_irqsave(&woinst->lock, flags);
- }
- }
- }
- emu10k1_waveout_close(wave_dev);
- }
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- /* remove the tasklet */
- tasklet_kill(&woinst->timer.tasklet);
- kfree(wave_dev->woinst);
- }
-
- if (file->f_mode & FMODE_READ) {
- struct wiinst *wiinst = wave_dev->wiinst;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (wiinst->state & WAVE_STATE_OPEN) {
- emu10k1_wavein_close(wave_dev);
- }
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- tasklet_kill(&wiinst->timer.tasklet);
- kfree(wave_dev->wiinst);
- }
-
- kfree(wave_dev);
-
- if (waitqueue_active(&card->open_wait))
- wake_up_interruptible(&card->open_wait);
-
- return 0;
-}
-
-/* FIXME sort out poll() + mmap() */
-static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct woinst *woinst = wave_dev->woinst;
- struct wiinst *wiinst = wave_dev->wiinst;
- unsigned int mask = 0;
- u32 bytestocopy;
- unsigned long flags;
-
- DPF(4, "emu10k1_audio_poll()\n");
-
- if (file->f_mode & FMODE_WRITE)
- poll_wait(file, &woinst->wait_queue, wait);
-
- if (file->f_mode & FMODE_READ)
- poll_wait(file, &wiinst->wait_queue, wait);
-
- if (file->f_mode & FMODE_WRITE) {
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (woinst->state & WAVE_STATE_OPEN) {
- emu10k1_waveout_update(woinst);
- emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-
- if (bytestocopy >= woinst->buffer.fragment_size)
- mask |= POLLOUT | POLLWRNORM;
- } else
- mask |= POLLOUT | POLLWRNORM;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
- }
-
- if (file->f_mode & FMODE_READ) {
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (wiinst->state & WAVE_STATE_OPEN) {
- emu10k1_wavein_update(wave_dev->card, wiinst);
- emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
- if (bytestocopy >= wiinst->buffer.fragment_size)
- mask |= POLLIN | POLLRDNORM;
- }
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
- }
-
- return mask;
-}
-
-static void calculate_ofrag(struct woinst *woinst)
-{
- struct waveout_buffer *buffer = &woinst->buffer;
- u32 fragsize;
-
- if (buffer->fragment_size)
- return;
-
- if (!buffer->ossfragshift) {
- fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
-
- while (fragsize) {
- fragsize >>= 1;
- buffer->ossfragshift++;
- }
- }
-
- if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT)
- buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT;
-
- buffer->fragment_size = 1 << buffer->ossfragshift;
-
- while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE)
- buffer->fragment_size >>= 1;
-
- /* now we are sure that:
- (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS)
- */
-
- if (!buffer->numfrags) {
- u32 numfrags;
-
- numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) /
- (buffer->fragment_size * 1000) - 1;
-
- buffer->numfrags = 1;
-
- while (numfrags) {
- numfrags >>= 1;
- buffer->numfrags <<= 1;
- }
- }
-
- if (buffer->numfrags < WAVEOUT_MINFRAGS)
- buffer->numfrags = WAVEOUT_MINFRAGS;
-
- if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE)
- buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size;
-
- if (buffer->numfrags < WAVEOUT_MINFRAGS)
- BUG();
-
- buffer->size = buffer->fragment_size * buffer->numfrags;
- buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-
- DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size);
- DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags);
-
- return;
-}
-
-static void calculate_ifrag(struct wiinst *wiinst)
-{
- struct wavein_buffer *buffer = &wiinst->buffer;
- u32 fragsize, bufsize, size[4];
- int i, j;
-
- if (buffer->fragment_size)
- return;
-
- if (!buffer->ossfragshift) {
- fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1;
-
- while (fragsize) {
- fragsize >>= 1;
- buffer->ossfragshift++;
- }
- }
-
- if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT)
- buffer->ossfragshift = WAVEIN_MINFRAGSHIFT;
-
- buffer->fragment_size = 1 << buffer->ossfragshift;
-
- while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE)
- buffer->fragment_size >>= 1;
-
- /* now we are sure that:
- (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS)
- */
-
-
- if (!buffer->numfrags)
- buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
-
- if (buffer->numfrags < WAVEIN_MINFRAGS)
- buffer->numfrags = WAVEIN_MINFRAGS;
-
- if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE)
- buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size;
-
- if (buffer->numfrags < WAVEIN_MINFRAGS)
- BUG();
-
- bufsize = buffer->fragment_size * buffer->numfrags;
-
- /* the buffer size for recording is restricted to certain values, adjust it now */
- if (bufsize >= 0x10000) {
- buffer->size = 0x10000;
- buffer->sizeregval = 0x1f;
- } else {
- buffer->size = 0;
- size[0] = 384;
- size[1] = 448;
- size[2] = 512;
- size[3] = 640;
-
- for (i = 0; i < 8; i++)
- for (j = 0; j < 4; j++)
- if (bufsize >= size[j]) {
- buffer->size = size[j];
- size[j] *= 2;
- buffer->sizeregval = i * 4 + j + 1;
- } else
- goto exitloop;
- exitloop:
- if (buffer->size == 0) {
- buffer->size = 384;
- buffer->sizeregval = 0x01;
- }
- }
-
- /* adjust the fragment size so that buffer size is an integer multiple */
- while (buffer->size % buffer->fragment_size)
- buffer->fragment_size >>= 1;
-
- buffer->numfrags = buffer->size / buffer->fragment_size;
- buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
-
- DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size);
- DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags);
- DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval);
-
- return;
-}
-
-static void emu10k1_wavein_bh(unsigned long refdata)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
- struct wiinst *wiinst = wave_dev->wiinst;
- u32 bytestocopy;
- unsigned long flags;
-
- if (!wiinst)
- return;
-
- spin_lock_irqsave(&wiinst->lock, flags);
-
- if (!(wiinst->state & WAVE_STATE_STARTED)) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return;
- }
-
- emu10k1_wavein_update(wave_dev->card, wiinst);
- emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- if (bytestocopy >= wiinst->buffer.fragment_size) {
- if (waitqueue_active(&wiinst->wait_queue))
- wake_up_interruptible(&wiinst->wait_queue);
- } else
- DPD(3, "Not enough transfer size, %d\n", bytestocopy);
-
- return;
-}
-
-static void emu10k1_waveout_bh(unsigned long refdata)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
- struct woinst *woinst = wave_dev->woinst;
- u32 bytestocopy;
- unsigned long flags;
-
- if (!woinst)
- return;
-
- spin_lock_irqsave(&woinst->lock, flags);
-
- if (!(woinst->state & WAVE_STATE_STARTED)) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return;
- }
-
- emu10k1_waveout_update(woinst);
- emu10k1_waveout_getxfersize(woinst, &bytestocopy);
-
- if (woinst->buffer.fill_silence) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- emu10k1_waveout_fillsilence(woinst);
- } else
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- if (bytestocopy >= woinst->buffer.fragment_size) {
- if (waitqueue_active(&woinst->wait_queue))
- wake_up_interruptible(&woinst->wait_queue);
- } else
- DPD(3, "Not enough transfer size -> %d\n", bytestocopy);
-
- return;
-}
-
-const struct file_operations emu10k1_audio_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = emu10k1_audio_read,
- .write = emu10k1_audio_write,
- .poll = emu10k1_audio_poll,
- .ioctl = emu10k1_audio_ioctl,
- .mmap = emu10k1_audio_mmap,
- .open = emu10k1_audio_open,
- .release = emu10k1_audio_release,
-};
diff --git a/sound/oss/emu10k1/audio.h b/sound/oss/emu10k1/audio.h
deleted file mode 100644
index 26ee81bbd6c6..000000000000
--- a/sound/oss/emu10k1/audio.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- **********************************************************************
- * audio.c -- /dev/dsp interface for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up types/leaks
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _AUDIO_H
-#define _AUDIO_H
-
-struct emu10k1_wavedevice
-{
- struct emu10k1_card *card;
- struct wiinst *wiinst;
- struct woinst *woinst;
- u16 enablebits;
-};
-
-#endif /* _AUDIO_H */
diff --git a/sound/oss/emu10k1/cardmi.c b/sound/oss/emu10k1/cardmi.c
deleted file mode 100644
index 57674f8c8a2e..000000000000
--- a/sound/oss/emu10k1/cardmi.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- **********************************************************************
- * sblive_mi.c - MIDI UART input HAL for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox clean up
- *
- **********************************************************************
- *
- * 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/slab.h>
-#include <linux/jiffies.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmi.h"
-#include "irqmgr.h"
-
-
-static int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned long data, u32 bytesvalid);
-
-static int sblive_miStateInit(struct emu10k1_mpuin *);
-static int sblive_miStateEntry(struct emu10k1_mpuin *, u8);
-static int sblive_miStateParse(struct emu10k1_mpuin *, u8);
-static int sblive_miState3Byte(struct emu10k1_mpuin *, u8);
-static int sblive_miState3ByteKey(struct emu10k1_mpuin *, u8);
-static int sblive_miState3ByteVel(struct emu10k1_mpuin *, u8);
-static int sblive_miState2Byte(struct emu10k1_mpuin *, u8);
-static int sblive_miState2ByteKey(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon2(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysExNorm(struct emu10k1_mpuin *, u8);
-static int sblive_miStateSysReal(struct emu10k1_mpuin *, u8);
-
-
-static struct {
- int (*Fn) (struct emu10k1_mpuin *, u8);
-} midistatefn[] = {
-
- {
- sblive_miStateParse}, {
- sblive_miState3Byte}, /* 0x8n, 0x9n, 0xAn, 0xBn, 0xEn */
- {
- sblive_miState3ByteKey}, /* Byte 1 */
- {
- sblive_miState3ByteVel}, /* Byte 2 */
- {
- sblive_miState2Byte}, /* 0xCn, 0xDn */
- {
- sblive_miState2ByteKey}, /* Byte 1 */
- {
- sblive_miStateSysCommon2}, /* 0xF1 , 0xF3 */
- {
- sblive_miStateSysCommon2Key}, /* 0xF1 , 0xF3, Byte 1 */
- {
- sblive_miStateSysCommon3}, /* 0xF2 */
- {
- sblive_miStateSysCommon3Key}, /* 0xF2 , Byte 1 */
- {
- sblive_miStateSysCommon3Vel}, /* 0xF2 , Byte 2 */
- {
- sblive_miStateSysExNorm}, /* 0xF0, 0xF7, Normal mode */
- {
- sblive_miStateSysReal} /* 0xF4 - 0xF6 ,0xF8 - 0xFF */
-};
-
-
-/* Installs the IRQ handler for the MPU in port */
-
-/* and initialize parameters */
-
-int emu10k1_mpuin_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
-{
- struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
- DPF(2, "emu10k1_mpuin_open\n");
-
- if (!(card_mpuin->status & FLAGS_AVAILABLE))
- return -1;
-
- /* Copy open info and mark channel as in use */
- card_mpuin->openinfo = *openinfo;
- card_mpuin->status &= ~FLAGS_AVAILABLE; /* clear */
- card_mpuin->status |= FLAGS_READY; /* set */
- card_mpuin->status &= ~FLAGS_MIDM_STARTED; /* clear */
- card_mpuin->firstmidiq = NULL;
- card_mpuin->lastmidiq = NULL;
- card_mpuin->qhead = 0;
- card_mpuin->qtail = 0;
-
- sblive_miStateInit(card_mpuin);
-
- emu10k1_mpu_reset(card);
- emu10k1_mpu_acquire(card);
-
- return 0;
-}
-
-int emu10k1_mpuin_close(struct emu10k1_card *card)
-{
- struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
- DPF(2, "emu10k1_mpuin_close()\n");
-
- /* Check if there are pending input SysEx buffers */
- if (card_mpuin->firstmidiq != NULL) {
- ERROR();
- return -1;
- }
-
- /* Disable RX interrupt */
- emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
- emu10k1_mpu_release(card);
-
- card_mpuin->status |= FLAGS_AVAILABLE; /* set */
- card_mpuin->status &= ~FLAGS_MIDM_STARTED; /* clear */
-
- return 0;
-}
-
-/* Adds MIDI buffer to local queue list */
-
-int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *card_mpuin, struct midi_hdr *midihdr)
-{
- struct midi_queue *midiq;
- unsigned long flags;
-
- DPF(2, "emu10k1_mpuin_add_buffer()\n");
-
- /* Update MIDI buffer flags */
- midihdr->flags |= MIDIBUF_INQUEUE; /* set */
- midihdr->flags &= ~MIDIBUF_DONE; /* clear */
-
- if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
- /* Message lost */
- return -1;
- }
-
- midiq->next = NULL;
- midiq->qtype = 1;
- midiq->length = midihdr->bufferlength;
- midiq->sizeLeft = midihdr->bufferlength;
- midiq->midibyte = midihdr->data;
- midiq->refdata = (unsigned long) midihdr;
-
- spin_lock_irqsave(&card_mpuin->lock, flags);
-
- if (card_mpuin->firstmidiq == NULL) {
- card_mpuin->firstmidiq = midiq;
- card_mpuin->lastmidiq = midiq;
- } else {
- (card_mpuin->lastmidiq)->next = midiq;
- card_mpuin->lastmidiq = midiq;
- }
-
- spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
- return 0;
-}
-
-/* First set the Time Stamp if MIDI IN has not started. */
-
-/* Then enable RX Irq. */
-
-int emu10k1_mpuin_start(struct emu10k1_card *card)
-{
- struct emu10k1_mpuin *card_mpuin = card->mpuin;
- u8 dummy;
-
- DPF(2, "emu10k1_mpuin_start()\n");
-
- /* Set timestamp if not set */
- if (card_mpuin->status & FLAGS_MIDM_STARTED) {
- DPF(2, "Time Stamp not changed\n");
- } else {
- while (!emu10k1_mpu_read_data(card, &dummy));
-
- card_mpuin->status |= FLAGS_MIDM_STARTED; /* set */
-
- /* Set new time stamp */
- card_mpuin->timestart = (jiffies * 1000) / HZ;
- DPD(2, "New Time Stamp = %d\n", card_mpuin->timestart);
-
- card_mpuin->qhead = 0;
- card_mpuin->qtail = 0;
-
- emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
- }
-
- return 0;
-}
-
-/* Disable the RX Irq. If a partial recorded buffer */
-
-/* exist, send it up to IMIDI level. */
-
-int emu10k1_mpuin_stop(struct emu10k1_card *card)
-{
- struct emu10k1_mpuin *card_mpuin = card->mpuin;
- struct midi_queue *midiq;
- unsigned long flags;
-
- DPF(2, "emu10k1_mpuin_stop()\n");
-
- emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
- card_mpuin->status &= ~FLAGS_MIDM_STARTED; /* clear */
-
- if (card_mpuin->firstmidiq) {
- spin_lock_irqsave(&card_mpuin->lock, flags);
-
- midiq = card_mpuin->firstmidiq;
- if (midiq != NULL) {
- if (midiq->sizeLeft == midiq->length)
- midiq = NULL;
- else {
- card_mpuin->firstmidiq = midiq->next;
- if (card_mpuin->firstmidiq == NULL)
- card_mpuin->lastmidiq = NULL;
- }
- }
-
- spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
- if (midiq) {
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
- kfree(midiq);
- }
- }
-
- return 0;
-}
-
-/* Disable the RX Irq. If any buffer */
-
-/* exist, send it up to IMIDI level. */
-int emu10k1_mpuin_reset(struct emu10k1_card *card)
-{
- struct emu10k1_mpuin *card_mpuin = card->mpuin;
- struct midi_queue *midiq;
-
- DPF(2, "emu10k1_mpuin_reset()\n");
-
- emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
-
- while (card_mpuin->firstmidiq) {
- midiq = card_mpuin->firstmidiq;
- card_mpuin->firstmidiq = midiq->next;
-
- if (midiq->sizeLeft == midiq->length)
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
- else
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-
- kfree(midiq);
- }
-
- card_mpuin->lastmidiq = NULL;
- card_mpuin->status &= ~FLAGS_MIDM_STARTED;
-
- return 0;
-}
-
-/* Passes the message with the data back to the client */
-
-/* via IRQ & DPC callbacks to Ring 3 */
-static int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned long data, u32 bytesvalid)
-{
- unsigned long timein;
- struct midi_queue *midiq;
- unsigned long callback_msg[3];
- struct midi_hdr *midihdr;
-
- /* Called during ISR. The data & code touched are:
- * 1. card_mpuin
- * 2. The function to be called
- */
-
- timein = card_mpuin->timein;
- if (card_mpuin->timestart <= timein)
- callback_msg[0] = timein - card_mpuin->timestart;
- else
- callback_msg[0] = (~0x0L - card_mpuin->timestart) + timein;
-
- if (msg == ICARDMIDI_INDATA || msg == ICARDMIDI_INDATAERROR) {
- callback_msg[1] = data;
- callback_msg[2] = bytesvalid;
- DPD(2, "emu10k1_mpuin_callback: midimsg = %#lx\n", data);
- } else {
- midiq = (struct midi_queue *) data;
- midihdr = (struct midi_hdr *) midiq->refdata;
-
- callback_msg[1] = midiq->length - midiq->sizeLeft;
- callback_msg[2] = midiq->refdata;
- midihdr->flags &= ~MIDIBUF_INQUEUE;
- midihdr->flags |= MIDIBUF_DONE;
-
- midihdr->bytesrecorded = midiq->length - midiq->sizeLeft;
- }
-
- /* Notify client that Sysex buffer has been sent */
- emu10k1_midi_callback(msg, card_mpuin->openinfo.refdata, callback_msg);
-
- return 0;
-}
-
-void emu10k1_mpuin_bh(unsigned long refdata)
-{
- u8 data;
- unsigned idx;
- struct emu10k1_mpuin *card_mpuin = (struct emu10k1_mpuin *) refdata;
- unsigned long flags;
-
- while (card_mpuin->qhead != card_mpuin->qtail) {
- spin_lock_irqsave(&card_mpuin->lock, flags);
- idx = card_mpuin->qhead;
- data = card_mpuin->midiq[idx].data;
- card_mpuin->timein = card_mpuin->midiq[idx].timein;
- idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
- card_mpuin->qhead = idx;
- spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
- sblive_miStateEntry(card_mpuin, data);
- }
-
- return;
-}
-
-/* IRQ callback handler routine for the MPU in port */
-
-int emu10k1_mpuin_irqhandler(struct emu10k1_card *card)
-{
- unsigned idx;
- unsigned count;
- u8 MPUIvalue;
- struct emu10k1_mpuin *card_mpuin = card->mpuin;
-
- /* IRQ service routine. The data and code touched are:
- * 1. card_mpuin
- */
-
- count = 0;
- idx = card_mpuin->qtail;
-
- while (1) {
- if (emu10k1_mpu_read_data(card, &MPUIvalue) < 0) {
- break;
- } else {
- ++count;
- card_mpuin->midiq[idx].data = MPUIvalue;
- card_mpuin->midiq[idx].timein = (jiffies * 1000) / HZ;
- idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
- }
- }
-
- if (count) {
- card_mpuin->qtail = idx;
-
- tasklet_hi_schedule(&card_mpuin->tasklet);
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-/* Supporting functions for Midi-In Interpretation State Machine */
-
-/*****************************************************************************/
-
-/* FIXME: This should be a macro */
-static int sblive_miStateInit(struct emu10k1_mpuin *card_mpuin)
-{
- card_mpuin->status = 0; /* For MIDI running status */
- card_mpuin->fstatus = 0; /* For 0xFn status only */
- card_mpuin->curstate = STIN_PARSE;
- card_mpuin->laststate = STIN_PARSE;
- card_mpuin->data = 0;
- card_mpuin->timestart = 0;
- card_mpuin->timein = 0;
-
- return 0;
-}
-
-/* FIXME: This should be a macro */
-static int sblive_miStateEntry(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
-}
-
-static int sblive_miStateParse(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- switch (data & 0xf0) {
- case 0x80:
- case 0x90:
- case 0xA0:
- case 0xB0:
- case 0xE0:
- card_mpuin->curstate = STIN_3BYTE;
- break;
-
- case 0xC0:
- case 0xD0:
- card_mpuin->curstate = STIN_2BYTE;
- break;
-
- case 0xF0:
- /* System messages do not affect the previous running status! */
- switch (data & 0x0f) {
- case 0x0:
- card_mpuin->laststate = card_mpuin->curstate;
- card_mpuin->curstate = STIN_SYS_EX_NORM;
-
- if (card_mpuin->firstmidiq) {
- struct midi_queue *midiq;
-
- midiq = card_mpuin->firstmidiq;
- *midiq->midibyte = data;
- --midiq->sizeLeft;
- ++midiq->midibyte;
- }
-
- return CTSTATUS_NEXT_BYTE;
-
- case 0x7:
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, 0xf7, 0);
- return -1;
-
- case 0x2:
- card_mpuin->laststate = card_mpuin->curstate;
- card_mpuin->curstate = STIN_SYS_COMMON_3;
- break;
-
- case 0x1:
- case 0x3:
- card_mpuin->laststate = card_mpuin->curstate;
- card_mpuin->curstate = STIN_SYS_COMMON_2;
- break;
-
- default:
- /* includes 0xF4 - 0xF6, 0xF8 - 0xFF */
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
- }
-
- break;
-
- default:
- DPF(2, "BUG: default case hit\n");
- return -1;
- }
-
- return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
-}
-
-static int sblive_miState3Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- u8 temp = data & 0xf0;
-
- if (temp < 0x80) {
- return midistatefn[STIN_3BYTE_KEY].Fn(card_mpuin, data);
- } else if (temp <= 0xe0 && temp != 0xc0 && temp != 0xd0) {
- card_mpuin->status = data;
- card_mpuin->curstate = STIN_3BYTE_KEY;
-
- return CTSTATUS_NEXT_BYTE;
- }
-
- return midistatefn[STIN_PARSE].Fn(card_mpuin, data);
-}
-
-static int sblive_miState3ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
- unsigned long tmp;
-
- if (data > 0x7f) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = STIN_PARSE;
- tmp = ((unsigned long) data) << 8;
- tmp |= (unsigned long) card_mpuin->status;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
- return -1;
- }
-
- card_mpuin->data = data;
- card_mpuin->curstate = STIN_3BYTE_VEL;
-
- return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miState3ByteVel(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 2 */
-{
- unsigned long tmp;
-
- if (data > 0x7f) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = STIN_PARSE;
- tmp = ((unsigned long) data) << 8;
- tmp |= card_mpuin->data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->status;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
- return -1;
- }
-
- card_mpuin->curstate = STIN_3BYTE;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->status;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
-
- return 0;
-}
-
-static int sblive_miState2Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- u8 temp = data & 0xf0;
-
- if ((temp == 0xc0) || (temp == 0xd0)) {
- card_mpuin->status = data;
- card_mpuin->curstate = STIN_2BYTE_KEY;
-
- return CTSTATUS_NEXT_BYTE;
- }
-
- if (temp < 0x80)
- return midistatefn[STIN_2BYTE_KEY].Fn(card_mpuin, data);
-
- return midistatefn[STIN_PARSE].Fn(card_mpuin, data);
-}
-
-static int sblive_miState2ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
- unsigned long tmp;
-
- if (data > 0x7f) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = STIN_PARSE;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->status;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
- return -1;
- }
-
- card_mpuin->curstate = STIN_2BYTE;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->status;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
-
- return 0;
-}
-
-static int sblive_miStateSysCommon2(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- card_mpuin->fstatus = data;
- card_mpuin->curstate = STIN_SYS_COMMON_2_KEY;
-
- return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
- unsigned long tmp;
-
- if (data > 0x7f) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = card_mpuin->laststate;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->fstatus;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
- return -1;
- }
-
- card_mpuin->curstate = card_mpuin->laststate;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->fstatus;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
-
- return 0;
-}
-
-static int sblive_miStateSysCommon3(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- card_mpuin->fstatus = data;
- card_mpuin->curstate = STIN_SYS_COMMON_3_KEY;
-
- return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 1 */
-{
- unsigned long tmp;
-
- if (data > 0x7f) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = card_mpuin->laststate;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->fstatus;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
- return -1;
- }
-
- card_mpuin->data = data;
- card_mpuin->curstate = STIN_SYS_COMMON_3_VEL;
-
- return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *card_mpuin, u8 data)
-/* byte 2 */
-{
- unsigned long tmp;
-
- if (data > 0x7f) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = card_mpuin->laststate;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->fstatus;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
-
- return -1;
- }
-
- card_mpuin->curstate = card_mpuin->laststate;
- tmp = (unsigned long) data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->data;
- tmp = tmp << 8;
- tmp |= (unsigned long) card_mpuin->fstatus;
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
-
- return 0;
-}
-
-static int sblive_miStateSysExNorm(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- unsigned long flags;
-
- if ((data > 0x7f) && (data != 0xf7)) {
- /* Real-time messages check */
- if (data > 0xf7)
- return midistatefn[STIN_SYS_REAL].Fn(card_mpuin, data);
-
- /* Invalid Data! */
- DPF(2, "Invalid data!\n");
-
- card_mpuin->curstate = card_mpuin->laststate;
-
- if (card_mpuin->firstmidiq) {
- struct midi_queue *midiq;
-
- midiq = card_mpuin->firstmidiq;
- *midiq->midibyte = data;
- --midiq->sizeLeft;
- ++midiq->midibyte;
-
- spin_lock_irqsave(&card_mpuin->lock, flags);
-
- card_mpuin->firstmidiq = midiq->next;
- if (card_mpuin->firstmidiq == NULL)
- card_mpuin->lastmidiq = NULL;
-
- spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGERROR, (unsigned long) midiq, 0);
-
- kfree(midiq);
- }
-
- return -1;
- }
-
- if (card_mpuin->firstmidiq) {
- struct midi_queue *midiq;
-
- midiq = card_mpuin->firstmidiq;
- *midiq->midibyte = data;
- --midiq->sizeLeft;
- ++midiq->midibyte;
- }
-
- if (data == 0xf7) {
- /* End of Sysex buffer */
- /* Send down the buffer */
-
- card_mpuin->curstate = card_mpuin->laststate;
-
- if (card_mpuin->firstmidiq) {
- struct midi_queue *midiq;
-
- midiq = card_mpuin->firstmidiq;
-
- spin_lock_irqsave(&card_mpuin->lock, flags);
-
- card_mpuin->firstmidiq = midiq->next;
- if (card_mpuin->firstmidiq == NULL)
- card_mpuin->lastmidiq = NULL;
-
- spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-
- kfree(midiq);
- }
-
- return 0;
- }
-
- if (card_mpuin->firstmidiq) {
- struct midi_queue *midiq;
-
- midiq = card_mpuin->firstmidiq;
-
- if (midiq->sizeLeft == 0) {
- /* Special case */
-
- spin_lock_irqsave(&card_mpuin->lock, flags);
-
- card_mpuin->firstmidiq = midiq->next;
- if (card_mpuin->firstmidiq == NULL)
- card_mpuin->lastmidiq = NULL;
-
- spin_unlock_irqrestore(&card_mpuin->lock, flags);
-
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INLONGDATA, (unsigned long) midiq, 0);
-
- kfree(midiq);
-
- return CTSTATUS_NEXT_BYTE;
- }
- }
-
- return CTSTATUS_NEXT_BYTE;
-}
-
-static int sblive_miStateSysReal(struct emu10k1_mpuin *card_mpuin, u8 data)
-{
- emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, data, 1);
-
- return CTSTATUS_NEXT_BYTE;
-}
diff --git a/sound/oss/emu10k1/cardmi.h b/sound/oss/emu10k1/cardmi.h
deleted file mode 100644
index d12c24116307..000000000000
--- a/sound/oss/emu10k1/cardmi.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- **********************************************************************
- * sblive_mi.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _CARDMI_H
-#define _CARDMI_H
-
-#include "icardmid.h"
-#include <linux/interrupt.h>
-
-typedef enum
-{
- STIN_PARSE = 0,
- STIN_3BYTE, /* 0x80, 0x90, 0xA0, 0xB0, 0xE0 */
- STIN_3BYTE_KEY, /* Byte 1 */
- STIN_3BYTE_VEL, /* Byte 1 */
- STIN_2BYTE, /* 0xC0, 0xD0 */
- STIN_2BYTE_KEY, /* Byte 1 */
- STIN_SYS_COMMON_2, /* 0xF1, 0xF3 */
- STIN_SYS_COMMON_2_KEY,
- STIN_SYS_COMMON_3, /* 0xF2 */
- STIN_SYS_COMMON_3_KEY,
- STIN_SYS_COMMON_3_VEL,
- STIN_SYS_EX_NORM, /* 0xF0, Normal mode */
- STIN_SYS_REAL
-} midi_in_state;
-
-
-/* flags for card MIDI in object */
-#define FLAGS_MIDM_STARTED 0x00001000 // Data has started to come in after Midm Start
-#define MIDIIN_MAX_BUFFER_SIZE 200 // Definition for struct emu10k1_mpuin
-
-struct midi_data
-{
- u8 data;
- u32 timein;
-};
-
-struct emu10k1_mpuin
-{
- spinlock_t lock;
- struct midi_queue *firstmidiq;
- struct midi_queue *lastmidiq;
- unsigned qhead, qtail;
- struct midi_data midiq[MIDIIN_MAX_BUFFER_SIZE];
- struct tasklet_struct tasklet;
- struct midi_openinfo openinfo;
-
- /* For MIDI state machine */
- u8 status; /* For MIDI running status */
- u8 fstatus; /* For 0xFn status only */
- midi_in_state curstate;
- midi_in_state laststate;
- u32 timestart;
- u32 timein;
- u8 data;
-};
-
-int emu10k1_mpuin_open(struct emu10k1_card *, struct midi_openinfo *);
-int emu10k1_mpuin_close(struct emu10k1_card *);
-int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *, struct midi_hdr *);
-int emu10k1_mpuin_start(struct emu10k1_card *);
-int emu10k1_mpuin_stop(struct emu10k1_card *);
-int emu10k1_mpuin_reset(struct emu10k1_card *);
-
-int emu10k1_mpuin_irqhandler(struct emu10k1_card *);
-void emu10k1_mpuin_bh(unsigned long);
-
-#endif /* _CARDMI_H */
diff --git a/sound/oss/emu10k1/cardmo.c b/sound/oss/emu10k1/cardmo.c
deleted file mode 100644
index a8cc75db3e45..000000000000
--- a/sound/oss/emu10k1/cardmo.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- **********************************************************************
- * cardmo.c - MIDI UART output HAL for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up
- *
- **********************************************************************
- *
- * 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/slab.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "cardmo.h"
-#include "irqmgr.h"
-
-/* Installs the IRQ handler for the MPU out port *
- * and initialize parameters */
-
-int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
-{
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
-
- DPF(2, "emu10k1_mpuout_open()\n");
-
- if (!(card_mpuout->status & FLAGS_AVAILABLE))
- return -1;
-
- /* Copy open info and mark channel as in use */
- card_mpuout->intr = 0;
- card_mpuout->openinfo = *openinfo;
- card_mpuout->status &= ~FLAGS_AVAILABLE;
- card_mpuout->laststatus = 0x80;
- card_mpuout->firstmidiq = NULL;
- card_mpuout->lastmidiq = NULL;
-
- emu10k1_mpu_reset(card);
- emu10k1_mpu_acquire(card);
-
- return 0;
-}
-
-int emu10k1_mpuout_close(struct emu10k1_card *card)
-{
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- struct midi_queue *midiq;
- struct midi_hdr *midihdr;
- unsigned long flags;
-
- DPF(2, "emu10k1_mpuout_close()\n");
-
- emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
- spin_lock_irqsave(&card_mpuout->lock, flags);
-
- while (card_mpuout->firstmidiq != NULL) {
- midiq = card_mpuout->firstmidiq;
- midihdr = (struct midi_hdr *) midiq->refdata;
-
- card_mpuout->firstmidiq = midiq->next;
-
- kfree(midihdr->data);
- kfree(midihdr);
- kfree(midiq);
- }
-
- card_mpuout->lastmidiq = NULL;
-
- emu10k1_mpu_release(card);
-
- card_mpuout->status |= FLAGS_AVAILABLE;
-
- spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
- return 0;
-}
-
-/* If there isn't enough buffer space, reject Midi Buffer. *
-* Otherwise, disable TX, create object to hold Midi *
-* uffer, update buffer flags and other parameters *
-* before enabling TX again. */
-
-int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihdr)
-{
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- struct midi_queue *midiq;
- unsigned long flags;
-
- DPF(2, "emu10k1_mpuout_add_buffer()\n");
-
- if (card_mpuout->state == CARDMIDIOUT_STATE_SUSPEND)
- return 0;
-
- midihdr->flags |= MIDIBUF_INQUEUE;
- midihdr->flags &= ~MIDIBUF_DONE;
-
- if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
- /* Message lost */
- return -1;
- }
-
- midiq->next = NULL;
- midiq->qtype = 1;
- midiq->length = midihdr->bufferlength;
- midiq->sizeLeft = midihdr->bufferlength;
- midiq->midibyte = midihdr->data;
-
- midiq->refdata = (unsigned long) midihdr;
-
- spin_lock_irqsave(&card_mpuout->lock, flags);
-
- if (card_mpuout->firstmidiq == NULL) {
- card_mpuout->firstmidiq = midiq;
- card_mpuout->lastmidiq = midiq;
- } else {
- (card_mpuout->lastmidiq)->next = midiq;
- card_mpuout->lastmidiq = midiq;
- }
-
- card_mpuout->intr = 0;
-
- emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
- spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
- return 0;
-}
-
-void emu10k1_mpuout_bh(unsigned long refdata)
-{
- struct emu10k1_card *card = (struct emu10k1_card *) refdata;
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- int cByteSent = 0;
- struct midi_queue *midiq;
- struct midi_queue *doneq = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&card_mpuout->lock, flags);
-
- while (card_mpuout->firstmidiq != NULL) {
- midiq = card_mpuout->firstmidiq;
-
- while (cByteSent < 4 && midiq->sizeLeft) {
- if (emu10k1_mpu_write_data(card, *midiq->midibyte) < 0) {
- DPF(2, "emu10k1_mpuoutDpcCallback error!!\n");
- } else {
- ++cByteSent;
- --midiq->sizeLeft;
- ++midiq->midibyte;
- }
- }
-
- if (midiq->sizeLeft == 0) {
- if (doneq == NULL)
- doneq = midiq;
- card_mpuout->firstmidiq = midiq->next;
- } else
- break;
- }
-
- if (card_mpuout->firstmidiq == NULL)
- card_mpuout->lastmidiq = NULL;
-
- if (doneq != NULL) {
- while (doneq != card_mpuout->firstmidiq) {
- unsigned long callback_msg[3];
-
- midiq = doneq;
- doneq = midiq->next;
-
- if (midiq->qtype) {
- callback_msg[0] = 0;
- callback_msg[1] = midiq->length;
- callback_msg[2] = midiq->refdata;
-
- emu10k1_midi_callback(ICARDMIDI_OUTLONGDATA, card_mpuout->openinfo.refdata, callback_msg);
- } else if (((u8) midiq->refdata) < 0xF0 && ((u8) midiq->refdata) > 0x7F)
- card_mpuout->laststatus = (u8) midiq->refdata;
-
- kfree(midiq);
- }
- }
-
- if ((card_mpuout->firstmidiq != NULL) || cByteSent) {
- card_mpuout->intr = 0;
- emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
- }
-
- spin_unlock_irqrestore(&card_mpuout->lock, flags);
-
- return;
-}
-
-int emu10k1_mpuout_irqhandler(struct emu10k1_card *card)
-{
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
-
- DPF(4, "emu10k1_mpuout_irqhandler\n");
-
- card_mpuout->intr = 1;
- emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
-
- tasklet_hi_schedule(&card_mpuout->tasklet);
-
- return 0;
-}
diff --git a/sound/oss/emu10k1/cardmo.h b/sound/oss/emu10k1/cardmo.h
deleted file mode 100644
index 7026eb3a85af..000000000000
--- a/sound/oss/emu10k1/cardmo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- **********************************************************************
- * cardmo.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _CARDMO_H
-#define _CARDMO_H
-
-#include "icardmid.h"
-#include <linux/interrupt.h>
-
-#define CARDMIDIOUT_STATE_DEFAULT 0x00000000
-#define CARDMIDIOUT_STATE_SUSPEND 0x00000001
-
-struct emu10k1_mpuout
-{
- u32 status;
- u32 state;
- volatile int intr;
- struct midi_queue *firstmidiq;
- struct midi_queue *lastmidiq;
- u8 laststatus;
- struct tasklet_struct tasklet;
- spinlock_t lock;
- struct midi_openinfo openinfo;
-};
-
-int emu10k1_mpuout_open(struct emu10k1_card *, struct midi_openinfo *);
-int emu10k1_mpuout_close(struct emu10k1_card *);
-int emu10k1_mpuout_add_buffer(struct emu10k1_card *, struct midi_hdr *);
-
-int emu10k1_mpuout_irqhandler(struct emu10k1_card *);
-void emu10k1_mpuout_bh(unsigned long);
-
-#endif /* _CARDMO_H */
diff --git a/sound/oss/emu10k1/cardwi.c b/sound/oss/emu10k1/cardwi.c
deleted file mode 100644
index 060d1be94d33..000000000000
--- a/sound/oss/emu10k1/cardwi.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- **********************************************************************
- * cardwi.c - PCM input HAL for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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/poll.h>
-#include "hwaccess.h"
-#include "timer.h"
-#include "recmgr.h"
-#include "audio.h"
-#include "cardwi.h"
-
-/**
- * query_format - returns a valid sound format
- *
- * This function will return a valid sound format as close
- * to the requested one as possible.
- */
-static void query_format(int recsrc, struct wave_format *wave_fmt)
-{
-
- switch (recsrc) {
- case WAVERECORD_AC97:
-
- if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
- wave_fmt->channels = 2;
-
- if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
- wave_fmt->samplingrate = 0xBB80;
- else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
- wave_fmt->samplingrate = 0xAC44;
- else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
- wave_fmt->samplingrate = 0x7D00;
- else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
- wave_fmt->samplingrate = 0x5DC0;
- else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
- wave_fmt->samplingrate = 0x5622;
- else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
- wave_fmt->samplingrate = 0x3E80;
- else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
- wave_fmt->samplingrate = 0x2B11;
- else
- wave_fmt->samplingrate = 0x1F40;
-
- switch (wave_fmt->id) {
- case AFMT_S16_LE:
- wave_fmt->bitsperchannel = 16;
- break;
- case AFMT_U8:
- wave_fmt->bitsperchannel = 8;
- break;
- default:
- wave_fmt->id = AFMT_S16_LE;
- wave_fmt->bitsperchannel = 16;
- break;
- }
-
- break;
-
- /* these can't be changed from the original values */
- case WAVERECORD_MIC:
- case WAVERECORD_FX:
- break;
-
- default:
- BUG();
- break;
- }
-
- wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
- wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
- wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
- wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
-}
-
-static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
- buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,
- &buffer->dma_handle);
- if (buffer->addr == NULL)
- return -1;
-
- return 0;
-}
-
-static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
- if (buffer->addr != NULL)
- pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
- buffer->addr, buffer->dma_handle);
-}
-
-int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct wiinst *wiinst = wave_dev->wiinst;
- struct wiinst **wiinst_tmp = NULL;
- u16 delay;
- unsigned long flags;
-
- DPF(2, "emu10k1_wavein_open()\n");
-
- switch (wiinst->recsrc) {
- case WAVERECORD_AC97:
- wiinst_tmp = &card->wavein.ac97;
- break;
- case WAVERECORD_MIC:
- wiinst_tmp = &card->wavein.mic;
- break;
- case WAVERECORD_FX:
- wiinst_tmp = &card->wavein.fx;
- break;
- default:
- BUG();
- break;
- }
-
- spin_lock_irqsave(&card->lock, flags);
- if (*wiinst_tmp != NULL) {
- spin_unlock_irqrestore(&card->lock, flags);
- return -1;
- }
-
- *wiinst_tmp = wiinst;
- spin_unlock_irqrestore(&card->lock, flags);
-
- /* handle 8 bit recording */
- if (wiinst->format.bytesperchannel == 1) {
- if (wiinst->buffer.size > 0x8000) {
- wiinst->buffer.size = 0x8000;
- wiinst->buffer.sizeregval = 0x1f;
- } else
- wiinst->buffer.sizeregval += 4;
-
- wiinst->buffer.cov = 2;
- } else
- wiinst->buffer.cov = 1;
-
- if (alloc_buffer(card, &wiinst->buffer) < 0) {
- ERROR();
- return -1;
- }
-
- emu10k1_set_record_src(card, wiinst);
-
- emu10k1_reset_record(card, &wiinst->buffer);
-
- wiinst->buffer.hw_pos = 0;
- wiinst->buffer.pos = 0;
- wiinst->buffer.bytestocopy = 0;
-
- delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
-
- emu10k1_timer_install(card, &wiinst->timer, delay / 2);
-
- wiinst->state = WAVE_STATE_OPEN;
-
- return 0;
-}
-
-void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct wiinst *wiinst = wave_dev->wiinst;
- unsigned long flags;
-
- DPF(2, "emu10k1_wavein_close()\n");
-
- emu10k1_wavein_stop(wave_dev);
-
- emu10k1_timer_uninstall(card, &wiinst->timer);
-
- free_buffer(card, &wiinst->buffer);
-
- spin_lock_irqsave(&card->lock, flags);
- switch (wave_dev->wiinst->recsrc) {
- case WAVERECORD_AC97:
- card->wavein.ac97 = NULL;
- break;
- case WAVERECORD_MIC:
- card->wavein.mic = NULL;
- break;
- case WAVERECORD_FX:
- card->wavein.fx = NULL;
- break;
- default:
- BUG();
- break;
- }
- spin_unlock_irqrestore(&card->lock, flags);
-
- wiinst->state = WAVE_STATE_CLOSED;
-}
-
-void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct wiinst *wiinst = wave_dev->wiinst;
-
- DPF(2, "emu10k1_wavein_start()\n");
-
- emu10k1_start_record(card, &wiinst->buffer);
- emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
-
- wiinst->state |= WAVE_STATE_STARTED;
-}
-
-void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct wiinst *wiinst = wave_dev->wiinst;
-
- DPF(2, "emu10k1_wavein_stop()\n");
-
- if (!(wiinst->state & WAVE_STATE_STARTED))
- return;
-
- emu10k1_timer_disable(card, &wiinst->timer);
- emu10k1_stop_record(card, &wiinst->buffer);
-
- wiinst->state &= ~WAVE_STATE_STARTED;
-}
-
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct wiinst *wiinst = wave_dev->wiinst;
- u16 delay;
-
- DPF(2, "emu10k1_wavein_setformat()\n");
-
- if (wiinst->state & WAVE_STATE_STARTED)
- return -1;
-
- query_format(wiinst->recsrc, format);
-
- if ((wiinst->format.samplingrate != format->samplingrate)
- || (wiinst->format.bitsperchannel != format->bitsperchannel)
- || (wiinst->format.channels != format->channels)) {
-
- wiinst->format = *format;
-
- if (wiinst->state == WAVE_STATE_CLOSED)
- return 0;
-
- wiinst->buffer.size *= wiinst->buffer.cov;
-
- if (wiinst->format.bytesperchannel == 1) {
- wiinst->buffer.cov = 2;
- wiinst->buffer.size /= wiinst->buffer.cov;
- } else
- wiinst->buffer.cov = 1;
-
- emu10k1_timer_uninstall(card, &wiinst->timer);
-
- delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
-
- emu10k1_timer_install(card, &wiinst->timer, delay / 2);
- }
-
- return 0;
-}
-
-void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
-{
- struct wavein_buffer *buffer = &wiinst->buffer;
-
- *size = buffer->bytestocopy;
-
- if (wiinst->mmapped)
- return;
-
- if (*size > buffer->size) {
- *size = buffer->size;
- buffer->pos = buffer->hw_pos;
- buffer->bytestocopy = buffer->size;
- DPF(1, "buffer overrun\n");
- }
-}
-
-static int copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
-{
- if (cov == 1) {
- if (__copy_to_user(dst, src + str, len))
- return -EFAULT;
- } else {
- u8 byte;
- u32 i;
-
- src += 1 + 2 * str;
-
- for (i = 0; i < len; i++) {
- byte = src[2 * i] ^ 0x80;
- if (__copy_to_user(dst + i, &byte, 1))
- return -EFAULT;
- }
- }
-
- return 0;
-}
-
-int emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
-{
- struct wavein_buffer *buffer = &wiinst->buffer;
- u32 sizetocopy, sizetocopy_now, start;
- unsigned long flags;
- int ret;
-
- sizetocopy = min_t(u32, buffer->size, *size);
- *size = sizetocopy;
-
- if (!sizetocopy)
- return 0;
-
- spin_lock_irqsave(&wiinst->lock, flags);
- start = buffer->pos;
- buffer->pos += sizetocopy;
- buffer->pos %= buffer->size;
- buffer->bytestocopy -= sizetocopy;
- sizetocopy_now = buffer->size - start;
-
- spin_unlock_irqrestore(&wiinst->lock, flags);
-
- if (sizetocopy > sizetocopy_now) {
- sizetocopy -= sizetocopy_now;
-
- ret = copy_block(data, buffer->addr, start, sizetocopy_now,
- buffer->cov);
- if (ret == 0)
- ret = copy_block(data + sizetocopy_now, buffer->addr, 0,
- sizetocopy, buffer->cov);
- } else {
- ret = copy_block(data, buffer->addr, start, sizetocopy,
- buffer->cov);
- }
-
- return ret;
-}
-
-void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
-{
- u32 hw_pos;
- u32 diff;
-
- /* There is no actual start yet */
- if (!(wiinst->state & WAVE_STATE_STARTED)) {
- hw_pos = wiinst->buffer.hw_pos;
- } else {
- /* hw_pos in byte units */
- hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
- }
-
- diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
- wiinst->total_recorded += diff;
- wiinst->buffer.bytestocopy += diff;
-
- wiinst->buffer.hw_pos = hw_pos;
-}
diff --git a/sound/oss/emu10k1/cardwi.h b/sound/oss/emu10k1/cardwi.h
deleted file mode 100644
index e82029b46ad1..000000000000
--- a/sound/oss/emu10k1/cardwi.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- **********************************************************************
- * cardwi.h -- header file for card wave input functions
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-#ifndef _CARDWI_H
-#define _CARDWI_H
-
-#include "icardwav.h"
-#include "audio.h"
-#include "timer.h"
-
-struct wavein_buffer {
- u16 ossfragshift;
- u32 fragment_size;
- u32 numfrags;
- u32 hw_pos; /* hardware cursor position */
- u32 pos; /* software cursor position */
- u32 bytestocopy; /* bytes of recorded data available */
- u32 size;
- u32 pages;
- u32 sizereg;
- u32 sizeregval;
- u32 addrreg;
- u32 idxreg;
- u32 adcctl;
- void *addr;
- u8 cov;
- dma_addr_t dma_handle;
-};
-
-struct wiinst
-{
- u8 state;
- struct emu_timer timer;
- struct wave_format format;
- struct wavein_buffer buffer;
- wait_queue_head_t wait_queue;
- u8 mmapped;
- u32 total_recorded; /* total bytes read() from device */
- u32 blocks;
- spinlock_t lock;
- u8 recsrc;
- u16 fxwc;
-};
-
-#define WAVEIN_MAXBUFSIZE 65536
-#define WAVEIN_MINBUFSIZE 368
-
-#define WAVEIN_DEFAULTFRAGLEN 100
-#define WAVEIN_DEFAULTBUFLEN 1000
-
-#define WAVEIN_MINFRAGSHIFT 8
-#define WAVEIN_MINFRAGS 2
-
-int emu10k1_wavein_open(struct emu10k1_wavedevice *);
-void emu10k1_wavein_close(struct emu10k1_wavedevice *);
-void emu10k1_wavein_start(struct emu10k1_wavedevice *);
-void emu10k1_wavein_stop(struct emu10k1_wavedevice *);
-void emu10k1_wavein_getxfersize(struct wiinst *, u32 *);
-int emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *);
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *);
-void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *);
-
-
-#endif /* _CARDWI_H */
diff --git a/sound/oss/emu10k1/cardwo.c b/sound/oss/emu10k1/cardwo.c
deleted file mode 100644
index 54daca4f57b4..000000000000
--- a/sound/oss/emu10k1/cardwo.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- **********************************************************************
- * cardwo.c - PCM output HAL for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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/poll.h>
-#include "hwaccess.h"
-#include "8010.h"
-#include "voicemgr.h"
-#include "cardwo.h"
-#include "audio.h"
-
-static u32 samplerate_to_linearpitch(u32 samplingrate)
-{
- samplingrate = (samplingrate << 8) / 375;
- return (samplingrate >> 1) + (samplingrate & 1);
-}
-
-static void query_format(struct emu10k1_wavedevice *wave_dev, struct wave_format *wave_fmt)
-{
- int i, j, do_passthrough = 0, is_ac3 = 0;
- struct emu10k1_card *card = wave_dev->card;
- struct woinst *woinst = wave_dev->woinst;
-
- if ((wave_fmt->channels > 2) && (wave_fmt->id != AFMT_S16_LE) && (wave_fmt->id != AFMT_U8))
- wave_fmt->channels = 2;
-
- if ((wave_fmt->channels < 1) || (wave_fmt->channels > WAVEOUT_MAXVOICES))
- wave_fmt->channels = 2;
-
- if (wave_fmt->channels == 2)
- woinst->num_voices = 1;
- else
- woinst->num_voices = wave_fmt->channels;
-
- if (wave_fmt->samplingrate >= 0x2ee00)
- wave_fmt->samplingrate = 0x2ee00;
-
- wave_fmt->passthrough = 0;
- do_passthrough = is_ac3 = 0;
-
- if (card->pt.selected)
- do_passthrough = 1;
-
- switch (wave_fmt->id) {
- case AFMT_S16_LE:
- wave_fmt->bitsperchannel = 16;
- break;
- case AFMT_U8:
- wave_fmt->bitsperchannel = 8;
- break;
- case AFMT_AC3:
- do_passthrough = 1;
- is_ac3 = 1;
- break;
- default:
- wave_fmt->id = AFMT_S16_LE;
- wave_fmt->bitsperchannel = 16;
- break;
- }
- if (do_passthrough) {
- /* currently only one waveout instance may use pass-through */
- if (woinst->state != WAVE_STATE_CLOSED ||
- card->pt.state != PT_STATE_INACTIVE ||
- (wave_fmt->samplingrate != 48000 && !is_ac3)) {
- DPF(2, "unable to set pass-through mode\n");
- } else if (USE_PT_METHOD1) {
- i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name);
- j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name);
- if (i < 0 || j < 0)
- DPF(2, "unable to set pass-through mode\n");
- else {
- wave_fmt->samplingrate = 48000;
- wave_fmt->channels = 2;
- card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
- card->pt.pos_gpr_name);
- wave_fmt->passthrough = 1;
- card->pt.intr_gpr = i;
- card->pt.enable_gpr = j;
- card->pt.state = PT_STATE_INACTIVE;
-
- DPD(2, "is_ac3 is %d\n", is_ac3);
- card->pt.ac3data = is_ac3;
- wave_fmt->bitsperchannel = 16;
- }
- }else{
- DPF(2, "Using Passthrough Method 2\n");
- card->pt.enable_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
- card->pt.enable_gpr_name);
- wave_fmt->passthrough = 2;
- wave_fmt->bitsperchannel = 16;
- }
- }
-
- wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
- wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
- wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-
- if (wave_fmt->channels == 2)
- wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;
- else
- wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;
-}
-
-static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum)
-{
- struct emu_voice *voice = &woinst->voice[voicenum];
-
- /* Allocate voices here, if no voices available, return error. */
-
- voice->usage = VOICE_USAGE_PLAYBACK;
-
- voice->flags = 0;
-
- if (woinst->format.channels == 2)
- voice->flags |= VOICE_FLAGS_STEREO;
-
- if (woinst->format.bitsperchannel == 16)
- voice->flags |= VOICE_FLAGS_16BIT;
-
- if (emu10k1_voice_alloc(card, voice) < 0) {
- voice->usage = VOICE_USAGE_FREE;
- return -1;
- }
-
- /* Calculate pitch */
- voice->initial_pitch = (u16) (srToPitch(woinst->format.samplingrate) >> 8);
- voice->pitch_target = samplerate_to_linearpitch(woinst->format.samplingrate);
-
- DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);
-
- voice->startloop = (voice->mem.emupageindex << 12) /
- woinst->format.bytespervoicesample;
- voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
- voice->start = voice->startloop;
-
-
- voice->params[0].volume_target = 0xffff;
- voice->params[0].initial_fc = 0xff;
- voice->params[0].initial_attn = 0x00;
- voice->params[0].byampl_env_sustain = 0x7f;
- voice->params[0].byampl_env_decay = 0x7f;
-
-
- if (voice->flags & VOICE_FLAGS_STEREO) {
- if (woinst->format.passthrough == 2) {
- voice->params[0].send_routing = voice->params[1].send_routing = card->waveout.send_routing[ROUTE_PT];
- voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PT];
- voice->params[0].send_dcba = 0xff;
- voice->params[1].send_dcba = 0xff00;
- voice->params[0].send_hgfe = voice->params[1].send_hgfe=0;
- } else {
- voice->params[0].send_dcba = card->waveout.send_dcba[SEND_LEFT];
- voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_LEFT];
- voice->params[1].send_dcba = card->waveout.send_dcba[SEND_RIGHT];
- voice->params[1].send_hgfe = card->waveout.send_hgfe[SEND_RIGHT];
-
- if (woinst->device) {
- // /dev/dps1
- voice->params[0].send_routing = voice->params[1].send_routing = card->waveout.send_routing[ROUTE_PCM1];
- voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
- } else {
- voice->params[0].send_routing = voice->params[1].send_routing = card->waveout.send_routing[ROUTE_PCM];
- voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
- }
- }
-
- voice->params[1].volume_target = 0xffff;
- voice->params[1].initial_fc = 0xff;
- voice->params[1].initial_attn = 0x00;
- voice->params[1].byampl_env_sustain = 0x7f;
- voice->params[1].byampl_env_decay = 0x7f;
- } else {
- if (woinst->num_voices > 1) {
- // Multichannel pcm
- voice->params[0].send_dcba=0xff;
- voice->params[0].send_hgfe=0;
- if (card->is_audigy) {
- voice->params[0].send_routing = 0x3f3f3f00 + card->mchannel_fx + voicenum;
- voice->params[0].send_routing2 = 0x3f3f3f3f;
- } else {
- voice->params[0].send_routing = 0xfff0 + card->mchannel_fx + voicenum;
- }
-
- } else {
- voice->params[0].send_dcba = card->waveout.send_dcba[SEND_MONO];
- voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_MONO];
-
- if (woinst->device) {
- voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM1];
- voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
- } else {
- voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM];
- voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
- }
- }
- }
-
- DPD(2, "voice: startloop=%#x, endloop=%#x\n", voice->startloop, voice->endloop);
-
- emu10k1_voice_playback_setup(voice);
-
- return 0;
-}
-
-int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct woinst *woinst = wave_dev->woinst;
- struct waveout_buffer *buffer = &woinst->buffer;
- unsigned int voicenum;
- u16 delay;
-
- DPF(2, "emu10k1_waveout_open()\n");
-
- for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
- if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) {
- ERROR();
- emu10k1_waveout_close(wave_dev);
- return -1;
- }
-
- if (get_voice(card, woinst, voicenum) < 0) {
- ERROR();
- emu10k1_waveout_close(wave_dev);
- return -1;
- }
- }
-
- buffer->fill_silence = 0;
- buffer->silence_bytes = 0;
- buffer->silence_pos = 0;
- buffer->hw_pos = 0;
- buffer->free_bytes = woinst->buffer.size;
-
- delay = (48000 * woinst->buffer.fragment_size) /
- (woinst->format.samplingrate * woinst->format.bytespervoicesample);
-
- emu10k1_timer_install(card, &woinst->timer, delay);
-
- woinst->state = WAVE_STATE_OPEN;
-
- return 0;
-}
-
-void emu10k1_waveout_close(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct woinst *woinst = wave_dev->woinst;
- unsigned int voicenum;
-
- DPF(2, "emu10k1_waveout_close()\n");
-
- emu10k1_waveout_stop(wave_dev);
-
- emu10k1_timer_uninstall(card, &woinst->timer);
-
- for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
- emu10k1_voice_free(&woinst->voice[voicenum]);
- emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);
- }
-
- woinst->state = WAVE_STATE_CLOSED;
-}
-
-void emu10k1_waveout_start(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct woinst *woinst = wave_dev->woinst;
- struct pt_data *pt = &card->pt;
-
- DPF(2, "emu10k1_waveout_start()\n");
-
- if (woinst->format.passthrough == 2) {
- emu10k1_pt_setup(wave_dev);
- sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 1);
- pt->state = PT_STATE_PLAYING;
- }
-
- /* Actual start */
- emu10k1_voices_start(woinst->voice, woinst->num_voices, woinst->total_played);
-
- emu10k1_timer_enable(card, &woinst->timer);
-
- woinst->state |= WAVE_STATE_STARTED;
-}
-
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct woinst *woinst = wave_dev->woinst;
- unsigned int voicenum;
- u16 delay;
-
- DPF(2, "emu10k1_waveout_setformat()\n");
-
- if (woinst->state & WAVE_STATE_STARTED)
- return -1;
-
- query_format(wave_dev, format);
-
- if (woinst->format.samplingrate != format->samplingrate ||
- woinst->format.channels != format->channels ||
- woinst->format.bitsperchannel != format->bitsperchannel) {
-
- woinst->format = *format;
-
- if (woinst->state == WAVE_STATE_CLOSED)
- return 0;
-
- emu10k1_timer_uninstall(card, &woinst->timer);
-
- for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
- emu10k1_voice_free(&woinst->voice[voicenum]);
-
- if (get_voice(card, woinst, voicenum) < 0) {
- ERROR();
- emu10k1_waveout_close(wave_dev);
- return -1;
- }
- }
-
- delay = (48000 * woinst->buffer.fragment_size) /
- (woinst->format.samplingrate * woinst->format.bytespervoicesample);
-
- emu10k1_timer_install(card, &woinst->timer, delay);
- }
-
- return 0;
-}
-
-void emu10k1_waveout_stop(struct emu10k1_wavedevice *wave_dev)
-{
- struct emu10k1_card *card = wave_dev->card;
- struct woinst *woinst = wave_dev->woinst;
-
- DPF(2, "emu10k1_waveout_stop()\n");
-
- if (!(woinst->state & WAVE_STATE_STARTED))
- return;
-
- emu10k1_timer_disable(card, &woinst->timer);
-
- /* Stop actual voices */
- emu10k1_voices_stop(woinst->voice, woinst->num_voices);
-
- emu10k1_waveout_update(woinst);
-
- woinst->state &= ~WAVE_STATE_STARTED;
-}
-
-/**
- * emu10k1_waveout_getxfersize -
- *
- * gives the total free bytes on the voice buffer, including silence bytes
- * (basically: total_free_bytes = free_bytes + silence_bytes).
- *
- */
-void emu10k1_waveout_getxfersize(struct woinst *woinst, u32 *total_free_bytes)
-{
- struct waveout_buffer *buffer = &woinst->buffer;
- int pending_bytes;
-
- if (woinst->mmapped) {
- *total_free_bytes = buffer->free_bytes;
- return;
- }
-
- pending_bytes = buffer->size - buffer->free_bytes;
-
- buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0;
-
- if (pending_bytes > (signed) buffer->silence_bytes) {
- *total_free_bytes = (buffer->free_bytes + buffer->silence_bytes);
- } else {
- *total_free_bytes = buffer->size;
- buffer->silence_bytes = pending_bytes;
- if (pending_bytes < 0) {
- buffer->silence_pos = buffer->hw_pos;
- buffer->silence_bytes = 0;
- buffer->free_bytes = buffer->size;
- DPF(1, "buffer underrun\n");
- }
- }
-}
-
-/**
- * copy_block -
- *
- * copies a block of pcm data to a voice buffer.
- * Notice that the voice buffer is actually a set of disjointed memory pages.
- *
- */
-static void copy_block(void **dst, u32 str, u8 __user *src, u32 len)
-{
- unsigned int pg;
- unsigned int pgoff;
- unsigned int k;
-
- pg = str / PAGE_SIZE;
- pgoff = str % PAGE_SIZE;
-
- if (len > PAGE_SIZE - pgoff) {
- k = PAGE_SIZE - pgoff;
- if (__copy_from_user((u8 *)dst[pg] + pgoff, src, k))
- return;
- len -= k;
- while (len > PAGE_SIZE) {
- if (__copy_from_user(dst[++pg], src + k, PAGE_SIZE))
- return;
- k += PAGE_SIZE;
- len -= PAGE_SIZE;
- }
- if (__copy_from_user(dst[++pg], src + k, len))
- return;
-
- } else
- __copy_from_user((u8 *)dst[pg] + pgoff, src, len);
-}
-
-/**
- * copy_ilv_block -
- *
- * copies a block of pcm data containing n interleaved channels to n mono voice buffers.
- * Notice that the voice buffer is actually a set of disjointed memory pages.
- *
- */
-static void copy_ilv_block(struct woinst *woinst, u32 str, u8 __user *src, u32 len)
-{
- unsigned int pg;
- unsigned int pgoff;
- unsigned int voice_num;
- struct emu_voice *voice = woinst->voice;
-
- pg = str / PAGE_SIZE;
- pgoff = str % PAGE_SIZE;
-
- while (len) {
- for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) {
- if (__copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample))
- return;
- src += woinst->format.bytespervoicesample;
- }
-
- len -= woinst->format.bytespervoicesample;
-
- pgoff += woinst->format.bytespervoicesample;
- if (pgoff >= PAGE_SIZE) {
- pgoff = 0;
- pg++;
- }
- }
-}
-
-/**
- * fill_block -
- *
- * fills a set voice buffers with a block of a given sample.
- *
- */
-static void fill_block(struct woinst *woinst, u32 str, u8 data, u32 len)
-{
- unsigned int pg;
- unsigned int pgoff;
- unsigned int voice_num;
- struct emu_voice *voice = woinst->voice;
- unsigned int k;
-
- pg = str / PAGE_SIZE;
- pgoff = str % PAGE_SIZE;
-
- if (len > PAGE_SIZE - pgoff) {
- k = PAGE_SIZE - pgoff;
- for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
- memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k);
- len -= k;
- while (len > PAGE_SIZE) {
- pg++;
- for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
- memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE);
-
- len -= PAGE_SIZE;
- }
- pg++;
- for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
- memset(voice[voice_num].mem.addr[pg], data, len);
-
- } else {
- for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
- memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len);
- }
-}
-
-/**
- * emu10k1_waveout_xferdata -
- *
- * copies pcm data to the voice buffer. Silence samples
- * previously added to the buffer are overwritten.
- *
- */
-void emu10k1_waveout_xferdata(struct woinst *woinst, u8 __user *data, u32 *size)
-{
- struct waveout_buffer *buffer = &woinst->buffer;
- struct voice_mem *mem = &woinst->voice[0].mem;
- u32 sizetocopy, sizetocopy_now, start;
- unsigned long flags;
-
- sizetocopy = min_t(u32, buffer->size, *size);
- *size = sizetocopy;
-
- if (!sizetocopy)
- return;
-
- spin_lock_irqsave(&woinst->lock, flags);
- start = (buffer->size + buffer->silence_pos - buffer->silence_bytes) % buffer->size;
-
- if (sizetocopy > buffer->silence_bytes) {
- buffer->silence_pos += sizetocopy - buffer->silence_bytes;
- buffer->free_bytes -= sizetocopy - buffer->silence_bytes;
- buffer->silence_bytes = 0;
- } else
- buffer->silence_bytes -= sizetocopy;
-
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- sizetocopy_now = buffer->size - start;
- if (sizetocopy > sizetocopy_now) {
- sizetocopy -= sizetocopy_now;
- if (woinst->num_voices > 1) {
- copy_ilv_block(woinst, start, data, sizetocopy_now);
- copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy);
- } else {
- copy_block(mem->addr, start, data, sizetocopy_now);
- copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy);
- }
- } else {
- if (woinst->num_voices > 1)
- copy_ilv_block(woinst, start, data, sizetocopy);
- else
- copy_block(mem->addr, start, data, sizetocopy);
- }
-}
-
-/**
- * emu10k1_waveout_fillsilence -
- *
- * adds samples of silence to the voice buffer so that we
- * don't loop over stale pcm data.
- *
- */
-void emu10k1_waveout_fillsilence(struct woinst *woinst)
-{
- struct waveout_buffer *buffer = &woinst->buffer;
- u32 sizetocopy, sizetocopy_now, start;
- u8 filldata;
- unsigned long flags;
-
- sizetocopy = buffer->fragment_size;
-
- if (woinst->format.bitsperchannel == 16)
- filldata = 0x00;
- else
- filldata = 0x80;
-
- spin_lock_irqsave(&woinst->lock, flags);
- buffer->silence_bytes += sizetocopy;
- buffer->free_bytes -= sizetocopy;
- buffer->silence_pos %= buffer->size;
- start = buffer->silence_pos;
- buffer->silence_pos += sizetocopy;
- spin_unlock_irqrestore(&woinst->lock, flags);
-
- sizetocopy_now = buffer->size - start;
-
- if (sizetocopy > sizetocopy_now) {
- sizetocopy -= sizetocopy_now;
- fill_block(woinst, start, filldata, sizetocopy_now);
- fill_block(woinst, 0, filldata, sizetocopy);
- } else {
- fill_block(woinst, start, filldata, sizetocopy);
- }
-}
-
-/**
- * emu10k1_waveout_update -
- *
- * updates the position of the voice buffer hardware pointer (hw_pos)
- * and the number of free bytes on the buffer (free_bytes).
- * The free bytes _don't_ include silence bytes that may have been
- * added to the buffer.
- *
- */
-void emu10k1_waveout_update(struct woinst *woinst)
-{
- u32 hw_pos;
- u32 diff;
-
- /* There is no actual start yet */
- if (!(woinst->state & WAVE_STATE_STARTED)) {
- hw_pos = woinst->buffer.hw_pos;
- } else {
- /* hw_pos in sample units */
- hw_pos = sblive_readptr(woinst->voice[0].card, CCCA_CURRADDR, woinst->voice[0].num);
-
- if(hw_pos < woinst->voice[0].start)
- hw_pos += woinst->buffer.size / woinst->format.bytespervoicesample - woinst->voice[0].start;
- else
- hw_pos -= woinst->voice[0].start;
-
- hw_pos *= woinst->format.bytespervoicesample;
- }
-
- diff = (woinst->buffer.size + hw_pos - woinst->buffer.hw_pos) % woinst->buffer.size;
- woinst->total_played += diff;
- woinst->buffer.free_bytes += diff;
- woinst->buffer.hw_pos = hw_pos;
-}
diff --git a/sound/oss/emu10k1/cardwo.h b/sound/oss/emu10k1/cardwo.h
deleted file mode 100644
index 1dece8853e5c..000000000000
--- a/sound/oss/emu10k1/cardwo.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- **********************************************************************
- * cardwo.h -- header file for card wave out functions
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _CARDWO_H
-#define _CARDWO_H
-
-#include "icardwav.h"
-#include "audio.h"
-#include "voicemgr.h"
-#include "timer.h"
-
-/* setting this to other than a power of two may break some applications */
-#define WAVEOUT_MAXBUFSIZE MAXBUFSIZE
-
-#define WAVEOUT_DEFAULTFRAGLEN 20 /* Time to play a fragment in ms (latency) */
-#define WAVEOUT_DEFAULTBUFLEN 500 /* Time to play the entire buffer in ms */
-
-#define WAVEOUT_MINFRAGSHIFT 6 /* Minimum fragment size in bytes is 2^6 */
-#define WAVEOUT_MINFRAGS 3 /* _don't_ go bellow 3, it would break silence filling */
-#define WAVEOUT_MAXVOICES 6
-
-struct waveout_buffer {
- u16 ossfragshift;
- u32 numfrags;
- u32 fragment_size; /* in bytes units */
- u32 size; /* in bytes units */
- u32 pages; /* buffer size in page units*/
- u32 silence_pos; /* software cursor position (including silence bytes) */
- u32 hw_pos; /* hardware cursor position */
- u32 free_bytes; /* free bytes available on the buffer (not including silence bytes) */
- u8 fill_silence;
- u32 silence_bytes; /* silence bytes on the buffer */
-};
-
-struct woinst
-{
- u8 state;
- u8 num_voices;
- struct emu_voice voice[WAVEOUT_MAXVOICES];
- struct emu_timer timer;
- struct wave_format format;
- struct waveout_buffer buffer;
- wait_queue_head_t wait_queue;
- u8 mmapped;
- u32 total_copied; /* total number of bytes written() to the buffer (excluding silence) */
- u32 total_played; /* total number of bytes played including silence */
- u32 blocks;
- u8 device;
- spinlock_t lock;
-};
-
-int emu10k1_waveout_open(struct emu10k1_wavedevice *);
-void emu10k1_waveout_close(struct emu10k1_wavedevice *);
-void emu10k1_waveout_start(struct emu10k1_wavedevice *);
-void emu10k1_waveout_stop(struct emu10k1_wavedevice *);
-void emu10k1_waveout_getxfersize(struct woinst*, u32 *);
-void emu10k1_waveout_xferdata(struct woinst*, u8 __user *, u32 *);
-void emu10k1_waveout_fillsilence(struct woinst*);
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice*, struct wave_format*);
-void emu10k1_waveout_update(struct woinst*);
-
-#endif /* _CARDWO_H */
diff --git a/sound/oss/emu10k1/ecard.c b/sound/oss/emu10k1/ecard.c
deleted file mode 100644
index 4ae635fe1402..000000000000
--- a/sound/oss/emu10k1/ecard.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- **********************************************************************
- * ecard.c - E-card initialization code
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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 "ecard.h"
-#include "hwaccess.h"
-
-/* Private routines */
-static void ecard_setadcgain(struct emu10k1_card *, struct ecard_state *, u16);
-static void ecard_write(struct emu10k1_card *, u32);
-
-/**************************************************************************
- * @func Set the gain of the ECARD's CS3310 Trim/gain controller. The
- * trim value consists of a 16bit value which is composed of two
- * 8 bit gain/trim values, one for the left channel and one for the
- * right channel. The following table maps from the Gain/Attenuation
- * value in decibels into the corresponding bit pattern for a single
- * channel.
- */
-
-static void ecard_setadcgain(struct emu10k1_card *card, struct ecard_state *ecard, u16 gain)
-{
- u32 currbit;
- ecard->adc_gain = gain;
-
- /* Enable writing to the TRIM registers */
- ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
-
- /* Do it again to insure that we meet hold time requirements */
- ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
-
- for (currbit = (1L << 15); currbit; currbit >>= 1) {
-
- u32 value = ecard->control_bits & ~(EC_TRIM_CSN|EC_TRIM_SDATA);
-
- if (gain & currbit)
- value |= EC_TRIM_SDATA;
-
- /* Clock the bit */
- ecard_write(card, value);
- ecard_write(card, value | EC_TRIM_SCLK);
- ecard_write(card, value);
- }
-
- ecard_write(card, ecard->control_bits);
-}
-
-/**************************************************************************
- * @func Clock bits into the Ecard's control latch. The Ecard uses a
- * control latch will is loaded bit-serially by toggling the Modem control
- * lines from function 2 on the E8010. This function hides these details
- * and presents the illusion that we are actually writing to a distinct
- * register.
- */
-static void ecard_write(struct emu10k1_card *card, u32 value)
-{
- u16 count;
- u32 data, hcvalue;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
-
- hcvalue = inl(card->iobase + HCFG) & ~(HOOKN_BIT|HANDN_BIT|PULSEN_BIT);
-
- outl(card->iobase + HCFG, hcvalue);
-
- for (count = 0 ; count < EC_NUM_CONTROL_BITS; count++) {
-
- /* Set up the value */
- data = ((value & 0x1) ? PULSEN_BIT : 0);
- value >>= 1;
-
- outl(card->iobase + HCFG, hcvalue | data);
-
- /* Clock the shift register */
- outl(card->iobase + HCFG, hcvalue | data | HANDN_BIT);
- outl(card->iobase + HCFG, hcvalue | data);
- }
-
- /* Latch the bits */
- outl(card->iobase + HCFG, hcvalue | HOOKN_BIT);
- outl(card->iobase + HCFG, hcvalue);
-
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-void __devinit emu10k1_ecard_init(struct emu10k1_card *card)
-{
- u32 hcvalue;
- struct ecard_state ecard;
-
- /* Set up the initial settings */
- ecard.mux0_setting = EC_DEFAULT_SPDIF0_SEL;
- ecard.mux1_setting = EC_DEFAULT_SPDIF1_SEL;
- ecard.mux2_setting = 0;
- ecard.adc_gain = EC_DEFAULT_ADC_GAIN;
- ecard.control_bits = EC_RAW_RUN_MODE |
- EC_SPDIF0_SELECT(ecard.mux0_setting) |
- EC_SPDIF1_SELECT(ecard.mux1_setting);
-
-
- /* Step 0: Set the codec type in the hardware control register
- * and enable audio output */
- hcvalue = emu10k1_readfn0(card, HCFG);
- emu10k1_writefn0(card, HCFG, hcvalue | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S);
-
- /* Step 1: Turn off the led and deassert TRIM_CS */
- ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
-
- /* Step 2: Calibrate the ADC and DAC */
- ecard_write(card, EC_DACCAL | EC_LEDN | EC_TRIM_CSN);
-
- /* Step 3: Wait for awhile; FIXME: Is this correct? */
-
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ);
-
- /* Step 4: Switch off the DAC and ADC calibration. Note
- * That ADC_CAL is actually an inverted signal, so we assert
- * it here to stop calibration. */
- ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
-
- /* Step 4: Switch into run mode */
- ecard_write(card, ecard.control_bits);
-
- /* Step 5: Set the analog input gain */
- ecard_setadcgain(card, &ecard, ecard.adc_gain);
-}
-
-
diff --git a/sound/oss/emu10k1/ecard.h b/sound/oss/emu10k1/ecard.h
deleted file mode 100644
index 67aead16e8ec..000000000000
--- a/sound/oss/emu10k1/ecard.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- **********************************************************************
- * ecard.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _ECARD_H
-#define _ECARD_H
-
-#include "8010.h"
-#include "hwaccess.h"
-#include <linux/init.h>
-
-/* In A1 Silicon, these bits are in the HC register */
-#define HOOKN_BIT (1L << 12)
-#define HANDN_BIT (1L << 11)
-#define PULSEN_BIT (1L << 10)
-
-#define EC_GDI1 (1 << 13)
-#define EC_GDI0 (1 << 14)
-
-#define EC_NUM_CONTROL_BITS 20
-
-#define EC_AC3_DATA_SELN 0x0001L
-#define EC_EE_DATA_SEL 0x0002L
-#define EC_EE_CNTRL_SELN 0x0004L
-#define EC_EECLK 0x0008L
-#define EC_EECS 0x0010L
-#define EC_EESDO 0x0020L
-#define EC_TRIM_CSN 0x0040L
-#define EC_TRIM_SCLK 0x0080L
-#define EC_TRIM_SDATA 0x0100L
-#define EC_TRIM_MUTEN 0x0200L
-#define EC_ADCCAL 0x0400L
-#define EC_ADCRSTN 0x0800L
-#define EC_DACCAL 0x1000L
-#define EC_DACMUTEN 0x2000L
-#define EC_LEDN 0x4000L
-
-#define EC_SPDIF0_SEL_SHIFT 15
-#define EC_SPDIF1_SEL_SHIFT 17
-#define EC_SPDIF0_SEL_MASK (0x3L << EC_SPDIF0_SEL_SHIFT)
-#define EC_SPDIF1_SEL_MASK (0x7L << EC_SPDIF1_SEL_SHIFT)
-#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK)
-#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK)
-#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory. This should
- * be incremented any time the EEPROM's
- * format is changed. */
-
-#define EC_EEPROM_SIZE 0x40 /* ECARD EEPROM has 64 16-bit words */
-
-/* Addresses for special values stored in to EEPROM */
-#define EC_PROM_VERSION_ADDR 0x20 /* Address of the current prom version */
-#define EC_BOARDREV0_ADDR 0x21 /* LSW of board rev */
-#define EC_BOARDREV1_ADDR 0x22 /* MSW of board rev */
-
-#define EC_LAST_PROMFILE_ADDR 0x2f
-
-#define EC_SERIALNUM_ADD 0x30 /* First word of serial number. The number
- * can be up to 30 characters in length
- * and is stored as a NULL-terminated
- * ASCII string. Any unused bytes must be
- * filled with zeros */
-#define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */
-
-
-
-/* Most of this stuff is pretty self-evident. According to the hardware
- * dudes, we need to leave the ADCCAL bit low in order to avoid a DC
- * offset problem. Weird.
- */
-#define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | EC_TRIM_CSN)
-
-
-#define EC_DEFAULT_ADC_GAIN 0xC4C4
-#define EC_DEFAULT_SPDIF0_SEL 0x0
-#define EC_DEFAULT_SPDIF1_SEL 0x4
-
-#define HC_EA 0x01L
-
-/* ECARD state structure. This structure maintains the state
- * for various portions of the ECARD's onboard hardware.
- */
-struct ecard_state {
- u32 control_bits;
- u16 adc_gain;
- u16 mux0_setting;
- u16 mux1_setting;
- u16 mux2_setting;
-};
-
-void emu10k1_ecard_init(struct emu10k1_card *) __devinit;
-
-#endif /* _ECARD_H */
diff --git a/sound/oss/emu10k1/efxmgr.c b/sound/oss/emu10k1/efxmgr.c
deleted file mode 100644
index 7d5865de4c2e..000000000000
--- a/sound/oss/emu10k1/efxmgr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- **********************************************************************
- * efxmgr.c
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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/bitops.h>
-#include "hwaccess.h"
-#include "efxmgr.h"
-
-int emu10k1_find_control_gpr(struct patch_manager *mgr, const char *patch_name, const char *gpr_name)
-{
- struct dsp_patch *patch;
- struct dsp_rpatch *rpatch;
- char s[PATCH_NAME_SIZE + 4];
- unsigned long *gpr_used;
- int i;
-
- DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name);
-
- rpatch = &mgr->rpatch;
- if (!strcmp(rpatch->name, patch_name)) {
- gpr_used = rpatch->gpr_used;
- goto match;
- }
-
- for (i = 0; i < mgr->current_pages * PATCHES_PER_PAGE; i++) {
- patch = PATCH(mgr, i);
- sprintf(s,"%s", patch->name);
-
- if (!strcmp(s, patch_name)) {
- gpr_used = patch->gpr_used;
- goto match;
- }
- }
-
- return -1;
-
- match:
- for (i = 0; i < NUM_GPRS; i++)
- if (mgr->gpr[i].type == GPR_TYPE_CONTROL &&
- test_bit(i, gpr_used) &&
- !strcmp(mgr->gpr[i].name, gpr_name))
- return i;
-
- return -1;
-}
-
-void emu10k1_set_control_gpr(struct emu10k1_card *card, int addr, s32 val, int flag)
-{
- struct patch_manager *mgr = &card->mgr;
-
- DPD(2, "emu10k1_set_control_gpr(): %d %x\n", addr, val);
-
- if (addr < 0 || addr >= NUM_GPRS)
- return;
-
- //fixme: once patch manager is up, remember to fix this for the audigy
- if (card->is_audigy) {
- sblive_writeptr(card, A_GPR_BASE + addr, 0, val);
- } else {
- if (flag)
- val += sblive_readptr(card, GPR_BASE + addr, 0);
- if (val > mgr->gpr[addr].max)
- val = mgr->gpr[addr].max;
- else if (val < mgr->gpr[addr].min)
- val = mgr->gpr[addr].min;
- sblive_writeptr(card, GPR_BASE + addr, 0, val);
- }
-
-
-}
-
-//TODO: make this configurable:
-#define VOLCTRL_CHANNEL SOUND_MIXER_VOLUME
-#define VOLCTRL_STEP_SIZE 5
-
-//An internal function for setting OSS mixer controls.
-static void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer,
- unsigned int left, unsigned int right)
-{
- extern char volume_params[SOUND_MIXER_NRDEVICES];
-
- card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
-
- if (!card->is_aps)
- card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
-
- emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
- volume_params[oss_mixer]);
-
- emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right,
- volume_params[oss_mixer]);
-}
-
-//FIXME: mute should unmute when pressed a second time
-void emu10k1_mute_irqhandler(struct emu10k1_card *card)
-{
- int oss_channel = VOLCTRL_CHANNEL;
- int left, right;
- static int val;
-
- if (val) {
- left = val & 0xff;
- right = (val >> 8) & 0xff;
- val = 0;
- } else {
- val = card->ac97->mixer_state[oss_channel];
- left = 0;
- right = 0;
- }
-
- emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_volincr_irqhandler(struct emu10k1_card *card)
-{
- int oss_channel = VOLCTRL_CHANNEL;
- int left, right;
-
- left = card->ac97->mixer_state[oss_channel] & 0xff;
- right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
-
- if ((left += VOLCTRL_STEP_SIZE) > 100)
- left = 100;
-
- if ((right += VOLCTRL_STEP_SIZE) > 100)
- right = 100;
-
- emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_voldecr_irqhandler(struct emu10k1_card *card)
-{
- int oss_channel = VOLCTRL_CHANNEL;
- int left, right;
-
- left = card->ac97->mixer_state[oss_channel] & 0xff;
- right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
-
- if ((left -= VOLCTRL_STEP_SIZE) < 0)
- left = 0;
-
- if ((right -= VOLCTRL_STEP_SIZE) < 0)
- right = 0;
-
- emu10k1_set_oss_vol(card, oss_channel, left, right);
-}
-
-void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale)
-{
- struct patch_manager *mgr = &card->mgr;
- unsigned long flags;
-
- static const s32 log2lin[4] ={ // attenuation (dB)
- 0x7fffffff, // 0.0
- 0x7fffffff * 0.840896415253715 , // 1.5
- 0x7fffffff * 0.707106781186548, // 3.0
- 0x7fffffff * 0.594603557501361 , // 4.5
- };
-
- if (addr < 0)
- return;
-
- vol = (100 - vol ) * scale / 100;
-
- // Thanks to the comp.dsp newsgroup for this neat trick:
- vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
-
- spin_lock_irqsave(&mgr->lock, flags);
- emu10k1_set_control_gpr(card, addr, vol, 0);
- spin_unlock_irqrestore(&mgr->lock, flags);
-}
-
-void emu10k1_dsp_irqhandler(struct emu10k1_card *card)
-{
- unsigned long flags;
-
- if (card->pt.state != PT_STATE_INACTIVE) {
- u32 bc;
- bc = sblive_readptr(card, GPR_BASE + card->pt.intr_gpr, 0);
- if (bc != 0) {
- DPD(3, "pt interrupt, bc = %d\n", bc);
- spin_lock_irqsave(&card->pt.lock, flags);
- card->pt.blocks_played = bc;
- if (card->pt.blocks_played >= card->pt.blocks_copied) {
- DPF(1, "buffer underrun in passthrough playback\n");
- emu10k1_pt_stop(card);
- }
- wake_up_interruptible(&card->pt.wait);
- spin_unlock_irqrestore(&card->pt.lock, flags);
- }
- }
-}
-
diff --git a/sound/oss/emu10k1/efxmgr.h b/sound/oss/emu10k1/efxmgr.h
deleted file mode 100644
index ef48e5c70d1f..000000000000
--- a/sound/oss/emu10k1/efxmgr.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- **********************************************************************
- * sblive_fx.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _EFXMGR_H
-#define _EFXMGR_H
-
-struct emu_efx_info_t{
- int opcode_shift;
- int high_operand_shift;
- int instruction_start;
- int gpr_base;
- int output_base;
-};
-
-
-#define WRITE_EFX(a, b, c) sblive_writeptr((a), emu_efx_info[card->is_audigy].instruction_start + (b), 0, (c))
-
-#define OP(op, z, w, x, y) \
- do { WRITE_EFX(card, (pc) * 2, ((x) << emu_efx_info[card->is_audigy].high_operand_shift) | (y)); \
- WRITE_EFX(card, (pc) * 2 + 1, ((op) << emu_efx_info[card->is_audigy].opcode_shift ) | ((z) << emu_efx_info[card->is_audigy].high_operand_shift) | (w)); \
- ++pc; } while (0)
-
-#define NUM_INPUTS 0x20
-#define NUM_OUTPUTS 0x20
-#define NUM_GPRS 0x100
-
-#define A_NUM_INPUTS 0x60
-#define A_NUM_OUTPUTS 0x60 //fixme: this may or may not be true
-#define A_NUM_GPRS 0x200
-
-#define GPR_NAME_SIZE 32
-#define PATCH_NAME_SIZE 32
-
-struct dsp_rpatch {
- char name[PATCH_NAME_SIZE];
- u16 code_start;
- u16 code_size;
-
- unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
- unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
- unsigned long route[NUM_OUTPUTS];
- unsigned long route_v[NUM_OUTPUTS];
-};
-
-struct dsp_patch {
- char name[PATCH_NAME_SIZE];
- u8 id;
- unsigned long input; /* bitmap of the lines used as inputs */
- unsigned long output; /* bitmap of the lines used as outputs */
- u16 code_start;
- u16 code_size;
-
- unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1]; /* bitmap of used gprs */
- unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
- u8 traml_istart; /* starting address of the internal tram lines used */
- u8 traml_isize; /* number of internal tram lines used */
-
- u8 traml_estart;
- u8 traml_esize;
-
- u16 tramb_istart; /* starting address of the internal tram memory used */
- u16 tramb_isize; /* amount of internal memory used */
- u32 tramb_estart;
- u32 tramb_esize;
-};
-
-struct dsp_gpr {
- u8 type; /* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
- char name[GPR_NAME_SIZE]; /* gpr value, only valid for control gprs */
- s32 min, max; /* value range for this gpr, only valid for control gprs */
- u8 line; /* which input/output line is the gpr attached, only valid for input/output gprs */
- u8 usage;
-};
-
-enum {
- GPR_TYPE_NULL = 0,
- GPR_TYPE_IO,
- GPR_TYPE_STATIC,
- GPR_TYPE_DYNAMIC,
- GPR_TYPE_CONTROL,
- GPR_TYPE_CONSTANT
-};
-
-#define GPR_BASE 0x100
-#define OUTPUT_BASE 0x20
-
-#define A_GPR_BASE 0x400
-#define A_OUTPUT_BASE 0x60
-
-#define MAX_PATCHES_PAGES 32
-
-struct patch_manager {
- void *patch[MAX_PATCHES_PAGES];
- int current_pages;
- struct dsp_rpatch rpatch;
- struct dsp_gpr gpr[NUM_GPRS]; /* gpr usage table */
- spinlock_t lock;
- s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2];
-};
-
-#define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch))
-
-#define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE)
-
-/* PCM volume control */
-#define TMP_PCM_L 0x100 //temp PCM L (after the vol control)
-#define TMP_PCM_R 0x101
-#define VOL_PCM_L 0x102 //vol PCM
-#define VOL_PCM_R 0x103
-
-/* Routing patch */
-#define TMP_AC_L 0x104 //tmp ac97 out
-#define TMP_AC_R 0x105
-#define TMP_REAR_L 0x106 //output - Temp Rear
-#define TMP_REAR_R 0x107
-#define TMP_DIGI_L 0x108 //output - Temp digital
-#define TMP_DIGI_R 0x109
-#define DSP_VOL_L 0x10a // main dsp volume
-#define DSP_VOL_R 0x10b
-
-/* hw inputs */
-#define PCM_IN_L 0x00
-#define PCM_IN_R 0x01
-
-#define PCM1_IN_L 0x04
-#define PCM1_IN_R 0x05
-//mutilchannel playback stream appear here:
-
-#define MULTI_FRONT_L 0x08
-#define MULTI_FRONT_R 0x09
-#define MULTI_REAR_L 0x0a
-#define MULTI_REAR_R 0x0b
-#define MULTI_CENTER 0x0c
-#define MULTI_LFE 0x0d
-
-#define AC97_IN_L 0x10
-#define AC97_IN_R 0x11
-#define SPDIF_CD_L 0x12
-#define SPDIF_CD_R 0x13
-
-/* hw outputs */
-#define AC97_FRONT_L 0x20
-#define AC97_FRONT_R 0x21
-#define DIGITAL_OUT_L 0x22
-#define DIGITAL_OUT_R 0x23
-#define DIGITAL_CENTER 0x24
-#define DIGITAL_LFE 0x25
-
-#define ANALOG_REAR_L 0x28
-#define ANALOG_REAR_R 0x29
-#define ADC_REC_L 0x2a
-#define ADC_REC_R 0x2b
-
-#define ANALOG_CENTER 0x31
-#define ANALOG_LFE 0x32
-
-
-#define INPUT_PATCH_START(patch, nm, ln, i) \
-do { \
- patch = PATCH(mgr, patch_n); \
- strcpy(patch->name, nm); \
- patch->code_start = pc * 2; \
- patch->input = (1<<(0x1f&ln)); \
- patch->output= (1<<(0x1f&ln)); \
- patch->id = i; \
-} while(0)
-
-#define INPUT_PATCH_END(patch) \
-do { \
- patch->code_size = pc * 2 - patch->code_start; \
- patch_n++; \
-} while(0)
-
-
-#define ROUTING_PATCH_START(patch, nm) \
-do { \
- patch = &mgr->rpatch; \
- strcpy(patch->name, nm); \
- patch->code_start = pc * 2; \
-} while(0)
-
-#define ROUTING_PATCH_END(patch) \
-do { \
- patch->code_size = pc * 2 - patch->code_start; \
-} while(0)
-
-#define CONNECT(input, output) set_bit(input, &rpatch->route[(output) - OUTPUT_BASE]);
-
-#define CONNECT_V(input, output) set_bit(input, &rpatch->route_v[(output) - OUTPUT_BASE]);
-
-#define OUTPUT_PATCH_START(patch, nm, ln, i) \
-do { \
- patch = PATCH(mgr, patch_n); \
- strcpy(patch->name, nm); \
- patch->code_start = pc * 2; \
- patch->input = (1<<(0x1f&ln)); \
- patch->output= (1<<(0x1f&ln)); \
- patch->id = i; \
-} while(0)
-
-#define OUTPUT_PATCH_END(patch) \
-do { \
- patch->code_size = pc * 2 - patch->code_start; \
- patch_n++; \
-} while(0)
-
-#define GET_OUTPUT_GPR(patch, g, ln) \
-do { \
- mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_IO; \
- mgr->gpr[(g) - GPR_BASE].usage++; \
- mgr->gpr[(g) - GPR_BASE].line = ln; \
- set_bit((g) - GPR_BASE, patch->gpr_used); \
-} while(0)
-
-#define GET_INPUT_GPR(patch, g, ln) \
-do { \
- mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_IO; \
- mgr->gpr[(g) - GPR_BASE].usage++; \
- mgr->gpr[(g) - GPR_BASE].line = ln; \
- set_bit((g) - GPR_BASE, patch->gpr_used); \
- set_bit((g) - GPR_BASE, patch->gpr_input); \
-} while(0)
-
-#define GET_DYNAMIC_GPR(patch, g) \
-do { \
- mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_DYNAMIC; \
- mgr->gpr[(g) - GPR_BASE].usage++; \
- set_bit((g) - GPR_BASE, patch->gpr_used); \
-} while(0)
-
-#define GET_CONTROL_GPR(patch, g, nm, a, b) \
-do { \
- strcpy(mgr->gpr[(g) - GPR_BASE].name, nm); \
- mgr->gpr[(g) - GPR_BASE].type = GPR_TYPE_CONTROL; \
- mgr->gpr[(g) - GPR_BASE].usage++; \
- mgr->gpr[(g) - GPR_BASE].min = a; \
- mgr->gpr[(g) - GPR_BASE].max = b; \
- sblive_writeptr(card, g, 0, b); \
- set_bit((g) - GPR_BASE, patch->gpr_used); \
-} while(0)
-
-#endif /* _EFXMGR_H */
diff --git a/sound/oss/emu10k1/emuadxmg.c b/sound/oss/emu10k1/emuadxmg.c
deleted file mode 100644
index d7d2d4caf7ba..000000000000
--- a/sound/oss/emu10k1/emuadxmg.c
+++ /dev/null
@@ -1,104 +0,0 @@
-
-/*
- **********************************************************************
- * emuadxmg.c - Address space manager for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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 "hwaccess.h"
-
-/* Allocates emu address space */
-
-int emu10k1_addxmgr_alloc(u32 size, struct emu10k1_card *card)
-{
- u16 *pagetable = card->emupagetable;
- u16 index = 0;
- u16 numpages;
- unsigned long flags;
-
- /* Convert bytes to pages */
- numpages = (size / EMUPAGESIZE) + ((size % EMUPAGESIZE) ? 1 : 0);
-
- spin_lock_irqsave(&card->lock, flags);
-
- while (index < (MAXPAGES - 1)) {
- if (pagetable[index] & 0x8000) {
- /* This block of pages is in use, jump to the start of the next block. */
- index += (pagetable[index] & 0x7fff);
- } else {
- /* Found free block */
- if (pagetable[index] >= numpages) {
-
- /* Block is large enough */
-
- /* If free block is larger than the block requested
- * then adjust the size of the block remaining */
- if (pagetable[index] > numpages)
- pagetable[index + numpages] = pagetable[index] - numpages;
-
- pagetable[index] = (numpages | 0x8000); /* Mark block as used */
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- return index;
- } else {
- /* Block too small, jump to the start of the next block */
- index += pagetable[index];
- }
- }
- }
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- return -1;
-}
-
-/* Frees a previously allocated emu address space. */
-
-void emu10k1_addxmgr_free(struct emu10k1_card *card, int index)
-{
- u16 *pagetable = card->emupagetable;
- u16 origsize = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
-
- if (pagetable[index] & 0x8000) {
- /* Block is allocated - mark block as free */
- origsize = pagetable[index] & 0x7fff;
- pagetable[index] = origsize;
-
- /* If next block is free, we concat both blocks */
- if (!(pagetable[index + origsize] & 0x8000))
- pagetable[index] += pagetable[index + origsize] & 0x7fff;
- }
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- return;
-}
diff --git a/sound/oss/emu10k1/hwaccess.c b/sound/oss/emu10k1/hwaccess.c
deleted file mode 100644
index 2dc16a841fa1..000000000000
--- a/sound/oss/emu10k1/hwaccess.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- **********************************************************************
- * hwaccess.c -- Hardware access layer
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * December 9, 1999 Jon Taylor rewrote the I/O subsystem
- *
- **********************************************************************
- *
- * 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 <asm/io.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "icardmid.h"
-
-/*************************************************************************
-* Function : srToPitch *
-* Input : sampleRate - sampling rate *
-* Return : pitch value *
-* About : convert sampling rate to pitch *
-* Note : for 8010, sampling rate is at 48kHz, this function should *
-* be changed. *
-*************************************************************************/
-u32 srToPitch(u32 sampleRate)
-{
- int i;
-
- /* FIXME: These tables should be defined in a headerfile */
- static u32 logMagTable[128] = {
- 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
- 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
- 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
- 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
- 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
- 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
- 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
- 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
- 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
- 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
- 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
- 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
- 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
- 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
- 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
- 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
- };
-
- static char logSlopeTable[128] = {
- 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
- 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
- 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
- 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
- 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
- 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
- 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
- 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
- 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
- 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
- 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
- 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
- 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
- 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
- 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
- };
-
- if (sampleRate == 0)
- return 0; /* Bail out if no leading "1" */
-
- sampleRate *= 11185; /* Scale 48000 to 0x20002380 */
-
- for (i = 31; i > 0; i--) {
- if (sampleRate & 0x80000000) { /* Detect leading "1" */
- return (u32) (((s32) (i - 15) << 20) +
- logMagTable[0x7f & (sampleRate >> 24)] +
- (0x7f & (sampleRate >> 17)) * logSlopeTable[0x7f & (sampleRate >> 24)]);
- }
- sampleRate = sampleRate << 1;
- }
-
- DPF(2, "srToPitch: BUG!\n");
- return 0; /* Should never reach this point */
-}
-
-/*******************************************
-* write/read PCI function 0 registers *
-********************************************/
-void emu10k1_writefn0(struct emu10k1_card *card, u32 reg, u32 data)
-{
- unsigned long flags;
-
- if (reg & 0xff000000) {
- u32 mask;
- u8 size, offset;
-
- size = (reg >> 24) & 0x3f;
- offset = (reg >> 16) & 0x1f;
- mask = ((1 << size) - 1) << offset;
- data = (data << offset) & mask;
- reg &= 0x7f;
-
- spin_lock_irqsave(&card->lock, flags);
- data |= inl(card->iobase + reg) & ~mask;
- outl(data, card->iobase + reg);
- spin_unlock_irqrestore(&card->lock, flags);
- } else {
- spin_lock_irqsave(&card->lock, flags);
- outl(data, card->iobase + reg);
- spin_unlock_irqrestore(&card->lock, flags);
- }
-
- return;
-}
-
-#ifdef DBGEMU
-void emu10k1_writefn0_2(struct emu10k1_card *card, u32 reg, u32 data, int size)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
-
- if (size == 32)
- outl(data, card->iobase + (reg & 0x1F));
- else if (size == 16)
- outw(data, card->iobase + (reg & 0x1F));
- else
- outb(data, card->iobase + (reg & 0x1F));
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- return;
-}
-#endif /* DBGEMU */
-
-u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg)
-{
- u32 val;
- unsigned long flags;
-
- if (reg & 0xff000000) {
- u32 mask;
- u8 size, offset;
-
- size = (reg >> 24) & 0x3f;
- offset = (reg >> 16) & 0x1f;
- mask = ((1 << size) - 1) << offset;
- reg &= 0x7f;
-
- spin_lock_irqsave(&card->lock, flags);
- val = inl(card->iobase + reg);
- spin_unlock_irqrestore(&card->lock, flags);
-
- return (val & mask) >> offset;
- } else {
- spin_lock_irqsave(&card->lock, flags);
- val = inl(card->iobase + reg);
- spin_unlock_irqrestore(&card->lock, flags);
- return val;
- }
-}
-
-void emu10k1_timer_set(struct emu10k1_card * card, u16 data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
- outw(data & TIMER_RATE_MASK, card->iobase + TIMER);
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/************************************************************************
-* write/read Emu10k1 pointer-offset register set, accessed through *
-* the PTR and DATA registers *
-*************************************************************************/
-#define A_PTR_ADDRESS_MASK 0x0fff0000
-void sblive_writeptr(struct emu10k1_card *card, u32 reg, u32 channel, u32 data)
-{
- u32 regptr;
- unsigned long flags;
-
- regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
-
- if (reg & 0xff000000) {
- u32 mask;
- u8 size, offset;
-
- size = (reg >> 24) & 0x3f;
- offset = (reg >> 16) & 0x1f;
- mask = ((1 << size) - 1) << offset;
- data = (data << offset) & mask;
-
- spin_lock_irqsave(&card->lock, flags);
- outl(regptr, card->iobase + PTR);
- data |= inl(card->iobase + DATA) & ~mask;
- outl(data, card->iobase + DATA);
- spin_unlock_irqrestore(&card->lock, flags);
- } else {
- spin_lock_irqsave(&card->lock, flags);
- outl(regptr, card->iobase + PTR);
- outl(data, card->iobase + DATA);
- spin_unlock_irqrestore(&card->lock, flags);
- }
-}
-
-/* ... : data, reg, ... , TAGLIST_END */
-void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...)
-{
- va_list args;
-
- unsigned long flags;
- u32 reg;
-
- va_start(args, channel);
-
- spin_lock_irqsave(&card->lock, flags);
- while ((reg = va_arg(args, u32)) != TAGLIST_END) {
- u32 data = va_arg(args, u32);
- u32 regptr = (((reg << 16) & A_PTR_ADDRESS_MASK)
- | (channel & PTR_CHANNELNUM_MASK));
- outl(regptr, card->iobase + PTR);
- if (reg & 0xff000000) {
- int size = (reg >> 24) & 0x3f;
- int offset = (reg >> 16) & 0x1f;
- u32 mask = ((1 << size) - 1) << offset;
- data = (data << offset) & mask;
-
- data |= inl(card->iobase + DATA) & ~mask;
- }
- outl(data, card->iobase + DATA);
- }
- spin_unlock_irqrestore(&card->lock, flags);
-
- va_end(args);
-
- return;
-}
-
-u32 sblive_readptr(struct emu10k1_card * card, u32 reg, u32 channel)
-{
- u32 regptr, val;
- unsigned long flags;
-
- regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
-
- if (reg & 0xff000000) {
- u32 mask;
- u8 size, offset;
-
- size = (reg >> 24) & 0x3f;
- offset = (reg >> 16) & 0x1f;
- mask = ((1 << size) - 1) << offset;
-
- spin_lock_irqsave(&card->lock, flags);
- outl(regptr, card->iobase + PTR);
- val = inl(card->iobase + DATA);
- spin_unlock_irqrestore(&card->lock, flags);
-
- return (val & mask) >> offset;
- } else {
- spin_lock_irqsave(&card->lock, flags);
- outl(regptr, card->iobase + PTR);
- val = inl(card->iobase + DATA);
- spin_unlock_irqrestore(&card->lock, flags);
-
- return val;
- }
-}
-
-void emu10k1_irq_enable(struct emu10k1_card *card, u32 irq_mask)
-{
- u32 val;
- unsigned long flags;
-
- DPF(2,"emu10k1_irq_enable()\n");
-
- spin_lock_irqsave(&card->lock, flags);
- val = inl(card->iobase + INTE) | irq_mask;
- outl(val, card->iobase + INTE);
- spin_unlock_irqrestore(&card->lock, flags);
- return;
-}
-
-void emu10k1_irq_disable(struct emu10k1_card *card, u32 irq_mask)
-{
- u32 val;
- unsigned long flags;
-
- DPF(2,"emu10k1_irq_disable()\n");
-
- spin_lock_irqsave(&card->lock, flags);
- val = inl(card->iobase + INTE) & ~irq_mask;
- outl(val, card->iobase + INTE);
- spin_unlock_irqrestore(&card->lock, flags);
- return;
-}
-
-void emu10k1_clear_stop_on_loop(struct emu10k1_card *card, u32 voicenum)
-{
- /* Voice interrupt */
- if (voicenum >= 32)
- sblive_writeptr(card, SOLEH | ((0x0100 | (voicenum - 32)) << 16), 0, 0);
- else
- sblive_writeptr(card, SOLEL | ((0x0100 | voicenum) << 16), 0, 0);
-
- return;
-}
-
-static void sblive_wcwait(struct emu10k1_card *card, u32 wait)
-{
- volatile unsigned uCount;
- u32 newtime = 0, curtime;
-
- curtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
- while (wait--) {
- uCount = 0;
- while (uCount++ < TIMEOUT) {
- newtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
- if (newtime != curtime)
- break;
- }
-
- if (uCount >= TIMEOUT)
- break;
-
- curtime = newtime;
- }
-}
-
-u16 emu10k1_ac97_read(struct ac97_codec *codec, u8 reg)
-{
- struct emu10k1_card *card = codec->private_data;
- u16 data;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
-
- outb(reg, card->iobase + AC97ADDRESS);
- data = inw(card->iobase + AC97DATA);
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- return data;
-}
-
-void emu10k1_ac97_write(struct ac97_codec *codec, u8 reg, u16 value)
-{
- struct emu10k1_card *card = codec->private_data;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
-
- outb(reg, card->iobase + AC97ADDRESS);
- outw(value, card->iobase + AC97DATA);
- outb( AC97_EXTENDED_ID, card->iobase + AC97ADDRESS);
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/*********************************************************
-* MPU access functions *
-**********************************************************/
-
-int emu10k1_mpu_write_data(struct emu10k1_card *card, u8 data)
-{
- unsigned long flags;
- int ret;
-
- if (card->is_audigy) {
- if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_ORDYN) == 0) {
- sblive_writeptr(card, A_MUDATA, 0, data);
- ret = 0;
- } else
- ret = -1;
- } else {
- spin_lock_irqsave(&card->lock, flags);
-
- if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) {
- outb(data, card->iobase + MUDATA);
- ret = 0;
- } else
- ret = -1;
-
- spin_unlock_irqrestore(&card->lock, flags);
- }
-
- return ret;
-}
-
-int emu10k1_mpu_read_data(struct emu10k1_card *card, u8 * data)
-{
- unsigned long flags;
- int ret;
-
- if (card->is_audigy) {
- if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_IRDYN) == 0) {
- *data = sblive_readptr(card, A_MUDATA,0);
- ret = 0;
- } else
- ret = -1;
- } else {
- spin_lock_irqsave(&card->lock, flags);
-
- if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) {
- *data = inb(card->iobase + MUDATA);
- ret = 0;
- } else
- ret = -1;
-
- spin_unlock_irqrestore(&card->lock, flags);
- }
-
- return ret;
-}
-
-int emu10k1_mpu_reset(struct emu10k1_card *card)
-{
- u8 status;
- unsigned long flags;
-
- DPF(2, "emu10k1_mpu_reset()\n");
- if (card->is_audigy) {
- if (card->mpuacqcount == 0) {
- sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
- sblive_wcwait(card, 8);
- sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
- sblive_wcwait(card, 8);
- sblive_writeptr(card, A_MUCMD, 0, MUCMD_ENTERUARTMODE);
- sblive_wcwait(card, 8);
- status = sblive_readptr(card, A_MUDATA, 0);
- if (status == 0xfe)
- return 0;
- else
- return -1;
- }
-
- return 0;
- } else {
- if (card->mpuacqcount == 0) {
- spin_lock_irqsave(&card->lock, flags);
- outb(MUCMD_RESET, card->iobase + MUCMD);
- spin_unlock_irqrestore(&card->lock, flags);
-
- sblive_wcwait(card, 8);
-
- spin_lock_irqsave(&card->lock, flags);
- outb(MUCMD_RESET, card->iobase + MUCMD);
- spin_unlock_irqrestore(&card->lock, flags);
-
- sblive_wcwait(card, 8);
-
- spin_lock_irqsave(&card->lock, flags);
- outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD);
- spin_unlock_irqrestore(&card->lock, flags);
-
- sblive_wcwait(card, 8);
-
- spin_lock_irqsave(&card->lock, flags);
- status = inb(card->iobase + MUDATA);
- spin_unlock_irqrestore(&card->lock, flags);
-
- if (status == 0xfe)
- return 0;
- else
- return -1;
- }
-
- return 0;
- }
-}
-
-int emu10k1_mpu_acquire(struct emu10k1_card *card)
-{
- /* FIXME: This should be a macro */
- ++card->mpuacqcount;
-
- return 0;
-}
-
-int emu10k1_mpu_release(struct emu10k1_card *card)
-{
- /* FIXME: this should be a macro */
- --card->mpuacqcount;
-
- return 0;
-}
diff --git a/sound/oss/emu10k1/hwaccess.h b/sound/oss/emu10k1/hwaccess.h
deleted file mode 100644
index 85e27bda694b..000000000000
--- a/sound/oss/emu10k1/hwaccess.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- **********************************************************************
- * hwaccess.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _HWACCESS_H
-#define _HWACCESS_H
-
-#include <linux/fs.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-
-#include "efxmgr.h"
-#include "passthrough.h"
-#include "midi.h"
-
-#define EMUPAGESIZE 4096 /* don't change */
-#define NUM_G 64 /* use all channels */
-#define NUM_FXSENDS 4 /* don't change */
-/* setting this to other than a power of two may break some applications */
-#define MAXBUFSIZE 65536
-#define MAXPAGES 8192
-#define BUFMAXPAGES (MAXBUFSIZE / PAGE_SIZE)
-
-#define FLAGS_AVAILABLE 0x0001
-#define FLAGS_READY 0x0002
-
-struct memhandle
-{
- dma_addr_t dma_handle;
- void *addr;
- u32 size;
-};
-
-#define DEBUG_LEVEL 2
-
-#ifdef EMU10K1_DEBUG
-# define DPD(level,x,y...) do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ , y );} while(0)
-# define DPF(level,x) do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ );} while(0)
-#else
-# define DPD(level,x,y...) do { } while (0) /* not debugging: nothing */
-# define DPF(level,x) do { } while (0)
-#endif /* EMU10K1_DEBUG */
-
-#define ERROR() DPF(1,"error\n")
-
-/* DATA STRUCTURES */
-
-struct emu10k1_waveout
-{
- u32 send_routing[3];
- // audigy only:
- u32 send_routing2[3];
-
- u32 send_dcba[3];
- // audigy only:
- u32 send_hgfe[3];
-};
-#define ROUTE_PCM 0
-#define ROUTE_PT 1
-#define ROUTE_PCM1 2
-
-#define SEND_MONO 0
-#define SEND_LEFT 1
-#define SEND_RIGHT 2
-
-struct emu10k1_wavein
-{
- struct wiinst *ac97;
- struct wiinst *mic;
- struct wiinst *fx;
-
- u8 recsrc;
- u32 fxwc;
-};
-
-#define CMD_READ 1
-#define CMD_WRITE 2
-
-struct mixer_private_ioctl {
- u32 cmd;
- u32 val[90];
-};
-
-/* bogus ioctls numbers to escape from OSS mixer limitations */
-#define CMD_WRITEFN0 _IOW('D', 0, struct mixer_private_ioctl)
-#define CMD_READFN0 _IOR('D', 1, struct mixer_private_ioctl)
-#define CMD_WRITEPTR _IOW('D', 2, struct mixer_private_ioctl)
-#define CMD_READPTR _IOR('D', 3, struct mixer_private_ioctl)
-#define CMD_SETRECSRC _IOW('D', 4, struct mixer_private_ioctl)
-#define CMD_GETRECSRC _IOR('D', 5, struct mixer_private_ioctl)
-#define CMD_GETVOICEPARAM _IOR('D', 6, struct mixer_private_ioctl)
-#define CMD_SETVOICEPARAM _IOW('D', 7, struct mixer_private_ioctl)
-#define CMD_GETPATCH _IOR('D', 8, struct mixer_private_ioctl)
-#define CMD_GETGPR _IOR('D', 9, struct mixer_private_ioctl)
-#define CMD_GETCTLGPR _IOR('D', 10, struct mixer_private_ioctl)
-#define CMD_SETPATCH _IOW('D', 11, struct mixer_private_ioctl)
-#define CMD_SETGPR _IOW('D', 12, struct mixer_private_ioctl)
-#define CMD_SETCTLGPR _IOW('D', 13, struct mixer_private_ioctl)
-#define CMD_SETGPOUT _IOW('D', 14, struct mixer_private_ioctl)
-#define CMD_GETGPR2OSS _IOR('D', 15, struct mixer_private_ioctl)
-#define CMD_SETGPR2OSS _IOW('D', 16, struct mixer_private_ioctl)
-#define CMD_SETMCH_FX _IOW('D', 17, struct mixer_private_ioctl)
-#define CMD_SETPASSTHROUGH _IOW('D', 18, struct mixer_private_ioctl)
-#define CMD_PRIVATE3_VERSION _IOW('D', 19, struct mixer_private_ioctl)
-#define CMD_AC97_BOOST _IOW('D', 20, struct mixer_private_ioctl)
-
-//up this number when breaking compatibility
-#define PRIVATE3_VERSION 2
-
-struct emu10k1_card
-{
- struct list_head list;
-
- struct memhandle virtualpagetable;
- struct memhandle tankmem;
- struct memhandle silentpage;
-
- spinlock_t lock;
-
- u8 voicetable[NUM_G];
- u16 emupagetable[MAXPAGES];
-
- struct list_head timers;
- u16 timer_delay;
- spinlock_t timer_lock;
-
- struct pci_dev *pci_dev;
- unsigned long iobase;
- unsigned long length;
- unsigned short model;
- unsigned int irq;
-
- int audio_dev;
- int audio_dev1;
- int midi_dev;
-#ifdef EMU10K1_SEQUENCER
- int seq_dev;
- struct emu10k1_mididevice *seq_mididev;
-#endif
-
- struct ac97_codec *ac97;
- int ac97_supported_mixers;
- int ac97_stereo_mixers;
-
- /* Number of first fx voice for multichannel output */
- u8 mchannel_fx;
- struct emu10k1_waveout waveout;
- struct emu10k1_wavein wavein;
- struct emu10k1_mpuout *mpuout;
- struct emu10k1_mpuin *mpuin;
-
- struct mutex open_sem;
- mode_t open_mode;
- wait_queue_head_t open_wait;
-
- u32 mpuacqcount; // Mpu acquire count
- u32 has_toslink; // TOSLink detection
-
- u8 chiprev; /* Chip revision */
- u8 is_audigy;
- u8 is_aps;
-
- struct patch_manager mgr;
- struct pt_data pt;
-};
-
-int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
-void emu10k1_addxmgr_free(struct emu10k1_card *, int);
-
-int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *);
-void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int );
-
-void emu10k1_set_volume_gpr(struct emu10k1_card *, int, s32, int);
-
-
-#define VOL_6BIT 0x40
-#define VOL_5BIT 0x20
-#define VOL_4BIT 0x10
-
-#define TIMEOUT 16384
-
-u32 srToPitch(u32);
-
-extern struct list_head emu10k1_devs;
-
-/* Hardware Abstraction Layer access functions */
-
-void emu10k1_writefn0(struct emu10k1_card *, u32, u32);
-void emu10k1_writefn0_2(struct emu10k1_card *, u32, u32, int);
-u32 emu10k1_readfn0(struct emu10k1_card *, u32);
-
-void emu10k1_timer_set(struct emu10k1_card *, u16);
-
-void sblive_writeptr(struct emu10k1_card *, u32, u32, u32);
-void sblive_writeptr_tag(struct emu10k1_card *, u32, ...);
-#define TAGLIST_END 0
-
-u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
-
-void emu10k1_irq_enable(struct emu10k1_card *, u32);
-void emu10k1_irq_disable(struct emu10k1_card *, u32);
-void emu10k1_clear_stop_on_loop(struct emu10k1_card *, u32);
-
-/* AC97 Codec register access function */
-u16 emu10k1_ac97_read(struct ac97_codec *, u8);
-void emu10k1_ac97_write(struct ac97_codec *, u8, u16);
-
-/* MPU access function*/
-int emu10k1_mpu_write_data(struct emu10k1_card *, u8);
-int emu10k1_mpu_read_data(struct emu10k1_card *, u8 *);
-int emu10k1_mpu_reset(struct emu10k1_card *);
-int emu10k1_mpu_acquire(struct emu10k1_card *);
-int emu10k1_mpu_release(struct emu10k1_card *);
-
-#endif /* _HWACCESS_H */
diff --git a/sound/oss/emu10k1/icardmid.h b/sound/oss/emu10k1/icardmid.h
deleted file mode 100644
index 6a6ef419401f..000000000000
--- a/sound/oss/emu10k1/icardmid.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- **********************************************************************
- * isblive_mid.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _ICARDMIDI_H
-#define _ICARDMIDI_H
-
-/* MIDI defines */
-#define MIDI_DATA_FIRST 0x00
-#define MIDI_DATA_LAST 0x7F
-#define MIDI_STATUS_FIRST 0x80
-#define MIDI_STATUS_LAST 0xFF
-
-/* Channel status bytes */
-#define MIDI_STATUS_CHANNEL_FIRST 0x80
-#define MIDI_STATUS_CHANNEL_LAST 0xE0
-#define MIDI_STATUS_CHANNEL_MASK 0xF0
-
-/* Channel voice messages */
-#define MIDI_VOICE_NOTE_OFF 0x80
-#define MIDI_VOICE_NOTE_ON 0x90
-#define MIDI_VOICE_POLY_PRESSURE 0xA0
-#define MIDI_VOICE_CONTROL_CHANGE 0xB0
-#define MIDI_VOICE_PROGRAM_CHANGE 0xC0
-#define MIDI_VOICE_CHANNEL_PRESSURE 0xD0
-#define MIDI_VOICE_PITCH_BEND 0xE0
-
-/* Channel mode messages */
-#define MIDI_MODE_CHANNEL MIDI_VOICE_CONTROL_CHANGE
-
-/* System status bytes */
-#define MIDI_STATUS_SYSTEM_FIRST 0xF0
-#define MIDI_STATUS_SYSTEM_LAST 0xFF
-
-/* System exclusive messages */
-#define MIDI_SYSEX_BEGIN 0xF0
-#define MIDI_SYSEX_EOX 0xF7
-
-/* System common messages */
-#define MIDI_COMMON_TCQF 0xF1 /* Time code quarter frame */
-#define MIDI_COMMON_SONG_POSITION 0xF2
-#define MIDI_COMMON_SONG_SELECT 0xF3
-#define MIDI_COMMON_UNDEFINED_F4 0xF4
-#define MIDI_COMMON_UNDEFINED_F5 0xF5
-#define MIDI_COMMON_TUNE_REQUEST 0xF6
-
-/* System real-time messages */
-#define MIDI_RTIME_TIMING_CLOCK 0xF8
-#define MIDI_RTIME_UNDEFINED_F9 0xF9
-#define MIDI_RTIME_START 0xFA
-#define MIDI_RTIME_CONTINUE 0xFB
-#define MIDI_RTIME_STOP 0xFC
-#define MIDI_RTIME_UNDEFINED_FD 0xFD
-#define MIDI_RTIME_ACTIVE_SENSING 0xFE
-#define MIDI_RTIME_SYSTEM_RESET 0xFF
-
-/* Flags for flags parm of midiOutCachePatches(), midiOutCacheDrumPatches() */
-#define MIDI_CACHE_ALL 1
-#define MIDI_CACHE_BESTFIT 2
-#define MIDI_CACHE_QUERY 3
-#define MIDI_UNCACHE 4
-
-/* Event declarations for MPU IRQ Callbacks */
-#define ICARDMIDI_INLONGDATA 0x00000001 /* MIM_LONGDATA */
-#define ICARDMIDI_INLONGERROR 0x00000002 /* MIM_LONGERROR */
-#define ICARDMIDI_OUTLONGDATA 0x00000004 /* MOM_DONE for MPU OUT buffer */
-#define ICARDMIDI_INDATA 0x00000010 /* MIM_DATA */
-#define ICARDMIDI_INDATAERROR 0x00000020 /* MIM_ERROR */
-
-/* Declaration for flags in CARDMIDIBUFFERHDR */
-/* Make it the same as MHDR_DONE, MHDR_INQUEUE in mmsystem.h */
-#define MIDIBUF_DONE 0x00000001
-#define MIDIBUF_INQUEUE 0x00000004
-
-/* Declaration for msg parameter in midiCallbackFn */
-#define ICARDMIDI_OUTBUFFEROK 0x00000001
-#define ICARDMIDI_INMIDIOK 0x00000002
-
-/* Declaration for technology in struct midi_caps */
-#define MT_MIDIPORT 0x00000001 /* In original MIDIOUTCAPS structure */
-#define MT_FMSYNTH 0x00000004 /* In original MIDIOUTCAPS structure */
-#define MT_AWESYNTH 0x00001000
-#define MT_PCISYNTH 0x00002000
-#define MT_PCISYNTH64 0x00004000
-#define CARDMIDI_AWEMASK 0x0000F000
-
-enum LocalErrorCode
-{
- CTSTATUS_NOTENABLED = 0x7000,
- CTSTATUS_READY,
- CTSTATUS_BUSY,
- CTSTATUS_DATAAVAIL,
- CTSTATUS_NODATA,
- CTSTATUS_NEXT_BYTE
-};
-
-/* MIDI data block header */
-struct midi_hdr
-{
- u8 *reserved; /* Pointer to original locked data block */
- u32 bufferlength; /* Length of data in data block */
- u32 bytesrecorded; /* Used for input only */
- u32 user; /* For client's use */
- u32 flags; /* Assorted flags (see defines) */
- struct list_head list; /* Reserved for driver */
- u8 *data; /* Second copy of first pointer */
-};
-
-/* Enumeration for SetControl */
-enum
-{
- MIDIOBJVOLUME = 0x1,
- MIDIQUERYACTIVEINST
-};
-
-struct midi_queue
-{
- struct midi_queue *next;
- u32 qtype; /* 0 = short message, 1 = long data */
- u32 length;
- u32 sizeLeft;
- u8 *midibyte;
- unsigned long refdata;
-};
-
-struct midi_openinfo
-{
- u32 cbsize;
- u32 flags;
- unsigned long refdata;
- u32 streamid;
-};
-
-int emu10k1_midi_callback(unsigned long , unsigned long, unsigned long *);
-
-#endif /* _ICARDMIDI_H */
diff --git a/sound/oss/emu10k1/icardwav.h b/sound/oss/emu10k1/icardwav.h
deleted file mode 100644
index 25be40928b4d..000000000000
--- a/sound/oss/emu10k1/icardwav.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- **********************************************************************
- * icardwav.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _ICARDWAV_H
-#define _ICARDWAV_H
-
-struct wave_format
-{
- int id;
- int samplingrate;
- u8 bitsperchannel;
- u8 channels; /* 1 = Mono, 2 = Stereo, 3, ... = Multichannel */
- u8 bytesperchannel;
- u8 bytespervoicesample;
- u8 bytespersample;
- int bytespersec;
- u8 passthrough;
-};
-
-/* emu10k1_wave states */
-#define WAVE_STATE_OPEN 0x01
-#define WAVE_STATE_STARTED 0x02
-#define WAVE_STATE_CLOSED 0x04
-
-#endif /* _ICARDWAV_H */
diff --git a/sound/oss/emu10k1/irqmgr.c b/sound/oss/emu10k1/irqmgr.c
deleted file mode 100644
index fb2ce638f01c..000000000000
--- a/sound/oss/emu10k1/irqmgr.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- **********************************************************************
- * irqmgr.c - IRQ manager for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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 "hwaccess.h"
-#include "8010.h"
-#include "cardmi.h"
-#include "cardmo.h"
-#include "irqmgr.h"
-
-/* Interrupt handler */
-
-irqreturn_t emu10k1_interrupt(int irq, void *dev_id)
-{
- struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
- u32 irqstatus, irqstatus_tmp;
- int handled = 0;
-
- DPD(4, "emu10k1_interrupt called, irq = %u\n", irq);
-
- /*
- ** NOTE :
- ** We do a 'while loop' here cos on certain machines, with both
- ** playback and recording going on at the same time, IRQs will
- ** stop coming in after a while. Checking IPND indeed shows that
- ** there are interrupts pending but the PIC says no IRQs pending.
- ** I suspect that some boards need edge-triggered IRQs but are not
- ** getting that condition if we don't completely clear the IPND
- ** (make sure no more interrupts are pending).
- ** - Eric
- */
-
- while ((irqstatus = inl(card->iobase + IPR))) {
- DPD(4, "irq status %#x\n", irqstatus);
-
- irqstatus_tmp = irqstatus;
-
- if (irqstatus & IRQTYPE_TIMER) {
- emu10k1_timer_irqhandler(card);
- irqstatus &= ~IRQTYPE_TIMER;
- }
-
- if (irqstatus & IRQTYPE_DSP) {
- emu10k1_dsp_irqhandler(card);
- irqstatus &= ~IRQTYPE_DSP;
- }
-
- if (irqstatus & IRQTYPE_MPUIN) {
- emu10k1_mpuin_irqhandler(card);
- irqstatus &= ~IRQTYPE_MPUIN;
- }
-
- if (irqstatus & IRQTYPE_MPUOUT) {
- emu10k1_mpuout_irqhandler(card);
- irqstatus &= ~IRQTYPE_MPUOUT;
- }
-
- if (irqstatus & IPR_MUTE) {
- emu10k1_mute_irqhandler(card);
- irqstatus &=~IPR_MUTE;
- }
-
- if (irqstatus & IPR_VOLINCR) {
- emu10k1_volincr_irqhandler(card);
- irqstatus &=~IPR_VOLINCR;
- }
-
- if (irqstatus & IPR_VOLDECR) {
- emu10k1_voldecr_irqhandler(card);
- irqstatus &=~IPR_VOLDECR;
- }
-
- if (irqstatus){
- printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus);
- //make sure any interrupts we don't handle are disabled:
- emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB |
- INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE |
- INTE_FXDSPENABLE));
- }
-
- /* acknowledge interrupt */
- outl(irqstatus_tmp, card->iobase + IPR);
- handled = 1;
- }
- return IRQ_RETVAL(handled);
-}
diff --git a/sound/oss/emu10k1/irqmgr.h b/sound/oss/emu10k1/irqmgr.h
deleted file mode 100644
index 7e7c9ca1098c..000000000000
--- a/sound/oss/emu10k1/irqmgr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- **********************************************************************
- * irq.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _IRQ_H
-#define _IRQ_H
-
-/* EMU Irq Types */
-#define IRQTYPE_PCIBUSERROR IPR_PCIERROR
-#define IRQTYPE_MIXERBUTTON (IPR_VOLINCR | IPR_VOLDECR | IPR_MUTE)
-#define IRQTYPE_VOICE (IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK)
-#define IRQTYPE_RECORD (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL | IPR_MICBUFFULL | IPR_MICBUFHALFFULL | IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)
-#define IRQTYPE_MPUOUT (IPR_MIDITRANSBUFEMPTY | A_IPR_MIDITRANSBUFEMPTY2)
-#define IRQTYPE_MPUIN (IPR_MIDIRECVBUFEMPTY | A_IPR_MIDIRECVBUFEMPTY2)
-#define IRQTYPE_TIMER IPR_INTERVALTIMER
-#define IRQTYPE_SPDIF (IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE)
-#define IRQTYPE_DSP IPR_FXDSP
-
-void emu10k1_timer_irqhandler(struct emu10k1_card *);
-void emu10k1_dsp_irqhandler(struct emu10k1_card *);
-void emu10k1_mute_irqhandler(struct emu10k1_card *);
-void emu10k1_volincr_irqhandler(struct emu10k1_card *);
-void emu10k1_voldecr_irqhandler(struct emu10k1_card *);
-
-#endif /* _IRQ_H */
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
deleted file mode 100644
index 5058411b7524..000000000000
--- a/sound/oss/emu10k1/main.c
+++ /dev/null
@@ -1,1471 +0,0 @@
- /*
- **********************************************************************
- * main.c - Creative EMU10K1 audio driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up stuff
- *
- **********************************************************************
- *
- * 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.
- *
- **********************************************************************
- *
- * Supported devices:
- * /dev/dsp: Standard /dev/dsp device, OSS-compatible
- * /dev/dsp1: Routes to rear speakers only
- * /dev/mixer: Standard /dev/mixer device, OSS-compatible
- * /dev/midi: Raw MIDI UART device, mostly OSS-compatible
- * /dev/sequencer: Sequencer Interface (requires sound.o)
- *
- * Revision history:
- * 0.1 beta Initial release
- * 0.2 Lowered initial mixer vol. Improved on stuttering wave playback. Added MIDI UART support.
- * 0.3 Fixed mixer routing bug, added APS, joystick support.
- * 0.4 Added rear-channel, SPDIF support.
- * 0.5 Source cleanup, SMP fixes, multiopen support, 64 bit arch fixes,
- * moved bh's to tasklets, moved to the new PCI driver initialization style.
- * 0.6 Make use of pci_alloc_consistent, improve compatibility layer for 2.2 kernels,
- * code reorganization and cleanup.
- * 0.7 Support for the Emu-APS. Bug fixes for voice cache setup, mmaped sound + poll().
- * Support for setting external TRAM size.
- * 0.8 Make use of the kernel ac97 interface. Support for a dsp patch manager.
- * 0.9 Re-enables rear speakers volume controls
- * 0.10 Initializes rear speaker volume.
- * Dynamic patch storage allocation.
- * New private ioctls to change control gpr values.
- * Enable volume control interrupts.
- * By default enable dsp routes to digital out.
- * 0.11 Fixed fx / 4 problem.
- * 0.12 Implemented mmaped for recording.
- * Fixed bug: not unreserving mmaped buffer pages.
- * IRQ handler cleanup.
- * 0.13 Fixed problem with dsp1
- * Simplified dsp patch writing (inside the driver)
- * Fixed several bugs found by the Stanford tools
- * 0.14 New control gpr to oss mixer mapping feature (Chris Purnell)
- * Added AC3 Passthrough Support (Juha Yrjola)
- * Added Support for 5.1 cards (digital out and the third analog out)
- * 0.15 Added Sequencer Support (Daniel Mack)
- * Support for multichannel pcm playback (Eduard Hasenleithner)
- * 0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand)
- * Small code format cleanup.
- * Deadlock bug fix for emu10k1_volxxx_irqhandler().
- * 0.17 Fix for mixer SOUND_MIXER_INFO ioctl.
- * Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master)
- * midi poll initial implementation.
- * Small mixer fixes/cleanups.
- * Improved support for 5.1 cards.
- * 0.18 Fix for possible leak in pci_alloc_consistent()
- * Cleaned up poll() functions (audio and midi). Don't start input.
- * Restrict DMA pages used to 512Mib range.
- * New AC97_BOOST mixer ioctl.
- * 0.19a Added Support for Audigy Cards
- * Real fix for kernel with highmem support (cast dma_handle to u32).
- * Fix recording buffering parameters calculation.
- * Use unsigned long for variables in bit ops.
- * 0.20a Fixed recording startup
- * Fixed timer rate setting (it's a 16-bit register)
- * 0.21 Converted code to use pci_name() instead of accessing slot_name
- * directly (Eugene Teo)
- *********************************************************************/
-
-/* These are only included once per module */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/dma-mapping.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "efxmgr.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "cardmo.h"
-#include "cardmi.h"
-#include "recmgr.h"
-#include "ecard.h"
-
-
-#ifdef EMU10K1_SEQUENCER
-#define MIDI_SYNTH_NAME "EMU10K1 MIDI"
-#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
-
-#include "../sound_config.h"
-#include "../midi_synth.h"
-
-/* this should be in dev_table.h */
-#define SNDCARD_EMU10K1 46
-#endif
-
-
-/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
-#define EMU10K1_DMA_MASK DMA_29BIT_MASK /* DMA buffer mask for pci_alloc_consist */
-
-#ifndef PCI_VENDOR_ID_CREATIVE
-#define PCI_VENDOR_ID_CREATIVE 0x1102
-#endif
-
-#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
-#endif
-#ifndef PCI_DEVICE_ID_CREATIVE_AUDIGY
-#define PCI_DEVICE_ID_CREATIVE_AUDIGY 0x0004
-#endif
-
-#define EMU_APS_SUBID 0x40011102
-
-enum {
- EMU10K1 = 0,
- AUDIGY,
-};
-
-static char *card_names[] __devinitdata = {
- "EMU10K1",
- "Audigy",
-};
-
-static struct pci_device_id emu10k1_pci_tbl[] = {
- {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
- {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_AUDIGY,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, AUDIGY},
- {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, emu10k1_pci_tbl);
-
-/* Global var instantiation */
-
-LIST_HEAD(emu10k1_devs);
-
-extern struct file_operations emu10k1_audio_fops;
-extern struct file_operations emu10k1_mixer_fops;
-extern struct file_operations emu10k1_midi_fops;
-
-#ifdef EMU10K1_SEQUENCER
-static struct midi_operations emu10k1_midi_operations;
-#endif
-
-extern irqreturn_t emu10k1_interrupt(int, void *);
-
-static int __devinit emu10k1_audio_init(struct emu10k1_card *card)
-{
- /* Assign default playback voice parameters */
- if (card->is_audigy)
- card->mchannel_fx = 0;
- else
- card->mchannel_fx = 8;
-
-
- if (card->is_audigy) {
- /* mono voice */
- card->waveout.send_dcba[SEND_MONO] = 0xffffffff;
- card->waveout.send_hgfe[SEND_MONO] = 0x0000ffff;
-
- /* stereo voice */
- /* left */
- card->waveout.send_dcba[SEND_LEFT] = 0x00ff00ff;
- card->waveout.send_hgfe[SEND_LEFT] = 0x00007f7f;
- /* right */
- card->waveout.send_dcba[SEND_RIGHT] = 0xff00ff00;
- card->waveout.send_hgfe[SEND_RIGHT] = 0x00007f7f;
-
- card->waveout.send_routing[ROUTE_PCM] = 0x03020100; // Regular pcm
- card->waveout.send_routing2[ROUTE_PCM] = 0x07060504;
-
- card->waveout.send_routing[ROUTE_PT] = 0x3f3f3d3c; // Passthrough
- card->waveout.send_routing2[ROUTE_PT] = 0x3f3f3f3f;
-
- card->waveout.send_routing[ROUTE_PCM1] = 0x03020100; // Spare
- card->waveout.send_routing2[ROUTE_PCM1] = 0x07060404;
-
- } else {
- /* mono voice */
- card->waveout.send_dcba[SEND_MONO] = 0x0000ffff;
-
- /* stereo voice */
- /* left */
- card->waveout.send_dcba[SEND_LEFT] = 0x000000ff;
- /* right */
- card->waveout.send_dcba[SEND_RIGHT] = 0x0000ff00;
-
- card->waveout.send_routing[ROUTE_PCM] = 0x3210; // pcm
- card->waveout.send_routing[ROUTE_PT] = 0x3210; // passthrough
- card->waveout.send_routing[ROUTE_PCM1] = 0x7654; // /dev/dsp1
- }
-
- /* Assign default recording parameters */
- /* FIXME */
- if (card->is_aps)
- card->wavein.recsrc = WAVERECORD_FX;
- else
- card->wavein.recsrc = WAVERECORD_AC97;
-
- card->wavein.fxwc = 0x0003;
- return 0;
-}
-
-static void emu10k1_audio_cleanup(struct emu10k1_card *card)
-{
-}
-
-static int __devinit emu10k1_register_devices(struct emu10k1_card *card)
-{
- card->audio_dev = register_sound_dsp(&emu10k1_audio_fops, -1);
- if (card->audio_dev < 0) {
- printk(KERN_ERR "emu10k1: cannot register first audio device!\n");
- goto err_dev;
- }
-
- card->audio_dev1 = register_sound_dsp(&emu10k1_audio_fops, -1);
- if (card->audio_dev1 < 0) {
- printk(KERN_ERR "emu10k1: cannot register second audio device!\n");
- goto err_dev1;
- }
-
- card->ac97->dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
- if (card->ac97->dev_mixer < 0) {
- printk(KERN_ERR "emu10k1: cannot register mixer device\n");
- goto err_mixer;
- }
-
- card->midi_dev = register_sound_midi(&emu10k1_midi_fops, -1);
- if (card->midi_dev < 0) {
- printk(KERN_ERR "emu10k1: cannot register midi device!\n");
- goto err_midi;
- }
-
-#ifdef EMU10K1_SEQUENCER
- card->seq_dev = sound_alloc_mididev();
- if (card->seq_dev == -1)
- printk(KERN_WARNING "emu10k1: unable to register sequencer device!");
- else {
- std_midi_synth.midi_dev = card->seq_dev;
- midi_devs[card->seq_dev] =
- (struct midi_operations *)
- kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
-
- if (midi_devs[card->seq_dev] == NULL) {
- printk(KERN_ERR "emu10k1: unable to allocate memory!");
- sound_unload_mididev(card->seq_dev);
- card->seq_dev = -1;
- /* return without error */
- } else {
- memcpy((char *)midi_devs[card->seq_dev],
- (char *)&emu10k1_midi_operations,
- sizeof(struct midi_operations));
- midi_devs[card->seq_dev]->devc = card;
- sequencer_init();
- card->seq_mididev = NULL;
- }
- }
-#endif
- return 0;
-
-err_midi:
- unregister_sound_mixer(card->ac97->dev_mixer);
-err_mixer:
- unregister_sound_dsp(card->audio_dev);
-err_dev1:
- unregister_sound_dsp(card->audio_dev);
-err_dev:
- return -ENODEV;
-}
-
-static void emu10k1_unregister_devices(struct emu10k1_card *card)
-{
-#ifdef EMU10K1_SEQUENCER
- if (card->seq_dev > -1) {
- kfree(midi_devs[card->seq_dev]);
- midi_devs[card->seq_dev] = NULL;
- sound_unload_mididev(card->seq_dev);
- card->seq_dev = -1;
- }
-#endif
-
- unregister_sound_midi(card->midi_dev);
- unregister_sound_mixer(card->ac97->dev_mixer);
- unregister_sound_dsp(card->audio_dev1);
- unregister_sound_dsp(card->audio_dev);
-}
-
-static int emu10k1_info_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct emu10k1_card *card = data;
- int len = 0;
-
- if (card == NULL)
- return -ENODEV;
-
- len += sprintf (page + len, "Driver Version : %s\n", DRIVER_VERSION);
- len += sprintf (page + len, "Card type : %s\n", card->is_aps ? "Aps" : (card->is_audigy ? "Audigy" : "Emu10k1"));
- len += sprintf (page + len, "Revision : %d\n", card->chiprev);
- len += sprintf (page + len, "Model : %#06x\n", card->model);
- len += sprintf (page + len, "IO : %#06lx-%#06lx\n", card->iobase, card->iobase + card->length - 1);
- len += sprintf (page + len, "IRQ : %d\n\n", card->irq);
-
- len += sprintf (page + len, "Registered /dev Entries:\n");
- len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev / 16);
- len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev1 / 16);
- len += sprintf (page + len, "/dev/mixer%d\n", card->ac97->dev_mixer / 16);
- len += sprintf (page + len, "/dev/midi%d\n", card->midi_dev / 16);
-
-#ifdef EMU10K1_SEQUENCER
- len += sprintf (page + len, "/dev/sequencer\n");
-#endif
-
- return len;
-}
-
-static int __devinit emu10k1_proc_init(struct emu10k1_card *card)
-{
- char s[48];
-
- if (!proc_mkdir ("driver/emu10k1", NULL)) {
- printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n");
- goto err_out;
- }
-
- sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
- if (!proc_mkdir (s, NULL)) {
- printk(KERN_ERR "emu10k1: unable to create proc directory %s\n", s);
- goto err_emu10k1_proc;
- }
-
- sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
- if (!create_proc_read_entry (s, 0, NULL, emu10k1_info_proc, card)) {
- printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
- goto err_dev_proc;
- }
-
- if (!card->is_aps) {
- sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));
- if (!create_proc_read_entry (s, 0, NULL, ac97_read_proc, card->ac97)) {
- printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
- goto err_proc_ac97;
- }
- }
-
- return 0;
-
-err_proc_ac97:
- sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
- remove_proc_entry(s, NULL);
-
-err_dev_proc:
- sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
- remove_proc_entry(s, NULL);
-
-err_emu10k1_proc:
- remove_proc_entry("driver/emu10k1", NULL);
-
-err_out:
- return -EIO;
-}
-
-static void emu10k1_proc_cleanup(struct emu10k1_card *card)
-{
- char s[48];
-
- if (!card->is_aps) {
- sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));
- remove_proc_entry(s, NULL);
- }
-
- sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));
- remove_proc_entry(s, NULL);
-
- sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));
- remove_proc_entry(s, NULL);
-
- remove_proc_entry("driver/emu10k1", NULL);
-}
-
-static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
-{
- struct ac97_codec *codec = ac97_alloc_codec();
-
- if(codec == NULL)
- {
- printk(KERN_ERR "emu10k1: cannot allocate mixer\n");
- return -EIO;
- }
- card->ac97 = codec;
- card->ac97->private_data = card;
-
- if (!card->is_aps) {
- card->ac97->id = 0;
- card->ac97->codec_read = emu10k1_ac97_read;
- card->ac97->codec_write = emu10k1_ac97_write;
-
- if (ac97_probe_codec (card->ac97) == 0) {
- printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");
- goto err_out;
- }
- /* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */
- if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){
- printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n");
- sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
- codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);
- }
-
- // Force 5bit:
- //card->ac97->bit_resolution=5;
-
- /* these will store the original values and never be modified */
- card->ac97_supported_mixers = card->ac97->supported_mixers;
- card->ac97_stereo_mixers = card->ac97->stereo_mixers;
- }
-
- return 0;
-
- err_out:
- ac97_release_codec(card->ac97);
- return -EIO;
-}
-
-static void emu10k1_mixer_cleanup(struct emu10k1_card *card)
-{
- ac97_release_codec(card->ac97);
-}
-
-static int __devinit emu10k1_midi_init(struct emu10k1_card *card)
-{
- int ret;
-
- card->mpuout = kzalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
- if (card->mpuout == NULL) {
- printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
- ret = -ENOMEM;
- goto err_out1;
- }
-
- card->mpuout->intr = 1;
- card->mpuout->status = FLAGS_AVAILABLE;
- card->mpuout->state = CARDMIDIOUT_STATE_DEFAULT;
-
- tasklet_init(&card->mpuout->tasklet, emu10k1_mpuout_bh, (unsigned long) card);
-
- spin_lock_init(&card->mpuout->lock);
-
- card->mpuin = kzalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);
- if (card->mpuin == NULL) {
- printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
- ret = -ENOMEM;
- goto err_out2;
- }
-
- card->mpuin->status = FLAGS_AVAILABLE;
-
- tasklet_init(&card->mpuin->tasklet, emu10k1_mpuin_bh, (unsigned long) card->mpuin);
-
- spin_lock_init(&card->mpuin->lock);
-
- /* Reset the MPU port */
- if (emu10k1_mpu_reset(card) < 0) {
- ERROR();
- ret = -EIO;
- goto err_out3;
- }
-
- return 0;
-
-err_out3:
- kfree(card->mpuin);
-err_out2:
- kfree(card->mpuout);
-err_out1:
- return ret;
-}
-
-static void emu10k1_midi_cleanup(struct emu10k1_card *card)
-{
- tasklet_kill(&card->mpuout->tasklet);
- kfree(card->mpuout);
-
- tasklet_kill(&card->mpuin->tasklet);
- kfree(card->mpuin);
-}
-
-static void __devinit voice_init(struct emu10k1_card *card)
-{
- int i;
-
- for (i = 0; i < NUM_G; i++)
- card->voicetable[i] = VOICE_USAGE_FREE;
-}
-
-static void __devinit timer_init(struct emu10k1_card *card)
-{
- INIT_LIST_HEAD(&card->timers);
- card->timer_delay = TIMER_STOPPED;
- spin_lock_init(&card->timer_lock);
-}
-
-static void __devinit addxmgr_init(struct emu10k1_card *card)
-{
- u32 count;
-
- for (count = 0; count < MAXPAGES; count++)
- card->emupagetable[count] = 0;
-
- /* Mark first page as used */
- /* This page is reserved by the driver */
- card->emupagetable[0] = 0x8001;
- card->emupagetable[1] = MAXPAGES - 1;
-}
-
-static void fx_cleanup(struct patch_manager *mgr)
-{
- int i;
- for(i = 0; i < mgr->current_pages; i++)
- free_page((unsigned long) mgr->patch[i]);
-}
-
-static int __devinit fx_init(struct emu10k1_card *card)
-{
- struct patch_manager *mgr = &card->mgr;
- struct dsp_patch *patch;
- struct dsp_rpatch *rpatch;
- s32 left, right;
- int i;
- u32 pc = 0;
- u32 patch_n=0;
- struct emu_efx_info_t emu_efx_info[2]=
- {{ 20, 10, 0x400, 0x100, 0x20 },
- { 24, 12, 0x600, 0x400, 0x60 },
- };
-
-
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
- mgr->ctrl_gpr[i][0] = -1;
- mgr->ctrl_gpr[i][1] = -1;
- }
-
-
- if (card->is_audigy)
- mgr->current_pages = (2 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
- else
- /* !! The number below must equal the number of patches, currently 11 !! */
- mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
-
- for (i = 0; i < mgr->current_pages; i++) {
- mgr->patch[i] = (void *)__get_free_page(GFP_KERNEL);
- if (mgr->patch[i] == NULL) {
- mgr->current_pages = i;
- fx_cleanup(mgr);
- return -ENOMEM;
- }
- memset(mgr->patch[i], 0, PAGE_SIZE);
- }
-
- if (card->is_audigy) {
- for (i = 0; i < 1024; i++)
- OP(0xf, 0x0c0, 0x0c0, 0x0cf, 0x0c0);
-
- for (i = 0; i < 512 ; i++)
- sblive_writeptr(card, A_GPR_BASE+i,0,0);
-
- pc=0;
-
- //Pcm input volume
- OP(0, 0x402, 0x0c0, 0x406, 0x000);
- OP(0, 0x403, 0x0c0, 0x407, 0x001);
-
- //CD-Digital input Volume
- OP(0, 0x404, 0x0c0, 0x40d, 0x42);
- OP(0, 0x405, 0x0c0, 0x40f, 0x43);
-
- // CD + PCM
- OP(6, 0x400, 0x0c0, 0x402, 0x404);
- OP(6, 0x401, 0x0c0, 0x403, 0x405);
-
- // Front Output + Master Volume
- OP(0, 0x68, 0x0c0, 0x408, 0x400);
- OP(0, 0x69, 0x0c0, 0x409, 0x401);
-
- // Add-in analog inputs for other speakers
- OP(6, 0x400, 0x40, 0x400, 0xc0);
- OP(6, 0x401, 0x41, 0x401, 0xc0);
-
- // Digital Front + Master Volume
- OP(0, 0x60, 0x0c0, 0x408, 0x400);
- OP(0, 0x61, 0x0c0, 0x409, 0x401);
-
- // Rear Output + Rear Volume
- OP(0, 0x06e, 0x0c0, 0x419, 0x400);
- OP(0, 0x06f, 0x0c0, 0x41a, 0x401);
-
- // Digital Rear Output + Rear Volume
- OP(0, 0x066, 0x0c0, 0x419, 0x400);
- OP(0, 0x067, 0x0c0, 0x41a, 0x401);
-
- // Audigy Drive, Headphone out
- OP(6, 0x64, 0x0c0, 0x0c0, 0x400);
- OP(6, 0x65, 0x0c0, 0x0c0, 0x401);
-
- // ac97 Recording
- OP(6, 0x76, 0x0c0, 0x0c0, 0x40);
- OP(6, 0x77, 0x0c0, 0x0c0, 0x41);
-
- // Center = sub = Left/2 + Right/2
- OP(0xe, 0x400, 0x401, 0xcd, 0x400);
-
- // center/sub Volume (master)
- OP(0, 0x06a, 0x0c0, 0x408, 0x400);
- OP(0, 0x06b, 0x0c0, 0x409, 0x400);
-
- // Digital center/sub Volume (master)
- OP(0, 0x062, 0x0c0, 0x408, 0x400);
- OP(0, 0x063, 0x0c0, 0x409, 0x400);
-
- ROUTING_PATCH_START(rpatch, "Routing");
- ROUTING_PATCH_END(rpatch);
-
- /* delimiter patch */
- patch = PATCH(mgr, patch_n);
- patch->code_size = 0;
-
-
- sblive_writeptr(card, 0x53, 0, 0);
- } else {
- for (i = 0; i < 512 ; i++)
- OP(6, 0x40, 0x40, 0x40, 0x40);
-
- for (i = 0; i < 256; i++)
- sblive_writeptr_tag(card, 0,
- FXGPREGBASE + i, 0,
- TANKMEMADDRREGBASE + i, 0,
- TAGLIST_END);
-
-
- pc = 0;
-
- //first free GPR = 0x11b
-
-
- /* FX volume correction and Volume control*/
- INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0);
- GET_OUTPUT_GPR(patch, 0x100, 0x0);
- GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff);
- GET_DYNAMIC_GPR(patch, 0x112);
-
- OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4
- OP(0, 0x100, 0x040, 0x112, 0x106); //*vol
- INPUT_PATCH_END(patch);
-
-
- INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0);
- GET_OUTPUT_GPR(patch, 0x101, 0x1);
- GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff);
- GET_DYNAMIC_GPR(patch, 0x112);
-
- OP(4, 0x112, 0x40, PCM_IN_R, 0x44);
- OP(0, 0x101, 0x040, 0x112, 0x107);
-
- INPUT_PATCH_END(patch);
-
-
- // CD-Digital In Volume control
- INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0);
- GET_OUTPUT_GPR(patch, 0x10c, 0x12);
- GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff);
-
- OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d);
- INPUT_PATCH_END(patch);
-
- INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0);
- GET_OUTPUT_GPR(patch, 0x10e, 0x13);
- GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff);
-
- OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f);
- INPUT_PATCH_END(patch);
-
- //Volume Correction for Multi-channel Inputs
- INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0);
- patch->input=patch->output=0x3F00;
-
- GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L);
- GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R);
- GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L);
- GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R);
- GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER);
- GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE);
-
- OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44);
- OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44);
- OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44);
- OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44);
- OP(4, 0x117, 0x40, MULTI_CENTER, 0x44);
- OP(4, 0x118, 0x40, MULTI_LFE, 0x44);
-
- INPUT_PATCH_END(patch);
-
-
- //Routing patch start
- ROUTING_PATCH_START(rpatch, "Routing");
- GET_INPUT_GPR(rpatch, 0x100, 0x0);
- GET_INPUT_GPR(rpatch, 0x101, 0x1);
- GET_INPUT_GPR(rpatch, 0x10c, 0x12);
- GET_INPUT_GPR(rpatch, 0x10e, 0x13);
- GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L);
- GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R);
- GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L);
- GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R);
- GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER);
- GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE);
-
- GET_DYNAMIC_GPR(rpatch, 0x102);
- GET_DYNAMIC_GPR(rpatch, 0x103);
-
- GET_OUTPUT_GPR(rpatch, 0x104, 0x8);
- GET_OUTPUT_GPR(rpatch, 0x105, 0x9);
- GET_OUTPUT_GPR(rpatch, 0x10a, 0x2);
- GET_OUTPUT_GPR(rpatch, 0x10b, 0x3);
-
-
- /* input buffer */
- OP(6, 0x102, AC97_IN_L, 0x40, 0x40);
- OP(6, 0x103, AC97_IN_R, 0x40, 0x40);
-
-
- /* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/
- OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113);
-
- CONNECT(MULTI_FRONT_L, AC97_FRONT_L);
- CONNECT(PCM_IN_L, AC97_FRONT_L);
- CONNECT(SPDIF_CD_L, AC97_FRONT_L);
-
- OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114);
-
- CONNECT(MULTI_FRONT_R, AC97_FRONT_R);
- CONNECT(PCM_IN_R, AC97_FRONT_R);
- CONNECT(SPDIF_CD_R, AC97_FRONT_R);
-
- /* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */
- OP(6, 0x104, PCM1_IN_L, 0x100, 0x115);
- OP(6, 0x104, 0x104, 0x10c, 0x102);
-
- CONNECT(MULTI_REAR_L, ANALOG_REAR_L);
- CONNECT(AC97_IN_L, ANALOG_REAR_L);
- CONNECT(PCM_IN_L, ANALOG_REAR_L);
- CONNECT(SPDIF_CD_L, ANALOG_REAR_L);
- CONNECT(PCM1_IN_L, ANALOG_REAR_L);
-
- OP(6, 0x105, PCM1_IN_R, 0x101, 0x116);
- OP(6, 0x105, 0x105, 0x10e, 0x103);
-
- CONNECT(MULTI_REAR_R, ANALOG_REAR_R);
- CONNECT(AC97_IN_R, ANALOG_REAR_R);
- CONNECT(PCM_IN_R, ANALOG_REAR_R);
- CONNECT(SPDIF_CD_R, ANALOG_REAR_R);
- CONNECT(PCM1_IN_R, ANALOG_REAR_R);
-
- /* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
- OP(6, 0x10b, 0x100, 0x102, 0x10c);
- OP(6, 0x10b, 0x10b, 0x113, 0x40);
-
- CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
- CONNECT(PCM_IN_L, DIGITAL_OUT_L);
- CONNECT(AC97_IN_L, DIGITAL_OUT_L);
- CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
-
- OP(6, 0x10a, 0x101, 0x103, 0x10e);
- OP(6, 0x10b, 0x10b, 0x114, 0x40);
-
- CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
- CONNECT(PCM_IN_R, DIGITAL_OUT_R);
- CONNECT(AC97_IN_R, DIGITAL_OUT_R);
- CONNECT(SPDIF_CD_R, DIGITAL_OUT_R);
-
- /* AC97 In --> ADC Recording Buffer */
- OP(6, ADC_REC_L, 0x102, 0x40, 0x40);
-
- CONNECT(AC97_IN_L, ADC_REC_L);
-
- OP(6, ADC_REC_R, 0x103, 0x40, 0x40);
-
- CONNECT(AC97_IN_R, ADC_REC_R);
-
-
- /* fx12:Analog-Center */
- OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40);
- CONNECT(MULTI_CENTER, ANALOG_CENTER);
-
- /* fx11:Analog-LFE */
- OP(6, ANALOG_LFE, 0x118, 0x40, 0x40);
- CONNECT(MULTI_LFE, ANALOG_LFE);
-
- /* fx12:Digital-Center */
- OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40);
- CONNECT(MULTI_CENTER, DIGITAL_CENTER);
-
- /* fx11:Analog-LFE */
- OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40);
- CONNECT(MULTI_LFE, DIGITAL_LFE);
-
- ROUTING_PATCH_END(rpatch);
-
-
- // Rear volume control
- OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0);
- GET_INPUT_GPR(patch, 0x104, 0x8);
- GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff);
-
- OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119);
- OUTPUT_PATCH_END(patch);
-
- OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0);
- GET_INPUT_GPR(patch, 0x105, 0x9);
- GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff);
-
- OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a);
- OUTPUT_PATCH_END(patch);
-
-
- //Master volume control on front-digital
- OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1);
- GET_INPUT_GPR(patch, 0x10a, 0x2);
- GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff);
-
- OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108);
- OUTPUT_PATCH_END(patch);
-
-
- OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1);
- GET_INPUT_GPR(patch, 0x10b, 0x3);
- GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff);
-
- OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109);
- OUTPUT_PATCH_END(patch);
-
-
- /* delimiter patch */
- patch = PATCH(mgr, patch_n);
- patch->code_size = 0;
-
-
- sblive_writeptr(card, DBG, 0, 0);
- }
-
- spin_lock_init(&mgr->lock);
-
- // Set up Volume controls, try to keep this the same for both Audigy and Live
-
- //Master volume
- mgr->ctrl_gpr[SOUND_MIXER_VOLUME][0] = 8;
- mgr->ctrl_gpr[SOUND_MIXER_VOLUME][1] = 9;
-
- left = card->ac97->mixer_state[SOUND_MIXER_VOLUME] & 0xff;
- right = (card->ac97->mixer_state[SOUND_MIXER_VOLUME] >> 8) & 0xff;
-
- emu10k1_set_volume_gpr(card, 8, left, 1 << card->ac97->bit_resolution);
- emu10k1_set_volume_gpr(card, 9, right, 1 << card->ac97->bit_resolution);
-
- //Rear volume
- mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][0] = 0x19;
- mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][1] = 0x1a;
-
- left = right = 67;
- card->ac97->mixer_state[SOUND_MIXER_OGAIN] = (right << 8) | left;
-
- card->ac97->supported_mixers |= SOUND_MASK_OGAIN;
- card->ac97->stereo_mixers |= SOUND_MASK_OGAIN;
-
- emu10k1_set_volume_gpr(card, 0x19, left, VOL_5BIT);
- emu10k1_set_volume_gpr(card, 0x1a, right, VOL_5BIT);
-
- //PCM Volume
- mgr->ctrl_gpr[SOUND_MIXER_PCM][0] = 6;
- mgr->ctrl_gpr[SOUND_MIXER_PCM][1] = 7;
-
- left = card->ac97->mixer_state[SOUND_MIXER_PCM] & 0xff;
- right = (card->ac97->mixer_state[SOUND_MIXER_PCM] >> 8) & 0xff;
-
- emu10k1_set_volume_gpr(card, 6, left, VOL_5BIT);
- emu10k1_set_volume_gpr(card, 7, right, VOL_5BIT);
-
- //CD-Digital Volume
- mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][0] = 0xd;
- mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][1] = 0xf;
-
- left = right = 67;
- card->ac97->mixer_state[SOUND_MIXER_DIGITAL1] = (right << 8) | left;
-
- card->ac97->supported_mixers |= SOUND_MASK_DIGITAL1;
- card->ac97->stereo_mixers |= SOUND_MASK_DIGITAL1;
-
- emu10k1_set_volume_gpr(card, 0xd, left, VOL_5BIT);
- emu10k1_set_volume_gpr(card, 0xf, right, VOL_5BIT);
-
-
- //hard wire the ac97's pcm, pcm volume is done above using dsp code.
- if (card->is_audigy)
- //for Audigy, we mute it and use the philips 6 channel DAC instead
- emu10k1_ac97_write(card->ac97, 0x18, 0x8000);
- else
- //For the Live we hardwire it to full volume
- emu10k1_ac97_write(card->ac97, 0x18, 0x0);
-
- //remove it from the ac97_codec's control
- card->ac97_supported_mixers &= ~SOUND_MASK_PCM;
- card->ac97_stereo_mixers &= ~SOUND_MASK_PCM;
-
- //set Igain to 0dB by default, maybe consider hardwiring it here.
- emu10k1_ac97_write(card->ac97, AC97_RECORD_GAIN, 0x0000);
- card->ac97->mixer_state[SOUND_MIXER_IGAIN] = 0x101;
-
- return 0;
-}
-
-static int __devinit hw_init(struct emu10k1_card *card)
-{
- int nCh;
- u32 pagecount; /* tmp */
- int ret;
-
- /* Disable audio and lock cache */
- emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
-
- /* Reset recording buffers */
- sblive_writeptr_tag(card, 0,
- MICBS, ADCBS_BUFSIZE_NONE,
- MICBA, 0,
- FXBS, ADCBS_BUFSIZE_NONE,
- FXBA, 0,
- ADCBS, ADCBS_BUFSIZE_NONE,
- ADCBA, 0,
- TAGLIST_END);
-
- /* Disable channel interrupt */
- emu10k1_writefn0(card, INTE, 0);
- sblive_writeptr_tag(card, 0,
- CLIEL, 0,
- CLIEH, 0,
- SOLEL, 0,
- SOLEH, 0,
- TAGLIST_END);
-
- if (card->is_audigy) {
- sblive_writeptr_tag(card,0,
- 0x5e,0xf00,
- 0x5f,0x3,
- TAGLIST_END);
- }
-
- /* Init envelope engine */
- for (nCh = 0; nCh < NUM_G; nCh++) {
- sblive_writeptr_tag(card, nCh,
- DCYSUSV, 0,
- IP, 0,
- VTFT, 0xffff,
- CVCF, 0xffff,
- PTRX, 0,
- //CPF, 0,
- CCR, 0,
-
- PSST, 0,
- DSL, 0x10,
- CCCA, 0,
- Z1, 0,
- Z2, 0,
- FXRT, 0xd01c0000,
-
- ATKHLDM, 0,
- DCYSUSM, 0,
- IFATN, 0xffff,
- PEFE, 0,
- FMMOD, 0,
- TREMFRQ, 24, /* 1 Hz */
- FM2FRQ2, 24, /* 1 Hz */
- TEMPENV, 0,
-
- /*** These are last so OFF prevents writing ***/
- LFOVAL2, 0,
- LFOVAL1, 0,
- ATKHLDV, 0,
- ENVVOL, 0,
- ENVVAL, 0,
- TAGLIST_END);
- sblive_writeptr(card, CPF, nCh, 0);
- /*
- Audigy FXRT initialization
- reversed eng'd, may not be accurate.
- */
- if (card->is_audigy) {
- sblive_writeptr_tag(card,nCh,
- 0x4c,0x0,
- 0x4d,0x0,
- 0x4e,0x0,
- 0x4f,0x0,
- A_FXRT1, 0x3f3f3f3f,
- A_FXRT2, 0x3f3f3f3f,
- A_SENDAMOUNTS, 0,
- TAGLIST_END);
- }
- }
-
-
- /*
- ** Init to 0x02109204 :
- ** Clock accuracy = 0 (1000ppm)
- ** Sample Rate = 2 (48kHz)
- ** Audio Channel = 1 (Left of 2)
- ** Source Number = 0 (Unspecified)
- ** Generation Status = 1 (Original for Cat Code 12)
- ** Cat Code = 12 (Digital Signal Mixer)
- ** Mode = 0 (Mode 0)
- ** Emphasis = 0 (None)
- ** CP = 1 (Copyright unasserted)
- ** AN = 0 (Digital audio)
- ** P = 0 (Consumer)
- */
-
- sblive_writeptr_tag(card, 0,
-
- /* SPDIF0 */
- SPCS0, (SPCS_CLKACCY_1000PPM | 0x002000000 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
- /* SPDIF1 */
- SPCS1, (SPCS_CLKACCY_1000PPM | 0x002000000 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
- /* SPDIF2 & SPDIF3 */
- SPCS2, (SPCS_CLKACCY_1000PPM | 0x002000000 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
-
- TAGLIST_END);
-
- if (card->is_audigy && (card->chiprev == 4)) {
- /* Hacks for Alice3 to work independent of haP16V driver */
- u32 tmp;
-
- //Setup SRCMulti_I2S SamplingRate
- tmp = sblive_readptr(card, A_SPDIF_SAMPLERATE, 0);
- tmp &= 0xfffff1ff;
- tmp |= (0x2<<9);
- sblive_writeptr(card, A_SPDIF_SAMPLERATE, 0, tmp);
-
- /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
- emu10k1_writefn0(card, 0x20, 0x600000);
- emu10k1_writefn0(card, 0x24, 0x14);
-
- /* Setup SRCMulti Input Audio Enable */
- emu10k1_writefn0(card, 0x20, 0x6E0000);
- emu10k1_writefn0(card, 0x24, 0xFF00FF00);
- }
-
- ret = fx_init(card); /* initialize effects engine */
- if (ret < 0)
- return ret;
-
- card->tankmem.size = 0;
-
- card->virtualpagetable.size = MAXPAGES * sizeof(u32);
-
- card->virtualpagetable.addr = pci_alloc_consistent(card->pci_dev, card->virtualpagetable.size, &card->virtualpagetable.dma_handle);
- if (card->virtualpagetable.addr == NULL) {
- ERROR();
- ret = -ENOMEM;
- goto err0;
- }
-
- card->silentpage.size = EMUPAGESIZE;
-
- card->silentpage.addr = pci_alloc_consistent(card->pci_dev, card->silentpage.size, &card->silentpage.dma_handle);
- if (card->silentpage.addr == NULL) {
- ERROR();
- ret = -ENOMEM;
- goto err1;
- }
-
- for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
- ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pagecount);
-
- /* Init page table & tank memory base register */
- sblive_writeptr_tag(card, 0,
- PTB, (u32) card->virtualpagetable.dma_handle,
- TCB, 0,
- TCBS, 0,
- TAGLIST_END);
-
- for (nCh = 0; nCh < NUM_G; nCh++) {
- sblive_writeptr_tag(card, nCh,
- MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
- MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
- TAGLIST_END);
- }
-
- /* Hokay, now enable the AUD bit */
- /* Enable Audio = 1 */
- /* Mute Disable Audio = 0 */
- /* Lock Tank Memory = 1 */
- /* Lock Sound Memory = 0 */
- /* Auto Mute = 1 */
- if (card->is_audigy) {
- if (card->chiprev == 4)
- emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_AC3ENABLE_CDSPDIF | HCFG_AC3ENABLE_GPSPDIF | HCFG_AUTOMUTE | HCFG_JOYENABLE);
- else
- emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_AUTOMUTE | HCFG_JOYENABLE);
- } else {
- if (card->model == 0x20 || card->model == 0xc400 ||
- (card->model == 0x21 && card->chiprev < 6))
- emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
- else
- emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
- }
- /* Enable Vol_Ctrl irqs */
- emu10k1_irq_enable(card, INTE_VOLINCRENABLE | INTE_VOLDECRENABLE | INTE_MUTEENABLE | INTE_FXDSPENABLE);
-
- if (card->is_audigy && (card->chiprev == 4)) {
- /* Unmute Analog now. Set GPO6 to 1 for Apollo.
- * This has to be done after init ALice3 I2SOut beyond 48KHz.
- * So, sequence is important. */
- u32 tmp = emu10k1_readfn0(card, A_IOCFG);
- tmp |= 0x0040;
- emu10k1_writefn0(card, A_IOCFG, tmp);
- }
-
- /* FIXME: TOSLink detection */
- card->has_toslink = 0;
-
- /* Initialize digital passthrough variables */
- card->pt.pos_gpr = card->pt.intr_gpr = card->pt.enable_gpr = -1;
- card->pt.selected = 0;
- card->pt.state = PT_STATE_INACTIVE;
- card->pt.spcs_to_use = 0x01;
- card->pt.patch_name = "AC3pass";
- card->pt.intr_gpr_name = "count";
- card->pt.enable_gpr_name = "enable";
- card->pt.pos_gpr_name = "ptr";
- spin_lock_init(&card->pt.lock);
- init_waitqueue_head(&card->pt.wait);
-
-/* tmp = sblive_readfn0(card, HCFG);
- if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
- sblive_writefn0(card, HCFG, tmp | 0x800);
-
- udelay(512);
-
- if (tmp != (sblive_readfn0(card, HCFG) & ~0x800)) {
- card->has_toslink = 1;
- sblive_writefn0(card, HCFG, tmp);
- }
- }
-*/
- return 0;
-
- err1:
- pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
- err0:
- fx_cleanup(&card->mgr);
-
- return ret;
-}
-
-static int __devinit emu10k1_init(struct emu10k1_card *card)
-{
- /* Init Card */
- if (hw_init(card) < 0)
- return -1;
-
- voice_init(card);
- timer_init(card);
- addxmgr_init(card);
-
- DPD(2, " hw control register -> %#x\n", emu10k1_readfn0(card, HCFG));
-
- return 0;
-}
-
-static void emu10k1_cleanup(struct emu10k1_card *card)
-{
- int ch;
-
- emu10k1_writefn0(card, INTE, 0);
-
- /** Shutdown the chip **/
- for (ch = 0; ch < NUM_G; ch++)
- sblive_writeptr(card, DCYSUSV, ch, 0);
-
- for (ch = 0; ch < NUM_G; ch++) {
- sblive_writeptr_tag(card, ch,
- VTFT, 0,
- CVCF, 0,
- PTRX, 0,
- //CPF, 0,
- TAGLIST_END);
- sblive_writeptr(card, CPF, ch, 0);
- }
-
- /* Disable audio and lock cache */
- emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
-
- sblive_writeptr_tag(card, 0,
- PTB, 0,
-
- /* Reset recording buffers */
- MICBS, ADCBS_BUFSIZE_NONE,
- MICBA, 0,
- FXBS, ADCBS_BUFSIZE_NONE,
- FXBA, 0,
- FXWC, 0,
- ADCBS, ADCBS_BUFSIZE_NONE,
- ADCBA, 0,
- TCBS, 0,
- TCB, 0,
- DBG, 0x8000,
-
- /* Disable channel interrupt */
- CLIEL, 0,
- CLIEH, 0,
- SOLEL, 0,
- SOLEH, 0,
- TAGLIST_END);
-
- if (card->is_audigy)
- sblive_writeptr(card, 0, A_DBG, A_DBG_SINGLE_STEP);
-
- pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
- pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
-
- if(card->tankmem.size != 0)
- pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
-
- /* release patch storage memory */
- fx_cleanup(&card->mgr);
-}
-
-/* Driver initialization routine */
-static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
- struct emu10k1_card *card;
- u32 subsysvid;
- int ret;
-
- if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) {
- printk(KERN_ERR "emu10k1: architecture does not support 29bit PCI busmaster DMA\n");
- return -ENODEV;
- }
-
- if (pci_enable_device(pci_dev))
- return -EIO;
-
- pci_set_master(pci_dev);
-
- if ((card = kzalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "emu10k1: out of memory\n");
- return -ENOMEM;
- }
-
- card->iobase = pci_resource_start(pci_dev, 0);
- card->length = pci_resource_len(pci_dev, 0);
-
- if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
- printk(KERN_ERR "emu10k1: IO space in use\n");
- ret = -EBUSY;
- goto err_region;
- }
-
- pci_set_drvdata(pci_dev, card);
-
- card->irq = pci_dev->irq;
- card->pci_dev = pci_dev;
-
- /* Reserve IRQ Line */
- if (request_irq(card->irq, emu10k1_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], card)) {
- printk(KERN_ERR "emu10k1: IRQ in use\n");
- ret = -EBUSY;
- goto err_irq;
- }
-
- card->chiprev = pci_dev->revision;
- pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
-
- printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
- card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
- card->iobase + card->length - 1, card->irq);
-
- if (pci_id->device == PCI_DEVICE_ID_CREATIVE_AUDIGY)
- card->is_audigy = 1;
-
- pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
- card->is_aps = (subsysvid == EMU_APS_SUBID);
-
- spin_lock_init(&card->lock);
- mutex_init(&card->open_sem);
- card->open_mode = 0;
- init_waitqueue_head(&card->open_wait);
-
- ret = emu10k1_audio_init(card);
- if (ret < 0) {
- printk(KERN_ERR "emu10k1: cannot initialize audio devices\n");
- goto err_audio;
- }
-
- ret = emu10k1_mixer_init(card);
- if (ret < 0) {
- printk(KERN_ERR "emu10k1: cannot initialize AC97 codec\n");
- goto err_mixer;
- }
-
- ret = emu10k1_midi_init(card);
- if (ret < 0) {
- printk(KERN_ERR "emu10k1: cannot register midi device\n");
- goto err_midi;
- }
-
- ret = emu10k1_init(card);
- if (ret < 0) {
- printk(KERN_ERR "emu10k1: cannot initialize device\n");
- goto err_emu10k1_init;
- }
-
- if (card->is_aps)
- emu10k1_ecard_init(card);
-
- ret = emu10k1_register_devices(card);
- if (ret < 0)
- goto err_register;
-
- /* proc entries must be created after registering devices, as
- * emu10k1_info_proc prints card->audio_dev &co. */
- ret = emu10k1_proc_init(card);
- if (ret < 0) {
- printk(KERN_ERR "emu10k1: cannot initialize proc directory\n");
- goto err_proc;
- }
-
- list_add(&card->list, &emu10k1_devs);
-
- return 0;
-
-err_proc:
- emu10k1_unregister_devices(card);
-
-err_register:
- emu10k1_cleanup(card);
-
-err_emu10k1_init:
- emu10k1_midi_cleanup(card);
-
-err_midi:
- emu10k1_mixer_cleanup(card);
-
-err_mixer:
- emu10k1_audio_cleanup(card);
-
-err_audio:
- free_irq(card->irq, card);
-
-err_irq:
- release_region(card->iobase, card->length);
- pci_set_drvdata(pci_dev, NULL);
-
-err_region:
- kfree(card);
-
- return ret;
-}
-
-static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
-{
- struct emu10k1_card *card = pci_get_drvdata(pci_dev);
-
- list_del(&card->list);
-
- emu10k1_unregister_devices(card);
- emu10k1_cleanup(card);
- emu10k1_midi_cleanup(card);
- emu10k1_mixer_cleanup(card);
- emu10k1_proc_cleanup(card);
- emu10k1_audio_cleanup(card);
- free_irq(card->irq, card);
- release_region(card->iobase, card->length);
- kfree(card);
- pci_set_drvdata(pci_dev, NULL);
-}
-
-MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)");
-MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd.");
-MODULE_LICENSE("GPL");
-
-static struct pci_driver emu10k1_pci_driver = {
- .name = "emu10k1",
- .id_table = emu10k1_pci_tbl,
- .probe = emu10k1_probe,
- .remove = __devexit_p(emu10k1_remove),
-};
-
-static int __init emu10k1_init_module(void)
-{
- printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
- return pci_register_driver(&emu10k1_pci_driver);
-}
-
-static void __exit emu10k1_cleanup_module(void)
-{
- pci_unregister_driver(&emu10k1_pci_driver);
-
- return;
-}
-
-module_init(emu10k1_init_module);
-module_exit(emu10k1_cleanup_module);
-
-#ifdef EMU10K1_SEQUENCER
-
-/* in midi.c */
-extern int emu10k1_seq_midi_open(int dev, int mode,
- void (*input)(int dev, unsigned char midi_byte),
- void (*output)(int dev));
-extern void emu10k1_seq_midi_close(int dev);
-extern int emu10k1_seq_midi_out(int dev, unsigned char midi_byte);
-extern int emu10k1_seq_midi_start_read(int dev);
-extern int emu10k1_seq_midi_end_read(int dev);
-extern void emu10k1_seq_midi_kick(int dev);
-extern int emu10k1_seq_midi_buffer_status(int dev);
-
-static struct midi_operations emu10k1_midi_operations =
-{
- THIS_MODULE,
- {"EMU10K1 MIDI", 0, 0, SNDCARD_EMU10K1},
- &std_midi_synth,
- {0},
- emu10k1_seq_midi_open,
- emu10k1_seq_midi_close,
- NULL,
- emu10k1_seq_midi_out,
- emu10k1_seq_midi_start_read,
- emu10k1_seq_midi_end_read,
- emu10k1_seq_midi_kick,
- NULL,
- emu10k1_seq_midi_buffer_status,
- NULL
-};
-
-#endif
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
deleted file mode 100644
index df1e990449a0..000000000000
--- a/sound/oss/emu10k1/midi.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- **********************************************************************
- * midi.c - /dev/midi interface for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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/poll.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-
-#include "hwaccess.h"
-#include "cardmo.h"
-#include "cardmi.h"
-#include "midi.h"
-
-#ifdef EMU10K1_SEQUENCER
-#include "../sound_config.h"
-#endif
-
-static DEFINE_SPINLOCK(midi_spinlock);
-
-static void init_midi_hdr(struct midi_hdr *midihdr)
-{
- midihdr->bufferlength = MIDIIN_BUFLEN;
- midihdr->bytesrecorded = 0;
- midihdr->flags = 0;
-}
-
-static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hdr **midihdrptr)
-{
- struct midi_hdr *midihdr;
-
- if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
- ERROR();
- return -EINVAL;
- }
-
- init_midi_hdr(midihdr);
-
- midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL);
- if (!midihdr->data) {
- ERROR();
- kfree(midihdr);
- return -1;
- }
-
- if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) < 0) {
- ERROR();
- kfree(midihdr->data);
- kfree(midihdr);
- return -1;
- }
-
- *midihdrptr = midihdr;
- list_add_tail(&midihdr->list, &midi_dev->mid_hdrs);
-
- return 0;
-}
-
-static int emu10k1_midi_open(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- struct emu10k1_card *card = NULL;
- struct emu10k1_mididevice *midi_dev;
- struct list_head *entry;
-
- DPF(2, "emu10k1_midi_open()\n");
-
- /* Check for correct device to open */
- list_for_each(entry, &emu10k1_devs) {
- card = list_entry(entry, struct emu10k1_card, list);
-
- if (card->midi_dev == minor)
- goto match;
- }
-
- return -ENODEV;
-
-match:
-#ifdef EMU10K1_SEQUENCER
- if (card->seq_mididev) /* card is opened by sequencer */
- return -EBUSY;
-#endif
-
- /* Wait for device to become free */
- mutex_lock(&card->open_sem);
- while (card->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&card->open_sem);
- return -EBUSY;
- }
-
- mutex_unlock(&card->open_sem);
- interruptible_sleep_on(&card->open_wait);
-
- if (signal_pending(current)) {
- return -ERESTARTSYS;
- }
-
- mutex_lock(&card->open_sem);
- }
-
- if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
- return -EINVAL;
-
- midi_dev->card = card;
- midi_dev->mistate = MIDIIN_STATE_STOPPED;
- init_waitqueue_head(&midi_dev->oWait);
- init_waitqueue_head(&midi_dev->iWait);
- midi_dev->ird = 0;
- midi_dev->iwr = 0;
- midi_dev->icnt = 0;
- INIT_LIST_HEAD(&midi_dev->mid_hdrs);
-
- if (file->f_mode & FMODE_READ) {
- struct midi_openinfo dsCardMidiOpenInfo;
- struct midi_hdr *midihdr1;
- struct midi_hdr *midihdr2;
-
- dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
- if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo) < 0) {
- ERROR();
- kfree(midi_dev);
- return -ENODEV;
- }
-
- /* Add two buffers to receive sysex buffer */
- if (midiin_add_buffer(midi_dev, &midihdr1) < 0) {
- kfree(midi_dev);
- return -ENODEV;
- }
-
- if (midiin_add_buffer(midi_dev, &midihdr2) < 0) {
- list_del(&midihdr1->list);
- kfree(midihdr1->data);
- kfree(midihdr1);
- kfree(midi_dev);
- return -ENODEV;
- }
- }
-
- if (file->f_mode & FMODE_WRITE) {
- struct midi_openinfo dsCardMidiOpenInfo;
-
- dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
- if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
- ERROR();
- kfree(midi_dev);
- return -ENODEV;
- }
- }
-
- file->private_data = (void *) midi_dev;
-
- card->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
-
- mutex_unlock(&card->open_sem);
-
- return nonseekable_open(inode, file);
-}
-
-static int emu10k1_midi_release(struct inode *inode, struct file *file)
-{
- struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
- struct emu10k1_card *card;
-
- lock_kernel();
-
- card = midi_dev->card;
- DPF(2, "emu10k1_midi_release()\n");
-
- if (file->f_mode & FMODE_WRITE) {
- if (!(file->f_flags & O_NONBLOCK)) {
-
- while (!signal_pending(current) && (card->mpuout->firstmidiq != NULL)) {
- DPF(4, "Cannot close - buffers not empty\n");
-
- interruptible_sleep_on(&midi_dev->oWait);
-
- }
- }
-
- emu10k1_mpuout_close(card);
- }
-
- if (file->f_mode & FMODE_READ) {
- struct midi_hdr *midihdr;
-
- if (midi_dev->mistate == MIDIIN_STATE_STARTED) {
- emu10k1_mpuin_stop(card);
- midi_dev->mistate = MIDIIN_STATE_STOPPED;
- }
-
- emu10k1_mpuin_reset(card);
- emu10k1_mpuin_close(card);
-
- while (!list_empty(&midi_dev->mid_hdrs)) {
- midihdr = list_entry(midi_dev->mid_hdrs.next, struct midi_hdr, list);
-
- list_del(midi_dev->mid_hdrs.next);
- kfree(midihdr->data);
- kfree(midihdr);
- }
- }
-
- kfree(midi_dev);
-
- mutex_lock(&card->open_sem);
- card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE));
- mutex_unlock(&card->open_sem);
- wake_up_interruptible(&card->open_wait);
-
- unlock_kernel();
-
- return 0;
-}
-
-static ssize_t emu10k1_midi_read(struct file *file, char __user *buffer, size_t count, loff_t * pos)
-{
- struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
- ssize_t ret = 0;
- u16 cnt;
- unsigned long flags;
-
- DPD(4, "emu10k1_midi_read(), count %#x\n", (u32) count);
-
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
-
- if (midi_dev->mistate == MIDIIN_STATE_STOPPED) {
- if (emu10k1_mpuin_start(midi_dev->card) < 0) {
- ERROR();
- return -EINVAL;
- }
-
- midi_dev->mistate = MIDIIN_STATE_STARTED;
- }
-
- while (count > 0) {
- cnt = MIDIIN_BUFLEN - midi_dev->ird;
-
- spin_lock_irqsave(&midi_spinlock, flags);
-
- if (midi_dev->icnt < cnt)
- cnt = midi_dev->icnt;
-
- spin_unlock_irqrestore(&midi_spinlock, flags);
-
- if (cnt > count)
- cnt = count;
-
- if (cnt <= 0) {
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- DPF(2, " Go to sleep...\n");
-
- interruptible_sleep_on(&midi_dev->iWait);
-
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
-
- continue;
- }
-
- if (copy_to_user(buffer, midi_dev->iBuf + midi_dev->ird, cnt)) {
- ERROR();
- return ret ? ret : -EFAULT;
- }
-
- midi_dev->ird += cnt;
- midi_dev->ird %= MIDIIN_BUFLEN;
-
- spin_lock_irqsave(&midi_spinlock, flags);
-
- midi_dev->icnt -= cnt;
-
- spin_unlock_irqrestore(&midi_spinlock, flags);
-
- count -= cnt;
- buffer += cnt;
- ret += cnt;
-
- if (midi_dev->icnt == 0)
- break;
- }
-
- return ret;
-}
-
-static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t * pos)
-{
- struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
- struct midi_hdr *midihdr;
- unsigned long flags;
-
- DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count);
-
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
-
- if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
- return -EINVAL;
-
- midihdr->bufferlength = count;
- midihdr->bytesrecorded = 0;
- midihdr->flags = 0;
-
- midihdr->data = kmalloc(count, GFP_KERNEL);
- if (!midihdr->data) {
- ERROR();
- kfree(midihdr);
- return -EINVAL;
- }
-
- if (copy_from_user(midihdr->data, buffer, count)) {
- kfree(midihdr->data);
- kfree(midihdr);
- return -EFAULT;
- }
-
- spin_lock_irqsave(&midi_spinlock, flags);
-
- if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) < 0) {
- ERROR();
- kfree(midihdr->data);
- kfree(midihdr);
- spin_unlock_irqrestore(&midi_spinlock, flags);
- return -EINVAL;
- }
-
- spin_unlock_irqrestore(&midi_spinlock, flags);
-
- return count;
-}
-
-static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
- unsigned long flags;
- unsigned int mask = 0;
-
- DPF(4, "emu10k1_midi_poll() called\n");
-
- if (file->f_mode & FMODE_WRITE)
- poll_wait(file, &midi_dev->oWait, wait);
-
- if (file->f_mode & FMODE_READ)
- poll_wait(file, &midi_dev->iWait, wait);
-
- spin_lock_irqsave(&midi_spinlock, flags);
-
- if (file->f_mode & FMODE_WRITE)
- mask |= POLLOUT | POLLWRNORM;
-
- if (file->f_mode & FMODE_READ) {
- if (midi_dev->mistate == MIDIIN_STATE_STARTED)
- if (midi_dev->icnt > 0)
- mask |= POLLIN | POLLRDNORM;
- }
-
- spin_unlock_irqrestore(&midi_spinlock, flags);
-
- return mask;
-}
-
-int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg)
-{
- struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) refdata;
- struct midi_hdr *midihdr = NULL;
- unsigned long flags;
- int i;
-
- DPF(4, "emu10k1_midi_callback()\n");
-
- spin_lock_irqsave(&midi_spinlock, flags);
-
- switch (msg) {
- case ICARDMIDI_OUTLONGDATA:
- midihdr = (struct midi_hdr *) pmsg[2];
-
- kfree(midihdr->data);
- kfree(midihdr);
- wake_up_interruptible(&midi_dev->oWait);
-
- break;
-
- case ICARDMIDI_INLONGDATA:
- midihdr = (struct midi_hdr *) pmsg[2];
-
- for (i = 0; i < midihdr->bytesrecorded; i++) {
- midi_dev->iBuf[midi_dev->iwr++] = midihdr->data[i];
- midi_dev->iwr %= MIDIIN_BUFLEN;
- }
-
- midi_dev->icnt += midihdr->bytesrecorded;
-
- if (midi_dev->mistate == MIDIIN_STATE_STARTED) {
- init_midi_hdr(midihdr);
- emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr);
- wake_up_interruptible(&midi_dev->iWait);
- }
- break;
-
- case ICARDMIDI_INDATA:
- {
- u8 *pBuf = (u8 *) & pmsg[1];
- u16 bytesvalid = pmsg[2];
-
- for (i = 0; i < bytesvalid; i++) {
- midi_dev->iBuf[midi_dev->iwr++] = pBuf[i];
- midi_dev->iwr %= MIDIIN_BUFLEN;
- }
-
- midi_dev->icnt += bytesvalid;
- }
-
- wake_up_interruptible(&midi_dev->iWait);
- break;
-
- default: /* Unknown message */
- spin_unlock_irqrestore(&midi_spinlock, flags);
- return -1;
- }
-
- spin_unlock_irqrestore(&midi_spinlock, flags);
-
- return 0;
-}
-
-/* MIDI file operations */
-const struct file_operations emu10k1_midi_fops = {
- .owner = THIS_MODULE,
- .read = emu10k1_midi_read,
- .write = emu10k1_midi_write,
- .poll = emu10k1_midi_poll,
- .open = emu10k1_midi_open,
- .release = emu10k1_midi_release,
-};
-
-
-#ifdef EMU10K1_SEQUENCER
-
-/* functions used for sequencer access */
-
-int emu10k1_seq_midi_open(int dev, int mode,
- void (*input) (int dev, unsigned char data),
- void (*output) (int dev))
-{
- struct emu10k1_card *card;
- struct midi_openinfo dsCardMidiOpenInfo;
- struct emu10k1_mididevice *midi_dev;
-
- if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
- return -EINVAL;
-
- card = midi_devs[dev]->devc;
-
- if (card->open_mode) /* card is opened native */
- return -EBUSY;
-
- DPF(2, "emu10k1_seq_midi_open()\n");
-
- if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
- return -EINVAL;
-
- midi_dev->card = card;
- midi_dev->mistate = MIDIIN_STATE_STOPPED;
- init_waitqueue_head(&midi_dev->oWait);
- init_waitqueue_head(&midi_dev->iWait);
- midi_dev->ird = 0;
- midi_dev->iwr = 0;
- midi_dev->icnt = 0;
- INIT_LIST_HEAD(&midi_dev->mid_hdrs);
-
- dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
-
- if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
- ERROR();
- return -ENODEV;
- }
-
- card->seq_mididev = midi_dev;
-
- return 0;
-}
-
-void emu10k1_seq_midi_close(int dev)
-{
- struct emu10k1_card *card;
-
- DPF(2, "emu10k1_seq_midi_close()\n");
- if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
- return;
-
- card = midi_devs[dev]->devc;
- emu10k1_mpuout_close(card);
-
- kfree(card->seq_mididev);
- card->seq_mididev = NULL;
-}
-
-int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
-{
- struct emu10k1_card *card;
- struct midi_hdr *midihdr;
- unsigned long flags;
-
- if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
- return -EINVAL;
-
- card = midi_devs[dev]->devc;
-
- if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
- return -EINVAL;
-
- midihdr->bufferlength = 1;
- midihdr->bytesrecorded = 0;
- midihdr->flags = 0;
-
- midihdr->data = kmalloc(1, GFP_KERNEL);
- if (!midihdr->data) {
- ERROR();
- kfree(midihdr);
- return -EINVAL;
- }
-
- *(midihdr->data) = midi_byte;
-
- spin_lock_irqsave(&midi_spinlock, flags);
-
- if (emu10k1_mpuout_add_buffer(card, midihdr) < 0) {
- ERROR();
- kfree(midihdr->data);
- kfree(midihdr);
- spin_unlock_irqrestore(&midi_spinlock, flags);
- return -EINVAL;
- }
-
- spin_unlock_irqrestore(&midi_spinlock, flags);
-
- return 1;
-}
-
-int emu10k1_seq_midi_start_read(int dev)
-{
- return 0;
-}
-
-int emu10k1_seq_midi_end_read(int dev)
-{
- return 0;
-}
-
-void emu10k1_seq_midi_kick(int dev)
-{
-}
-
-int emu10k1_seq_midi_buffer_status(int dev)
-{
- int count;
- struct midi_queue *queue;
- struct emu10k1_card *card;
-
- if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL)
- return -EINVAL;
-
- count = 0;
-
- card = midi_devs[dev]->devc;
- queue = card->mpuout->firstmidiq;
-
- while (queue != NULL) {
- count++;
- if (queue == card->mpuout->lastmidiq)
- break;
-
- queue = queue->next;
- }
-
- return count;
-}
-
-#endif
-
diff --git a/sound/oss/emu10k1/midi.h b/sound/oss/emu10k1/midi.h
deleted file mode 100644
index 2459ec929e8d..000000000000
--- a/sound/oss/emu10k1/midi.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- **********************************************************************
- * midi.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _MIDI_H
-#define _MIDI_H
-
-#define FMODE_MIDI_SHIFT 3
-#define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT)
-#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
-
-#define MIDIIN_STATE_STARTED 0x00000001
-#define MIDIIN_STATE_STOPPED 0x00000002
-
-#define MIDIIN_BUFLEN 1024
-
-struct emu10k1_mididevice
-{
- struct emu10k1_card *card;
- u32 mistate;
- wait_queue_head_t oWait;
- wait_queue_head_t iWait;
- s8 iBuf[MIDIIN_BUFLEN];
- u16 ird, iwr, icnt;
- struct list_head mid_hdrs;
-};
-
-/* uncomment next line to use midi port on Audigy drive */
-//#define USE_AUDIGY_DRIVE_MIDI
-
-#ifdef USE_AUDIGY_DRIVE_MIDI
-#define A_MUDATA A_MUDATA2
-#define A_MUCMD A_MUCMD2
-#define A_MUSTAT A_MUCMD2
-#define A_IPR_MIDITRANSBUFEMPTY A_IPR_MIDITRANSBUFEMPTY2
-#define A_IPR_MIDIRECVBUFEMPTY A_IPR_MIDIRECVBUFEMPTY2
-#define A_INTE_MIDITXENABLE A_INTE_MIDITXENABLE2
-#define A_INTE_MIDIRXENABLE A_INTE_MIDIRXENABLE2
-#else
-#define A_MUDATA A_MUDATA1
-#define A_MUCMD A_MUCMD1
-#define A_MUSTAT A_MUCMD1
-#define A_IPR_MIDITRANSBUFEMPTY A_IPR_MIDITRANSBUFEMPTY1
-#define A_IPR_MIDIRECVBUFEMPTY A_IPR_MIDIRECVBUFEMPTY1
-#define A_INTE_MIDITXENABLE A_INTE_MIDITXENABLE1
-#define A_INTE_MIDIRXENABLE A_INTE_MIDIRXENABLE1
-#endif
-
-
-#endif /* _MIDI_H */
-
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
deleted file mode 100644
index bc3805fb0701..000000000000
--- a/sound/oss/emu10k1/mixer.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- **********************************************************************
- * mixer.c - /dev/mixer interface for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up stuff
- *
- **********************************************************************
- *
- * 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 <asm/uaccess.h>
-#include <linux/fs.h>
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "recmgr.h"
-
-
-static const u32 bass_table[41][5] = {
- { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
- { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
- { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
- { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
- { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
- { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
- { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
- { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
- { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
- { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
- { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
- { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
- { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
- { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
- { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
- { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
- { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
- { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
- { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
- { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
- { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
- { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
- { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
- { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
- { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
- { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
- { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
- { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
- { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
- { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
- { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
- { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
- { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
- { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
- { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
- { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
- { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
- { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
- { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
- { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
- { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
-};
-
-static const u32 treble_table[41][5] = {
- { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
- { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
- { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
- { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
- { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
- { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
- { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
- { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
- { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
- { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
- { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
- { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
- { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
- { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
- { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
- { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
- { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
- { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
- { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
- { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
- { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
- { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
- { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
- { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
- { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
- { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
- { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
- { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
- { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
- { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
- { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
- { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
- { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
- { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
- { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
- { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
- { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
- { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
- { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
- { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
- { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
-};
-
-
-static void set_bass(struct emu10k1_card *card, int l, int r)
-{
- int i;
-
- l = (l * 40 + 50) / 100;
- r = (r * 40 + 50) / 100;
-
- for (i = 0; i < 5; i++)
- sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]);
-}
-
-static void set_treble(struct emu10k1_card *card, int l, int r)
-{
- int i;
-
- l = (l * 40 + 50) / 100;
- r = (r * 40 + 50) / 100;
-
- for (i = 0; i < 5; i++)
- sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]);
-}
-
-const char volume_params[SOUND_MIXER_NRDEVICES]= {
-/* Used by the ac97 driver */
- [SOUND_MIXER_VOLUME] = VOL_6BIT,
- [SOUND_MIXER_BASS] = VOL_4BIT,
- [SOUND_MIXER_TREBLE] = VOL_4BIT,
- [SOUND_MIXER_PCM] = VOL_5BIT,
- [SOUND_MIXER_SPEAKER] = VOL_4BIT,
- [SOUND_MIXER_LINE] = VOL_5BIT,
- [SOUND_MIXER_MIC] = VOL_5BIT,
- [SOUND_MIXER_CD] = VOL_5BIT,
- [SOUND_MIXER_ALTPCM] = VOL_6BIT,
- [SOUND_MIXER_IGAIN] = VOL_4BIT,
- [SOUND_MIXER_LINE1] = VOL_5BIT,
- [SOUND_MIXER_PHONEIN] = VOL_5BIT,
- [SOUND_MIXER_PHONEOUT] = VOL_6BIT,
- [SOUND_MIXER_VIDEO] = VOL_5BIT,
-/* Not used by the ac97 driver */
- [SOUND_MIXER_SYNTH] = VOL_5BIT,
- [SOUND_MIXER_IMIX] = VOL_5BIT,
- [SOUND_MIXER_RECLEV] = VOL_5BIT,
- [SOUND_MIXER_OGAIN] = VOL_5BIT,
- [SOUND_MIXER_LINE2] = VOL_5BIT,
- [SOUND_MIXER_LINE3] = VOL_5BIT,
- [SOUND_MIXER_DIGITAL1] = VOL_5BIT,
- [SOUND_MIXER_DIGITAL2] = VOL_5BIT,
- [SOUND_MIXER_DIGITAL3] = VOL_5BIT,
- [SOUND_MIXER_RADIO] = VOL_5BIT,
- [SOUND_MIXER_MONITOR] = VOL_5BIT
-};
-
-/* Mixer file operations */
-static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, unsigned long arg)
-{
- struct mixer_private_ioctl *ctl;
- struct dsp_patch *patch;
- u32 size, page;
- int addr, size_reg, i, ret;
- unsigned int id, ch;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
-
- case SOUND_MIXER_PRIVATE3:
-
- ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
- if (ctl == NULL)
- return -ENOMEM;
-
- if (copy_from_user(ctl, argp, sizeof(struct mixer_private_ioctl))) {
- kfree(ctl);
- return -EFAULT;
- }
-
- ret = 0;
- switch (ctl->cmd) {
-#ifdef DBGEMU
- case CMD_WRITEFN0:
- emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]);
- break;
-#endif
- case CMD_WRITEPTR:
-#ifdef DBGEMU
- if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) {
-#else
- if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) &&
- //Any register allowed raw access goes here:
- (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG)
- )
- ) {
-#endif
- ret = -EINVAL;
- break;
- }
- sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]);
- break;
-
- case CMD_READFN0:
- ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]);
-
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
-
- break;
-
- case CMD_READPTR:
- if (ctl->val[1] >= 0x40 || (ctl->val[0] & 0x7ff) > 0xff) {
- ret = -EINVAL;
- break;
- }
-
- if ((ctl->val[0] & 0x7ff) > 0x3f)
- ctl->val[1] = 0x00;
-
- ctl->val[2] = sblive_readptr(card, ctl->val[0], ctl->val[1]);
-
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
-
- break;
-
- case CMD_SETRECSRC:
- switch (ctl->val[0]) {
- case WAVERECORD_AC97:
- if (card->is_aps) {
- ret = -EINVAL;
- break;
- }
-
- card->wavein.recsrc = WAVERECORD_AC97;
- break;
-
- case WAVERECORD_MIC:
- card->wavein.recsrc = WAVERECORD_MIC;
- break;
-
- case WAVERECORD_FX:
- card->wavein.recsrc = WAVERECORD_FX;
- card->wavein.fxwc = ctl->val[1] & 0xffff;
-
- if (!card->wavein.fxwc)
- ret = -EINVAL;
-
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
- break;
-
- case CMD_GETRECSRC:
- ctl->val[0] = card->wavein.recsrc;
- ctl->val[1] = card->wavein.fxwc;
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
-
- break;
-
- case CMD_GETVOICEPARAM:
- ctl->val[0] = card->waveout.send_routing[0];
- ctl->val[1] = card->waveout.send_dcba[0];
-
- ctl->val[2] = card->waveout.send_routing[1];
- ctl->val[3] = card->waveout.send_dcba[1];
-
- ctl->val[4] = card->waveout.send_routing[2];
- ctl->val[5] = card->waveout.send_dcba[2];
-
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
-
- break;
-
- case CMD_SETVOICEPARAM:
- card->waveout.send_routing[0] = ctl->val[0];
- card->waveout.send_dcba[0] = ctl->val[1];
-
- card->waveout.send_routing[1] = ctl->val[2];
- card->waveout.send_dcba[1] = ctl->val[3];
-
- card->waveout.send_routing[2] = ctl->val[4];
- card->waveout.send_dcba[2] = ctl->val[5];
-
- break;
-
- case CMD_SETMCH_FX:
- card->mchannel_fx = ctl->val[0] & 0x000f;
- break;
-
- case CMD_GETPATCH:
- if (ctl->val[0] == 0) {
- if (copy_to_user(argp, &card->mgr.rpatch, sizeof(struct dsp_rpatch)))
- ret = -EFAULT;
- } else {
- if ((ctl->val[0] - 1) / PATCHES_PER_PAGE >= card->mgr.current_pages) {
- ret = -EINVAL;
- break;
- }
-
- if (copy_to_user(argp, PATCH(&card->mgr, ctl->val[0] - 1), sizeof(struct dsp_patch)))
- ret = -EFAULT;
- }
-
- break;
-
- case CMD_GETGPR:
- id = ctl->val[0];
-
- if (id > NUM_GPRS) {
- ret = -EINVAL;
- break;
- }
-
- if (copy_to_user(argp, &card->mgr.gpr[id], sizeof(struct dsp_gpr)))
- ret = -EFAULT;
-
- break;
-
- case CMD_GETCTLGPR:
- addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, &((char *) ctl->val)[PATCH_NAME_SIZE]);
- ctl->val[0] = sblive_readptr(card, addr, 0);
-
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
-
- break;
-
- case CMD_SETPATCH:
- if (ctl->val[0] == 0)
- memcpy(&card->mgr.rpatch, &ctl->val[1], sizeof(struct dsp_rpatch));
- else {
- page = (ctl->val[0] - 1) / PATCHES_PER_PAGE;
- if (page > MAX_PATCHES_PAGES) {
- ret = -EINVAL;
- break;
- }
-
- if (page >= card->mgr.current_pages) {
- for (i = card->mgr.current_pages; i < page + 1; i++) {
- card->mgr.patch[i] = (void *)__get_free_page(GFP_KERNEL);
- if(card->mgr.patch[i] == NULL) {
- card->mgr.current_pages = i;
- ret = -ENOMEM;
- break;
- }
- memset(card->mgr.patch[i], 0, PAGE_SIZE);
- }
- card->mgr.current_pages = page + 1;
- }
-
- patch = PATCH(&card->mgr, ctl->val[0] - 1);
-
- memcpy(patch, &ctl->val[1], sizeof(struct dsp_patch));
-
- if (patch->code_size == 0) {
- for(i = page + 1; i < card->mgr.current_pages; i++)
- free_page((unsigned long) card->mgr.patch[i]);
-
- card->mgr.current_pages = page + 1;
- }
- }
- break;
-
- case CMD_SETGPR:
- if (ctl->val[0] > NUM_GPRS) {
- ret = -EINVAL;
- break;
- }
-
- memcpy(&card->mgr.gpr[ctl->val[0]], &ctl->val[1], sizeof(struct dsp_gpr));
- break;
-
- case CMD_SETCTLGPR:
- addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, (char *) ctl->val + PATCH_NAME_SIZE);
- emu10k1_set_control_gpr(card, addr, *((s32 *)((char *) ctl->val + 2 * PATCH_NAME_SIZE)), 0);
- break;
-
- case CMD_SETGPOUT:
- if ( ((ctl->val[0] > 2) && (!card->is_audigy))
- || (ctl->val[0] > 15) || ctl->val[1] > 1) {
- ret= -EINVAL;
- break;
- }
-
- if (card->is_audigy)
- emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]);
- else
- emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]);
- break;
-
- case CMD_GETGPR2OSS:
- id = ctl->val[0];
- ch = ctl->val[1];
-
- if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
- ret = -EINVAL;
- break;
- }
-
- ctl->val[2] = card->mgr.ctrl_gpr[id][ch];
-
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
-
- break;
-
- case CMD_SETGPR2OSS:
- id = ctl->val[0];
- /* 0 == left, 1 == right */
- ch = ctl->val[1];
- addr = ctl->val[2];
-
- if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
- ret = -EINVAL;
- break;
- }
-
- card->mgr.ctrl_gpr[id][ch] = addr;
-
- if (card->is_aps)
- break;
-
- if (addr >= 0) {
- unsigned int state = card->ac97->mixer_state[id];
-
- if (ch == 1) {
- state >>= 8;
- card->ac97->stereo_mixers |= (1 << id);
- }
-
- card->ac97->supported_mixers |= (1 << id);
-
- if (id == SOUND_MIXER_TREBLE) {
- set_treble(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
- } else if (id == SOUND_MIXER_BASS) {
- set_bass(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
- } else
- emu10k1_set_volume_gpr(card, addr, state & 0xff,
- volume_params[id]);
- } else {
- card->ac97->stereo_mixers &= ~(1 << id);
- card->ac97->stereo_mixers |= card->ac97_stereo_mixers;
-
- if (ch == 0) {
- card->ac97->supported_mixers &= ~(1 << id);
- card->ac97->supported_mixers |= card->ac97_supported_mixers;
- }
- }
- break;
-
- case CMD_SETPASSTHROUGH:
- card->pt.selected = ctl->val[0] ? 1 : 0;
- if (card->pt.state != PT_STATE_INACTIVE)
- break;
-
- card->pt.spcs_to_use = ctl->val[0] & 0x07;
- break;
-
- case CMD_PRIVATE3_VERSION:
- ctl->val[0] = PRIVATE3_VERSION; //private3 version
- ctl->val[1] = MAJOR_VER; //major driver version
- ctl->val[2] = MINOR_VER; //minor driver version
- ctl->val[3] = card->is_audigy; //1=card is audigy
-
- if (card->is_audigy)
- ctl->val[4]=emu10k1_readfn0(card, 0x18);
-
- if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
- ret = -EFAULT;
- break;
-
- case CMD_AC97_BOOST:
- if (ctl->val[0])
- emu10k1_ac97_write(card->ac97, 0x18, 0x0);
- else
- emu10k1_ac97_write(card->ac97, 0x18, 0x0808);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- kfree(ctl);
- return ret;
- break;
-
- case SOUND_MIXER_PRIVATE4:
-
- if (copy_from_user(&size, argp, sizeof(size)))
- return -EFAULT;
-
- DPD(2, "External tram size %#x\n", size);
-
- if (size > 0x1fffff)
- return -EINVAL;
-
- size_reg = 0;
-
- if (size != 0) {
- size = (size - 1) >> 14;
-
- while (size) {
- size >>= 1;
- size_reg++;
- }
-
- size = 0x4000 << size_reg;
- }
-
- DPD(2, "External tram size %#x %#x\n", size, size_reg);
-
- if (size != card->tankmem.size) {
- if (card->tankmem.size > 0) {
- emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 1);
-
- sblive_writeptr_tag(card, 0, TCB, 0, TCBS, 0, TAGLIST_END);
-
- pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
-
- card->tankmem.size = 0;
- }
-
- if (size != 0) {
- card->tankmem.addr = pci_alloc_consistent(card->pci_dev, size, &card->tankmem.dma_handle);
- if (card->tankmem.addr == NULL)
- return -ENOMEM;
-
- card->tankmem.size = size;
-
- sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS,(u32) size_reg, TAGLIST_END);
-
- emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
- }
- }
- return 0;
- break;
-
- default:
- break;
- }
-
- return -EINVAL;
-}
-
-static int emu10k1_dsp_mixer(struct emu10k1_card *card, unsigned int oss_mixer, unsigned long arg)
-{
- unsigned int left, right;
- int val;
- int scale;
-
- card->ac97->modcnt++;
-
- if (get_user(val, (int __user *)arg))
- return -EFAULT;
-
- /* cleanse input a little */
- right = ((val >> 8) & 0xff);
- left = (val & 0xff);
-
- if (right > 100) right = 100;
- if (left > 100) left = 100;
-
- card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
- if (oss_mixer == SOUND_MIXER_TREBLE) {
- set_treble(card, left, right);
- return 0;
- } if (oss_mixer == SOUND_MIXER_BASS) {
- set_bass(card, left, right);
- return 0;
- }
-
- if (oss_mixer == SOUND_MIXER_VOLUME)
- scale = 1 << card->ac97->bit_resolution;
- else
- scale = volume_params[oss_mixer];
-
- emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, scale);
- emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, scale);
-
- if (card->ac97_supported_mixers & (1 << oss_mixer))
- card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
-
- return 0;
-}
-
-static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- int ret;
- struct emu10k1_card *card = file->private_data;
- unsigned int oss_mixer = _IOC_NR(cmd);
-
- ret = -EINVAL;
- if (!card->is_aps) {
- if (cmd == SOUND_MIXER_INFO) {
- mixer_info info;
-
- strlcpy(info.id, card->ac97->name, sizeof(info.id));
-
- if (card->is_audigy)
- strlcpy(info.name, "Audigy - Emu10k1", sizeof(info.name));
- else
- strlcpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
-
- info.modify_counter = card->ac97->modcnt;
-
- if (copy_to_user((void __user *)arg, &info, sizeof(info)))
- return -EFAULT;
-
- return 0;
- }
-
- if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
- ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
- else
- ret = card->ac97->mixer_ioctl(card->ac97, cmd, arg);
- }
-
- if (ret < 0)
- ret = emu10k1_private_mixer(card, cmd, arg);
-
- return ret;
-}
-
-static int emu10k1_mixer_open(struct inode *inode, struct file *file)
-{
- int minor = iminor(inode);
- struct emu10k1_card *card = NULL;
- struct list_head *entry;
-
- DPF(4, "emu10k1_mixer_open()\n");
-
- list_for_each(entry, &emu10k1_devs) {
- card = list_entry(entry, struct emu10k1_card, list);
-
- if (card->ac97->dev_mixer == minor)
- goto match;
- }
-
- return -ENODEV;
-
- match:
- file->private_data = card;
- return 0;
-}
-
-static int emu10k1_mixer_release(struct inode *inode, struct file *file)
-{
- DPF(4, "emu10k1_mixer_release()\n");
- return 0;
-}
-
-const struct file_operations emu10k1_mixer_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .ioctl = emu10k1_mixer_ioctl,
- .open = emu10k1_mixer_open,
- .release = emu10k1_mixer_release,
-};
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
deleted file mode 100644
index 6d21d4368dec..000000000000
--- a/sound/oss/emu10k1/passthrough.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- **********************************************************************
- * passthrough.c -- Emu10k1 digital passthrough
- * Copyright (C) 2001 Juha Yrjölä <jyrjola@cc.hut.fi>
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * May 15, 2001 Juha Yrjölä base code release
- *
- **********************************************************************
- *
- * 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/poll.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-
-#include "hwaccess.h"
-#include "cardwo.h"
-#include "cardwi.h"
-#include "recmgr.h"
-#include "irqmgr.h"
-#include "audio.h"
-#include "8010.h"
-
-static void pt_putsamples(struct pt_data *pt, u16 *ptr, u16 left, u16 right)
-{
- unsigned int idx;
-
- ptr[pt->copyptr] = left;
- idx = pt->copyptr + PT_SAMPLES/2;
- idx %= PT_SAMPLES;
- ptr[idx] = right;
-}
-
-static inline int pt_can_write(struct pt_data *pt)
-{
- return pt->blocks_copied < pt->blocks_played + 8;
-}
-
-static int pt_wait_for_write(struct emu10k1_wavedevice *wavedev, int nonblock)
-{
- struct emu10k1_card *card = wavedev->card;
- struct pt_data *pt = &card->pt;
-
- if (nonblock && !pt_can_write(pt))
- return -EAGAIN;
- while (!pt_can_write(pt) && pt->state != PT_STATE_INACTIVE) {
- interruptible_sleep_on(&pt->wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
- if (pt->state == PT_STATE_INACTIVE)
- return -EAGAIN;
-
- return 0;
-}
-
-static int pt_putblock(struct emu10k1_wavedevice *wave_dev, u16 *block, int nonblock)
-{
- struct woinst *woinst = wave_dev->woinst;
- struct emu10k1_card *card = wave_dev->card;
- struct pt_data *pt = &card->pt;
- u16 *ptr = (u16 *) card->tankmem.addr;
- int i = 0, r;
- unsigned long flags;
-
- r = pt_wait_for_write(wave_dev, nonblock);
- if (r < 0)
- return r;
- spin_lock_irqsave(&card->pt.lock, flags);
- while (i < PT_BLOCKSAMPLES) {
- pt_putsamples(pt, ptr, block[2*i], block[2*i+1]);
- if (pt->copyptr == 0)
- pt->copyptr = PT_SAMPLES;
- pt->copyptr--;
- i++;
- }
- woinst->total_copied += PT_BLOCKSIZE;
- pt->blocks_copied++;
- if (pt->blocks_copied >= 4 && pt->state != PT_STATE_PLAYING) {
- DPF(2, "activating digital pass-through playback\n");
- sblive_writeptr(card, GPR_BASE + pt->enable_gpr, 0, 1);
- pt->state = PT_STATE_PLAYING;
- }
- spin_unlock_irqrestore(&card->pt.lock, flags);
- return 0;
-}
-
-int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev)
-{
- u32 bits;
- struct emu10k1_card *card = wave_dev->card;
- struct pt_data *pt = &card->pt;
- int i;
-
- for (i = 0; i < 3; i++) {
- pt->old_spcs[i] = sblive_readptr(card, SPCS0 + i, 0);
- if (pt->spcs_to_use & (1 << i)) {
- DPD(2, "using S/PDIF port %d\n", i);
- bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
- 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
- if (pt->ac3data)
- bits |= SPCS_NOTAUDIODATA;
- sblive_writeptr(card, SPCS0 + i, 0, bits);
- }
- }
- return 0;
-}
-
-ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t count)
-{
- struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
- struct emu10k1_card *card = wave_dev->card;
- struct pt_data *pt = &card->pt;
- int nonblock, i, r, blocks, blocks_copied, bytes_copied = 0;
-
- DPD(3, "emu10k1_pt_write(): %d bytes\n", count);
-
- nonblock = file->f_flags & O_NONBLOCK;
-
- if (card->tankmem.size < PT_SAMPLES*2)
- return -EFAULT;
- if (pt->state == PT_STATE_INACTIVE) {
- DPF(2, "bufptr init\n");
- pt->playptr = PT_SAMPLES-1;
- pt->copyptr = PT_INITPTR;
- pt->blocks_played = pt->blocks_copied = 0;
- memset(card->tankmem.addr, 0, card->tankmem.size);
- pt->state = PT_STATE_ACTIVATED;
- pt->buf = kmalloc(PT_BLOCKSIZE, GFP_KERNEL);
- pt->prepend_size = 0;
- if (pt->buf == NULL)
- return -ENOMEM;
- emu10k1_pt_setup(wave_dev);
- }
- if (pt->prepend_size) {
- int needed = PT_BLOCKSIZE - pt->prepend_size;
-
- DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
- if (count < needed) {
- if (copy_from_user(pt->buf + pt->prepend_size,
- buffer, count))
- return -EFAULT;
- pt->prepend_size += count;
- DPD(3, "prepend size now %d\n", pt->prepend_size);
- return count;
- }
- if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
- return -EFAULT;
- r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
- if (r)
- return r;
- bytes_copied += needed;
- pt->prepend_size = 0;
- }
- blocks = (count-bytes_copied)/PT_BLOCKSIZE;
- blocks_copied = 0;
- while (blocks > 0) {
- u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2);
- if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
- return -EFAULT;
- r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock);
- if (r) {
- if (bytes_copied)
- return bytes_copied;
- else
- return r;
- }
- bytes_copied += PT_BLOCKSIZE;
- blocks--;
- blocks_copied++;
- }
- i = count - bytes_copied;
- if (i) {
- pt->prepend_size = i;
- if (copy_from_user(pt->buf, buffer + bytes_copied, i))
- return -EFAULT;
- bytes_copied += i;
- DPD(3, "filling prepend buffer with %d bytes", i);
- }
- return bytes_copied;
-}
-
-void emu10k1_pt_stop(struct emu10k1_card *card)
-{
- struct pt_data *pt = &card->pt;
- int i;
-
- if (pt->state != PT_STATE_INACTIVE) {
- DPF(2, "digital pass-through stopped\n");
- sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 0);
- for (i = 0; i < 3; i++) {
- if (pt->spcs_to_use & (1 << i))
- sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]);
- }
- pt->state = PT_STATE_INACTIVE;
- kfree(pt->buf);
- }
-}
-
-void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev)
-{
- struct woinst *woinst = wave_dev->woinst;
- struct pt_data *pt = &wave_dev->card->pt;
- u32 pos;
-
- if (pt->state == PT_STATE_PLAYING && pt->pos_gpr >= 0) {
- pos = sblive_readptr(wave_dev->card, GPR_BASE + pt->pos_gpr, 0);
- if (pos > PT_BLOCKSAMPLES)
- pos = PT_BLOCKSAMPLES;
- pos = 4 * (PT_BLOCKSAMPLES - pos);
- } else
- pos = 0;
- woinst->total_played = pt->blocks_played * woinst->buffer.fragment_size + pos;
- woinst->buffer.hw_pos = pos;
-}
diff --git a/sound/oss/emu10k1/passthrough.h b/sound/oss/emu10k1/passthrough.h
deleted file mode 100644
index 420cc9784251..000000000000
--- a/sound/oss/emu10k1/passthrough.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- **********************************************************************
- * passthrough.h -- Emu10k1 digital passthrough header file
- * Copyright (C) 2001 Juha Yrjölä <jyrjola@cc.hut.fi>
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * May 15, 2001 Juha Yrjölä base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _PASSTHROUGH_H
-#define _PASSTHROUGH_H
-
-#include "audio.h"
-
-/* number of 16-bit stereo samples in XTRAM buffer */
-#define PT_SAMPLES 0x8000
-#define PT_BLOCKSAMPLES 0x400
-#define PT_BLOCKSIZE (PT_BLOCKSAMPLES*4)
-#define PT_BLOCKSIZE_LOG2 12
-#define PT_BLOCKCOUNT (PT_SAMPLES/PT_BLOCKSAMPLES)
-#define PT_INITPTR (PT_SAMPLES/2-1)
-
-#define PT_STATE_INACTIVE 0
-#define PT_STATE_ACTIVATED 1
-#define PT_STATE_PLAYING 2
-
-/* passthrough struct */
-struct pt_data
-{
- u8 selected, state, spcs_to_use;
- int intr_gpr, enable_gpr, pos_gpr;
- u32 blocks_played, blocks_copied, old_spcs[3];
- u32 playptr, copyptr;
- u32 prepend_size;
- u8 *buf;
- u8 ac3data;
-
- char *patch_name, *intr_gpr_name, *enable_gpr_name, *pos_gpr_name;
-
- wait_queue_head_t wait;
- spinlock_t lock;
-};
-
-/*
- Passthrough can be done in two methods:
-
- Method 1 : tram
- In original emu10k1, we couldn't bypass the sample rate converters. Even at 48kHz
- (the internal sample rate of the emu10k1) the samples would get messed up.
- To over come this, samples are copied into the tram and a special dsp patch copies
- the samples out and generates interrupts when a block has finnished playing.
-
- Method 2 : Interpolator bypass
-
- Creative fixed the sample rate convert problem in emu10k1 rev 7 and higher
- (including the emu10k2 (audigy)). This allows us to use the regular, and much simpler
- playback method.
-
-
- In both methods, dsp code is used to mux audio and passthrough. This ensures that the spdif
- doesn't receive audio and pasthrough data at the same time. The spdif flag SPCS_NOTAUDIODATA
- is set to tell
-
- */
-
-// emu10k1 revs greater than or equal to 7 can use method2
-
-#define USE_PT_METHOD2 (card->is_audigy)
-#define USE_PT_METHOD1 !USE_PT_METHOD2
-
-ssize_t emu10k1_pt_write(struct file *file, const char __user *buf, size_t count);
-
-int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev);
-void emu10k1_pt_stop(struct emu10k1_card *card);
-void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev);
-
-#endif /* _PASSTHROUGH_H */
diff --git a/sound/oss/emu10k1/recmgr.c b/sound/oss/emu10k1/recmgr.c
deleted file mode 100644
index 2ce56180e7d4..000000000000
--- a/sound/oss/emu10k1/recmgr.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- **********************************************************************
- * recmgr.c -- Recording manager for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#include <linux/delay.h>
-#include "8010.h"
-#include "recmgr.h"
-
-void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
- DPF(2, "emu10k1_reset_record()\n");
-
- sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
-
- sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);
-
- while (sblive_readptr(card, buffer->idxreg, 0))
- udelay(5);
-}
-
-void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
- DPF(2, "emu10k1_start_record()\n");
-
- if (buffer->adcctl)
- sblive_writeptr(card, ADCCR, 0, buffer->adcctl);
-}
-
-void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
-{
- DPF(2, "emu10k1_stop_record()\n");
-
- /* Disable record transfer */
- if (buffer->adcctl)
- sblive_writeptr(card, ADCCR, 0, 0);
-}
-
-void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
-{
- struct wavein_buffer *buffer = &wiinst->buffer;
-
- DPF(2, "emu10k1_set_record_src()\n");
-
- switch (wiinst->recsrc) {
-
- case WAVERECORD_AC97:
- DPF(2, "recording source: AC97\n");
- buffer->sizereg = ADCBS;
- buffer->addrreg = ADCBA;
- buffer->idxreg = card->is_audigy ? A_ADCIDX_IDX : ADCIDX_IDX;
-
- switch (wiinst->format.samplingrate) {
- case 0xBB80:
- buffer->adcctl = ADCCR_SAMPLERATE_48;
- break;
- case 0xAC44:
- buffer->adcctl = ADCCR_SAMPLERATE_44;
- break;
- case 0x7D00:
- buffer->adcctl = ADCCR_SAMPLERATE_32;
- break;
- case 0x5DC0:
- buffer->adcctl = ADCCR_SAMPLERATE_24;
- break;
- case 0x5622:
- buffer->adcctl = ADCCR_SAMPLERATE_22;
- break;
- case 0x3E80:
- buffer->adcctl = ADCCR_SAMPLERATE_16;
- break;
- // FIXME: audigy supports 12kHz recording
- /*
- case ????:
- buffer->adcctl = A_ADCCR_SAMPLERATE_12;
- break;
- */
- case 0x2B11:
- buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_11 : ADCCR_SAMPLERATE_11;
- break;
- case 0x1F40:
- buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_8 : ADCCR_SAMPLERATE_8;
- break;
- default:
- BUG();
- break;
- }
-
- buffer->adcctl |= card->is_audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
-
- if (wiinst->format.channels == 2)
- buffer->adcctl |= card->is_audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
-
- break;
-
- case WAVERECORD_MIC:
- DPF(2, "recording source: MIC\n");
- buffer->sizereg = MICBS;
- buffer->addrreg = MICBA;
- buffer->idxreg = MICIDX_IDX;
- buffer->adcctl = 0;
- break;
-
- case WAVERECORD_FX:
- DPF(2, "recording source: FX\n");
- buffer->sizereg = FXBS;
- buffer->addrreg = FXBA;
- buffer->idxreg = FXIDX_IDX;
- buffer->adcctl = 0;
-
- sblive_writeptr(card, FXWC, 0, wiinst->fxwc);
- break;
- default:
- BUG();
- break;
- }
-
- DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle);
-
- sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle);
-}
diff --git a/sound/oss/emu10k1/recmgr.h b/sound/oss/emu10k1/recmgr.h
deleted file mode 100644
index a68766ac4fd5..000000000000
--- a/sound/oss/emu10k1/recmgr.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- **********************************************************************
- * recmgr.h
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _RECORDMGR_H
-#define _RECORDMGR_H
-
-#include "hwaccess.h"
-#include "cardwi.h"
-
-/* Recording resources */
-#define WAVERECORD_AC97 0x01
-#define WAVERECORD_MIC 0x02
-#define WAVERECORD_FX 0x03
-
-void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer);
-void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *);
-void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *);
-void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst);
-
-#endif /* _RECORDMGR_H */
diff --git a/sound/oss/emu10k1/timer.c b/sound/oss/emu10k1/timer.c
deleted file mode 100644
index d10d30739f41..000000000000
--- a/sound/oss/emu10k1/timer.c
+++ /dev/null
@@ -1,176 +0,0 @@
-
-/*
- **********************************************************************
- * timer.c
- * Copyright (C) 1999, 2000 Creative Labs, inc.
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-/* 3/6/2000 Improved support for different timer delays Rui Sousa */
-
-/* 4/3/2000 Implemented timer list using list.h Rui Sousa */
-
-#include "hwaccess.h"
-#include "8010.h"
-#include "irqmgr.h"
-#include "timer.h"
-
-/* Try to schedule only once per fragment */
-
-void emu10k1_timer_irqhandler(struct emu10k1_card *card)
-{
- struct emu_timer *t;
- struct list_head *entry;
-
- spin_lock(&card->timer_lock);
-
- list_for_each(entry, &card->timers) {
- t = list_entry(entry, struct emu_timer, list);
-
- if (t->state & TIMER_STATE_ACTIVE) {
- t->count++;
- if (t->count == t->count_max) {
- t->count = 0;
- tasklet_hi_schedule(&t->tasklet);
- }
- }
- }
-
- spin_unlock(&card->timer_lock);
-
- return;
-}
-
-void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u16 delay)
-{
- struct emu_timer *t;
- struct list_head *entry;
- unsigned long flags;
-
- if (delay < 5)
- delay = 5;
-
- timer->delay = delay;
- timer->state = TIMER_STATE_INSTALLED;
-
- spin_lock_irqsave(&card->timer_lock, flags);
-
- timer->count_max = timer->delay / (card->timer_delay < 1024 ? card->timer_delay : 1024);
- timer->count = timer->count_max - 1;
-
- list_add(&timer->list, &card->timers);
-
- if (card->timer_delay > delay) {
- if (card->timer_delay == TIMER_STOPPED)
- emu10k1_irq_enable(card, INTE_INTERVALTIMERENB);
-
- card->timer_delay = delay;
- delay = (delay < 1024 ? delay : 1024);
-
- emu10k1_timer_set(card, delay);
-
- list_for_each(entry, &card->timers) {
- t = list_entry(entry, struct emu_timer, list);
-
- t->count_max = t->delay / delay;
- /* don't want to think much, just force scheduling
- on the next interrupt */
- t->count = t->count_max - 1;
- }
-
- DPD(2, "timer rate --> %u\n", delay);
- }
-
- spin_unlock_irqrestore(&card->timer_lock, flags);
-
- return;
-}
-
-void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
-{
- struct emu_timer *t;
- struct list_head *entry;
- u16 delay = TIMER_STOPPED;
- unsigned long flags;
-
- if (timer->state == TIMER_STATE_UNINSTALLED)
- return;
-
- spin_lock_irqsave(&card->timer_lock, flags);
-
- list_del(&timer->list);
-
- list_for_each(entry, &card->timers) {
- t = list_entry(entry, struct emu_timer, list);
-
- if (t->delay < delay)
- delay = t->delay;
- }
-
- if (card->timer_delay != delay) {
- card->timer_delay = delay;
-
- if (delay == TIMER_STOPPED)
- emu10k1_irq_disable(card, INTE_INTERVALTIMERENB);
- else {
- delay = (delay < 1024 ? delay : 1024);
-
- emu10k1_timer_set(card, delay);
-
- list_for_each(entry, &card->timers) {
- t = list_entry(entry, struct emu_timer, list);
-
- t->count_max = t->delay / delay;
- t->count = t->count_max - 1;
- }
- }
-
- DPD(2, "timer rate --> %u\n", delay);
- }
-
- spin_unlock_irqrestore(&card->timer_lock, flags);
-
- timer->state = TIMER_STATE_UNINSTALLED;
-
- return;
-}
-
-void emu10k1_timer_enable(struct emu10k1_card *card, struct emu_timer *timer)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&card->timer_lock, flags);
- timer->state |= TIMER_STATE_ACTIVE;
- spin_unlock_irqrestore(&card->timer_lock, flags);
-
- return;
-}
-
-void emu10k1_timer_disable(struct emu10k1_card *card, struct emu_timer *timer)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&card->timer_lock, flags);
- timer->state &= ~TIMER_STATE_ACTIVE;
- spin_unlock_irqrestore(&card->timer_lock, flags);
-
- return;
-}
diff --git a/sound/oss/emu10k1/timer.h b/sound/oss/emu10k1/timer.h
deleted file mode 100644
index b2543b4d53a8..000000000000
--- a/sound/oss/emu10k1/timer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- **********************************************************************
- * timer.h
- * Copyright (C) 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-
-#ifndef _TIMER_H
-#define _TIMER_H
-
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include "hwaccess.h"
-
-struct emu_timer
-{
- struct list_head list;
- struct tasklet_struct tasklet;
- u8 state;
- u16 count; /* current number of interrupts */
- u16 count_max; /* number of interrupts needed to schedule the bh */
- u16 delay; /* timer delay */
-};
-
-void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u16);
-void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *);
-void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *);
-void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *);
-
-#define TIMER_STOPPED 0xffff
-#define TIMER_STATE_INSTALLED 0x01
-#define TIMER_STATE_ACTIVE 0x02
-#define TIMER_STATE_UNINSTALLED 0x04
-
-#endif /* _TIMER_H */
diff --git a/sound/oss/emu10k1/voicemgr.c b/sound/oss/emu10k1/voicemgr.c
deleted file mode 100644
index d88b602c07c2..000000000000
--- a/sound/oss/emu10k1/voicemgr.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- **********************************************************************
- * voicemgr.c - Voice manager for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * 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 "voicemgr.h"
-#include "8010.h"
-
-#define PITCH_48000 0x00004000
-#define PITCH_96000 0x00008000
-#define PITCH_85000 0x00007155
-#define PITCH_80726 0x00006ba2
-#define PITCH_67882 0x00005a82
-#define PITCH_57081 0x00004c1c
-
-static u32 emu10k1_select_interprom(struct emu10k1_card *card,
- struct emu_voice *voice)
-{
- if(voice->pitch_target==PITCH_48000)
- return CCCA_INTERPROM_0;
- else if(voice->pitch_target<PITCH_48000)
- return CCCA_INTERPROM_1;
- else if(voice->pitch_target>=PITCH_96000)
- return CCCA_INTERPROM_0;
- else if(voice->pitch_target>=PITCH_85000)
- return CCCA_INTERPROM_6;
- else if(voice->pitch_target>=PITCH_80726)
- return CCCA_INTERPROM_5;
- else if(voice->pitch_target>=PITCH_67882)
- return CCCA_INTERPROM_4;
- else if(voice->pitch_target>=PITCH_57081)
- return CCCA_INTERPROM_3;
- else
- return CCCA_INTERPROM_2;
-}
-
-
-/**
- * emu10k1_voice_alloc_buffer -
- *
- * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
- * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
- * is passed to the device so that it can do DMA to host memory.
- *
- */
-int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
-{
- u32 pageindex, pagecount;
- u32 busaddx;
- int i;
-
- DPD(2, "requested pages is: %d\n", pages);
-
- if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
- {
- DPF(1, "couldn't allocate emu10k1 address space\n");
- return -1;
- }
-
- /* Fill in virtual memory table */
- for (pagecount = 0; pagecount < pages; pagecount++) {
- if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
- == NULL) {
- mem->pages = pagecount;
- DPF(1, "couldn't allocate dma memory\n");
- return -1;
- }
-
- DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
-
- for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
- busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
-
- DPD(3, "Bus Addx: %#x\n", busaddx);
-
- pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-
- ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
- }
- }
-
- mem->pages = pagecount;
-
- return 0;
-}
-
-/**
- * emu10k1_voice_free_buffer -
- *
- * frees the memory buffer for a voice.
- */
-void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
-{
- u32 pagecount, pageindex;
- int i;
-
- if (mem->emupageindex < 0)
- return;
-
- for (pagecount = 0; pagecount < mem->pages; pagecount++) {
- pci_free_consistent(card->pci_dev, PAGE_SIZE,
- mem->addr[pagecount],
- mem->dma_handle[pagecount]);
-
- for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
- pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
- ((u32 *) card->virtualpagetable.addr)[pageindex] =
- cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
- }
- }
-
- emu10k1_addxmgr_free(card, mem->emupageindex);
- mem->emupageindex = -1;
-}
-
-int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
-{
- u8 *voicetable = card->voicetable;
- int i;
- unsigned long flags;
-
- DPF(2, "emu10k1_voice_alloc()\n");
-
- spin_lock_irqsave(&card->lock, flags);
-
- if (voice->flags & VOICE_FLAGS_STEREO) {
- for (i = 0; i < NUM_G; i += 2)
- if ((voicetable[i] == VOICE_USAGE_FREE) && (voicetable[i + 1] == VOICE_USAGE_FREE)) {
- voicetable[i] = voice->usage;
- voicetable[i + 1] = voice->usage;
- break;
- }
- } else {
- for (i = 0; i < NUM_G; i++)
- if (voicetable[i] == VOICE_USAGE_FREE) {
- voicetable[i] = voice->usage;
- break;
- }
- }
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- if (i >= NUM_G)
- return -1;
-
- voice->card = card;
- voice->num = i;
-
- for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
- DPD(2, " voice allocated -> %d\n", voice->num + i);
-
- sblive_writeptr_tag(card, voice->num + i, IFATN, 0xffff,
- DCYSUSV, 0,
- VTFT, 0x0000ffff,
- PTRX, 0,
- TAGLIST_END);
- }
-
- return 0;
-}
-
-void emu10k1_voice_free(struct emu_voice *voice)
-{
- struct emu10k1_card *card = voice->card;
- int i;
- unsigned long flags;
-
- DPF(2, "emu10k1_voice_free()\n");
-
- if (voice->usage == VOICE_USAGE_FREE)
- return;
-
- for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
- DPD(2, " voice released -> %d\n", voice->num + i);
-
- sblive_writeptr_tag(card, voice->num + i, DCYSUSV, 0,
- VTFT, 0x0000ffff,
- PTRX_PITCHTARGET, 0,
- CVCF, 0x0000ffff,
- //CPF, 0,
- TAGLIST_END);
-
- sblive_writeptr(card, CPF, voice->num + i, 0);
- }
-
- voice->usage = VOICE_USAGE_FREE;
-
- spin_lock_irqsave(&card->lock, flags);
-
- card->voicetable[voice->num] = VOICE_USAGE_FREE;
-
- if (voice->flags & VOICE_FLAGS_STEREO)
- card->voicetable[voice->num + 1] = VOICE_USAGE_FREE;
-
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-void emu10k1_voice_playback_setup(struct emu_voice *voice)
-{
- struct emu10k1_card *card = voice->card;
- u32 start;
- int i;
-
- DPF(2, "emu10k1_voice_playback_setup()\n");
-
- if (voice->flags & VOICE_FLAGS_STEREO) {
- /* Set stereo bit */
- start = 28;
- sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
- sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
- } else {
- start = 30;
- sblive_writeptr(card, CPF, voice->num, 0);
- }
-
- if(!(voice->flags & VOICE_FLAGS_16BIT))
- start *= 2;
-
- voice->start += start;
-
- for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
- if (card->is_audigy) {
- sblive_writeptr(card, A_FXRT1, voice->num + i, voice->params[i].send_routing);
- sblive_writeptr(card, A_FXRT2, voice->num + i, voice->params[i].send_routing2);
- sblive_writeptr(card, A_SENDAMOUNTS, voice->num + i, voice->params[i].send_hgfe);
- } else {
- sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
- }
-
- /* Stop CA */
- /* Assumption that PT is already 0 so no harm overwriting */
- sblive_writeptr(card, PTRX, voice->num + i, ((voice->params[i].send_dcba & 0xff) << 8)
- | ((voice->params[i].send_dcba & 0xff00) >> 8));
-
- sblive_writeptr_tag(card, voice->num + i,
- /* CSL, ST, CA */
- DSL, voice->endloop | (voice->params[i].send_dcba & 0xff000000),
- PSST, voice->startloop | ((voice->params[i].send_dcba & 0x00ff0000) << 8),
- CCCA, (voice->start) | emu10k1_select_interprom(card,voice) |
- ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
- /* Clear filter delay memory */
- Z1, 0,
- Z2, 0,
- /* Invalidate maps */
- MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
- MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
- /* modulation envelope */
- CVCF, 0x0000ffff,
- VTFT, 0x0000ffff,
- ATKHLDM, 0,
- DCYSUSM, 0x007f,
- LFOVAL1, 0x8000,
- LFOVAL2, 0x8000,
- FMMOD, 0,
- TREMFRQ, 0,
- FM2FRQ2, 0,
- ENVVAL, 0x8000,
- /* volume envelope */
- ATKHLDV, 0x7f7f,
- ENVVOL, 0x8000,
- /* filter envelope */
- PEFE_FILTERAMOUNT, 0x7f,
- /* pitch envelope */
- PEFE_PITCHAMOUNT, 0, TAGLIST_END);
-
- voice->params[i].fc_target = 0xffff;
- }
-}
-
-void emu10k1_voices_start(struct emu_voice *first_voice, unsigned int num_voices, int set)
-{
- struct emu10k1_card *card = first_voice->card;
- struct emu_voice *voice;
- unsigned int voicenum;
- int j;
-
- DPF(2, "emu10k1_voices_start()\n");
-
- for (voicenum = 0; voicenum < num_voices; voicenum++)
- {
- voice = first_voice + voicenum;
-
- if (!set) {
- u32 cra, ccis, cs, sample;
- if (voice->flags & VOICE_FLAGS_STEREO) {
- cra = 64;
- ccis = 28;
- cs = 4;
- } else {
- cra = 64;
- ccis = 30;
- cs = 2;
- }
-
- if(voice->flags & VOICE_FLAGS_16BIT) {
- sample = 0x00000000;
- } else {
- sample = 0x80808080;
- ccis *= 2;
- }
-
- for(j = 0; j < cs; j++)
- sblive_writeptr(card, CD0 + j, voice->num, sample);
-
- /* Reset cache */
- sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, 0);
- if (voice->flags & VOICE_FLAGS_STEREO)
- sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num + 1, 0);
-
- sblive_writeptr(card, CCR_READADDRESS, voice->num, cra);
-
- if (voice->flags & VOICE_FLAGS_STEREO)
- sblive_writeptr(card, CCR_READADDRESS, voice->num + 1, cra);
-
- /* Fill cache */
- sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, ccis);
- }
-
- for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
- sblive_writeptr_tag(card, voice->num + j,
- IFATN, (voice->params[j].initial_fc << 8) | voice->params[j].initial_attn,
- VTFT, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
- CVCF, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
- DCYSUSV, (voice->params[j].byampl_env_sustain << 8) | voice->params[j].byampl_env_decay,
- TAGLIST_END);
-
- emu10k1_clear_stop_on_loop(card, voice->num + j);
- }
- }
-
-
- for (voicenum = 0; voicenum < num_voices; voicenum++)
- {
- voice = first_voice + voicenum;
-
- for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
- sblive_writeptr(card, PTRX_PITCHTARGET, voice->num + j, voice->pitch_target);
-
- if (j == 0)
- sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->pitch_target);
-
- sblive_writeptr(card, IP, voice->num + j, voice->initial_pitch);
- }
- }
-}
-
-void emu10k1_voices_stop(struct emu_voice *first_voice, int num_voices)
-{
- struct emu10k1_card *card = first_voice->card;
- struct emu_voice *voice;
- unsigned int voice_num;
- int j;
-
- DPF(2, "emu10k1_voice_stop()\n");
-
- for (voice_num = 0; voice_num < num_voices; voice_num++)
- {
- voice = first_voice + voice_num;
-
- for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
- sblive_writeptr_tag(card, voice->num + j,
- PTRX_PITCHTARGET, 0,
- CPF_CURRENTPITCH, 0,
- IFATN, 0xffff,
- VTFT, 0x0000ffff,
- CVCF, 0x0000ffff,
- IP, 0,
- TAGLIST_END);
- }
- }
-}
-
diff --git a/sound/oss/emu10k1/voicemgr.h b/sound/oss/emu10k1/voicemgr.h
deleted file mode 100644
index 099a8cb7f2c5..000000000000
--- a/sound/oss/emu10k1/voicemgr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- **********************************************************************
- * sblive_voice.h -- EMU Voice Resource Manager header file
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
-
-#ifndef _VOICEMGR_H
-#define _VOICEMGR_H
-
-#include "hwaccess.h"
-
-/* struct emu_voice.usage flags */
-#define VOICE_USAGE_FREE 0x01
-#define VOICE_USAGE_MIDI 0x02
-#define VOICE_USAGE_PLAYBACK 0x04
-
-/* struct emu_voice.flags flags */
-#define VOICE_FLAGS_STEREO 0x02
-#define VOICE_FLAGS_16BIT 0x04
-
-struct voice_param
-{
- /* FX bus amount send */
-
- u32 send_routing;
- // audigy only:
- u32 send_routing2;
-
- u32 send_dcba;
- // audigy only:
- u32 send_hgfe;
-
-
- u32 initial_fc;
- u32 fc_target;
-
- u32 initial_attn;
- u32 volume_target;
-
- u32 byampl_env_sustain;
- u32 byampl_env_decay;
-};
-
-struct voice_mem {
- int emupageindex;
- void *addr[BUFMAXPAGES];
- dma_addr_t dma_handle[BUFMAXPAGES];
- u32 pages;
-};
-
-struct emu_voice
-{
- struct emu10k1_card *card;
- u8 usage; /* Free, MIDI, playback */
- u8 num; /* Voice ID */
- u8 flags; /* Stereo/mono, 8/16 bit */
-
- u32 startloop;
- u32 endloop;
- u32 start;
-
- u32 initial_pitch;
- u32 pitch_target;
-
- struct voice_param params[2];
-
- struct voice_mem mem;
-};
-
-int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32);
-void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *);
-int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
-void emu10k1_voice_free(struct emu_voice *);
-void emu10k1_voice_playback_setup(struct emu_voice *);
-void emu10k1_voices_start(struct emu_voice *, unsigned int, int);
-void emu10k1_voices_stop(struct emu_voice *, int);
-
-#endif /* _VOICEMGR_H */
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 2796c0ef985f..a690ca57adb5 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1003,7 +1003,8 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
}
if (!devc->shared_irq)
{
- if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0)
+ if (request_irq(devc->irq, mpuintr, 0, "mpu401",
+ hw_config) < 0)
{
printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq);
ret = -ENOMEM;
@@ -1112,7 +1113,7 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
return 0;
out_irq:
- free_irq(devc->irq, (void *)m);
+ free_irq(devc->irq, hw_config);
out_mididev:
sound_unload_mididev(m);
out_err:
@@ -1227,7 +1228,7 @@ void unload_mpu401(struct address_info *hw_config)
if (n != -1) {
release_region(hw_config->io_base, 2);
if (hw_config->always_detect == 0 && hw_config->irq > 0)
- free_irq(hw_config->irq, (void *)n);
+ free_irq(hw_config->irq, hw_config);
p=mpu401_synth_operations[n];
sound_unload_mididev(n);
sound_unload_timerdev(hw_config->slots[2]);
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h
deleted file mode 100644
index 1dade9033995..000000000000
--- a/sound/oss/nm256.h
+++ /dev/null
@@ -1,292 +0,0 @@
-#ifndef _NM256_H_
-#define _NM256_H_
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-
-#include "ac97.h"
-
-/* The revisions that we currently handle. */
-enum nm256rev {
- REV_NM256AV, REV_NM256ZX
-};
-
-/* Per-card structure. */
-struct nm256_info
-{
- /* Magic number used to verify that this struct is valid. */
-#define NM_MAGIC_SIG 0x55aa00ff
- int magsig;
-
- /* Revision number */
- enum nm256rev rev;
-
- struct ac97_hwint mdev;
-
- /* Our audio device numbers. */
- int dev[2];
-
- /* The # of times each device has been opened. (Should only be
- 0 or 1). */
- int opencnt[2];
-
- /* We use two devices, because we can do simultaneous play and record.
- This keeps track of which device is being used for what purpose;
- these are the actual device numbers. */
- int dev_for_play;
- int dev_for_record;
-
- spinlock_t lock;
-
- /* The mixer device. */
- int mixer_oss_dev;
-
- /*
- * Can only be opened once for each operation. These aren't set
- * until an actual I/O operation is performed; this allows one
- * device to be open for read/write without inhibiting I/O to
- * the other device.
- */
- int is_open_play;
- int is_open_record;
-
- /* Non-zero if we're currently playing a sample. */
- int playing;
- /* Ditto for recording a sample. */
- int recording;
-
- /* The two memory ports. */
- struct nm256_ports {
- /* Physical address of the port. */
- u32 physaddr;
- /* Our mapped-in pointer. */
- char __iomem *ptr;
- /* PTR's offset within the physical port. */
- u32 start_offset;
- /* And the offset of the end of the buffer. */
- u32 end_offset;
- } port[2];
-
- /* The following are offsets within memory port 1. */
- u32 coeffBuf;
- u32 allCoeffBuf;
-
- /* Record and playback buffers. */
- u32 abuf1, abuf2;
-
- /* Offset of the AC97 mixer in memory port 2. */
- u32 mixer;
-
- /* Offset of the mixer status register in memory port 2. */
- u32 mixer_status_offset;
-
- /* Non-zero if we have written initial values to the mixer. */
- u8 mixer_values_init;
-
- /*
- * Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means
- * it's ready.
- */
- u16 mixer_status_mask;
-
- /* The sizes of the playback and record ring buffers. */
- u32 playbackBufferSize;
- u32 recordBufferSize;
-
- /* Are the coefficient values in the memory cache current? */
- u8 coeffsCurrent;
-
- /* For writes, the amount we last wrote. */
- u32 requested_amt;
- /* The start of the block currently playing. */
- u32 curPlayPos;
-
- /* The amount of data we were requested to record. */
- u32 requestedRecAmt;
- /* The offset of the currently-recording block. */
- u32 curRecPos;
- /* The destination buffer. */
- char *recBuf;
-
- /* Our IRQ number. */
- int irq;
-
- /* A flag indicating how many times we've grabbed the IRQ. */
- int has_irq;
-
- /* The card interrupt service routine. */
- irq_handler_t introutine;
-
- /* Current audio config, cached. */
- struct sinfo {
- u32 samplerate;
- u8 bits;
- u8 stereo;
- } sinfo[2]; /* goes with each device */
-
- /* The cards are stored in a chain; this is the next card. */
- struct nm256_info *next_card;
-};
-
-/* The BIOS signature. */
-#define NM_SIGNATURE 0x4e4d0000
-/* Signature mask. */
-#define NM_SIG_MASK 0xffff0000
-
-/* Size of the second memory area. */
-#define NM_PORT2_SIZE 4096
-
-/* The base offset of the mixer in the second memory area. */
-#define NM_MIXER_OFFSET 0x600
-
-/* The maximum size of a coefficient entry. */
-#define NM_MAX_COEFFICIENT 0x5000
-
-/* The interrupt register. */
-#define NM_INT_REG 0xa04
-/* And its bits. */
-#define NM_PLAYBACK_INT 0x40
-#define NM_RECORD_INT 0x100
-#define NM_MISC_INT_1 0x4000
-#define NM_MISC_INT_2 0x1
-#define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1)
-
-/* The AV's "mixer ready" status bit and location. */
-#define NM_MIXER_STATUS_OFFSET 0xa04
-#define NM_MIXER_READY_MASK 0x0800
-#define NM_MIXER_PRESENCE 0xa06
-#define NM_PRESENCE_MASK 0x0050
-#define NM_PRESENCE_VALUE 0x0040
-
-/*
- * For the ZX. It uses the same interrupt register, but it holds 32
- * bits instead of 16.
- */
-#define NM2_PLAYBACK_INT 0x10000
-#define NM2_RECORD_INT 0x80000
-#define NM2_MISC_INT_1 0x8
-#define NM2_MISC_INT_2 0x2
-#define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X))
-
-/* The ZX's "mixer ready" status bit and location. */
-#define NM2_MIXER_STATUS_OFFSET 0xa06
-#define NM2_MIXER_READY_MASK 0x0800
-
-/* The playback registers start from here. */
-#define NM_PLAYBACK_REG_OFFSET 0x0
-/* The record registers start from here. */
-#define NM_RECORD_REG_OFFSET 0x200
-
-/* The rate register is located 2 bytes from the start of the register area. */
-#define NM_RATE_REG_OFFSET 2
-
-/* Mono/stereo flag, number of bits on playback, and rate mask. */
-#define NM_RATE_STEREO 1
-#define NM_RATE_BITS_16 2
-#define NM_RATE_MASK 0xf0
-
-/* Playback enable register. */
-#define NM_PLAYBACK_ENABLE_REG (NM_PLAYBACK_REG_OFFSET + 0x1)
-#define NM_PLAYBACK_ENABLE_FLAG 1
-#define NM_PLAYBACK_ONESHOT 2
-#define NM_PLAYBACK_FREERUN 4
-
-/* Mutes the audio output. */
-#define NM_AUDIO_MUTE_REG (NM_PLAYBACK_REG_OFFSET + 0x18)
-#define NM_AUDIO_MUTE_LEFT 0x8000
-#define NM_AUDIO_MUTE_RIGHT 0x0080
-
-/* Recording enable register. */
-#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0)
-#define NM_RECORD_ENABLE_FLAG 1
-#define NM_RECORD_FREERUN 2
-
-#define NM_RBUFFER_START (NM_RECORD_REG_OFFSET + 0x4)
-#define NM_RBUFFER_END (NM_RECORD_REG_OFFSET + 0x10)
-#define NM_RBUFFER_WMARK (NM_RECORD_REG_OFFSET + 0xc)
-#define NM_RBUFFER_CURRP (NM_RECORD_REG_OFFSET + 0x8)
-
-#define NM_PBUFFER_START (NM_PLAYBACK_REG_OFFSET + 0x4)
-#define NM_PBUFFER_END (NM_PLAYBACK_REG_OFFSET + 0x14)
-#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc)
-#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8)
-
-/* A few trivial routines to make it easier to work with the registers
- on the chip. */
-
-/* This is a common code portion used to fix up the port offsets. */
-#define NM_FIX_PORT \
- if (port < 1 || port > 2 || card == NULL) \
- return -1; \
-\
- if (offset < card->port[port - 1].start_offset \
- || offset >= card->port[port - 1].end_offset) { \
- printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \
- return -1; \
- } \
- offset -= card->port[port - 1].start_offset;
-
-#define DEFwritePortX(X, func) \
-static inline int nm256_writePort##X (struct nm256_info *card,\
- int port, int offset, int value)\
-{\
- u##X __iomem *addr;\
-\
- if (nm256_debug > 1)\
- printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\
-\
- NM_FIX_PORT;\
-\
- addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
- func (value, addr);\
- return 0;\
-}
-
-DEFwritePortX (8, writeb)
-DEFwritePortX (16, writew)
-DEFwritePortX (32, writel)
-
-#define DEFreadPortX(X, func) \
-static inline u##X nm256_readPort##X (struct nm256_info *card,\
- int port, int offset)\
-{\
- u##X __iomem *addr;\
-\
- NM_FIX_PORT\
-\
- addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
- return func(addr);\
-}
-
-DEFreadPortX (8, readb)
-DEFreadPortX (16, readw)
-DEFreadPortX (32, readl)
-
-static inline int
-nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset,
- int amt)
-{
- NM_FIX_PORT;
- memcpy_toio (card->port[port - 1].ptr + offset, src, amt);
- return 0;
-}
-
-static inline int
-nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset,
- int amt)
-{
- NM_FIX_PORT;
- memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt);
- return 0;
-}
-
-/* Returns a non-zero value if we should use the coefficient cache. */
-static int nm256_cachedCoefficients (struct nm256_info *card);
-
-#endif
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
deleted file mode 100644
index 44cd15505001..000000000000
--- a/sound/oss/nm256_audio.c
+++ /dev/null
@@ -1,1662 +0,0 @@
-/*
- * Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
- * mode, with AC97 mixer support.
- *
- * Overall design and parts of this code stolen from vidc_*.c and
- * skeleton.c.
- *
- * Yeah, there are a lot of magic constants in here. You tell ME what
- * they are. I just get this stuff psychically, remember?
- *
- * This driver was written by someone who wishes to remain anonymous.
- * It is in the public domain, so share and enjoy. Try to make a profit
- * off of it; go on, I dare you.
- *
- * Changes:
- * 11-10-2000 Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
- * Added some __init
- * 19-04-2001 Marcus Meissner <mm@caldera.de>
- * Ported to 2.4 PCI API.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include "sound_config.h"
-
-static int nm256_debug;
-static int force_load;
-
-#include "nm256.h"
-#include "nm256_coeff.h"
-
-/*
- * The size of the playback reserve. When the playback buffer has less
- * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
- * buffer.
- */
-#define NM256_PLAY_WMARK_SIZE 512
-
-static struct audio_driver nm256_audio_driver;
-
-static int nm256_grabInterrupt (struct nm256_info *card);
-static int nm256_releaseInterrupt (struct nm256_info *card);
-static irqreturn_t nm256_interrupt (int irq, void *dev_id);
-static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id);
-
-/* These belong in linux/pci.h. */
-#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
-#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
-#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-
-/* List of cards. */
-static struct nm256_info *nmcard_list;
-
-/* Release the mapped-in memory for CARD. */
-static void
-nm256_release_ports (struct nm256_info *card)
-{
- int x;
-
- for (x = 0; x < 2; x++) {
- if (card->port[x].ptr != NULL) {
- iounmap (card->port[x].ptr);
- card->port[x].ptr = NULL;
- }
- }
-}
-
-/*
- * Map in the memory ports for CARD, if they aren't already mapped in
- * and have been configured. If successful, a zero value is returned;
- * otherwise any previously mapped-in areas are released and a non-zero
- * value is returned.
- *
- * This is invoked twice, once for each port. Ideally it would only be
- * called once, but we now need to map in the second port in order to
- * check how much memory the card has on the 256ZX.
- */
-static int
-nm256_remap_ports (struct nm256_info *card)
-{
- int x;
-
- for (x = 0; x < 2; x++) {
- if (card->port[x].ptr == NULL && card->port[x].end_offset > 0) {
- u32 physaddr
- = card->port[x].physaddr + card->port[x].start_offset;
- u32 size
- = card->port[x].end_offset - card->port[x].start_offset;
-
- card->port[x].ptr = ioremap_nocache (physaddr, size);
-
- if (card->port[x].ptr == NULL) {
- printk (KERN_ERR "NM256: Unable to remap port %d\n", x + 1);
- nm256_release_ports (card);
- return -1;
- }
- }
- }
- return 0;
-}
-
-/* Locate the card in our list. */
-static struct nm256_info *
-nm256_find_card (int dev)
-{
- struct nm256_info *card;
-
- for (card = nmcard_list; card != NULL; card = card->next_card)
- if (card->dev[0] == dev || card->dev[1] == dev)
- return card;
-
- return NULL;
-}
-
-/*
- * Ditto, but find the card struct corresponding to the mixer device DEV
- * instead.
- */
-static struct nm256_info *
-nm256_find_card_for_mixer (int dev)
-{
- struct nm256_info *card;
-
- for (card = nmcard_list; card != NULL; card = card->next_card)
- if (card->mixer_oss_dev == dev)
- return card;
-
- return NULL;
-}
-
-static int usecache;
-static int buffertop;
-
-/* Check to see if we're using the bank of cached coefficients. */
-static int
-nm256_cachedCoefficients (struct nm256_info *card)
-{
- return usecache;
-}
-
-/* The actual rates supported by the card. */
-static int samplerates[9] = {
- 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
-};
-
-/*
- * Set the card samplerate, word size and stereo mode to correspond to
- * the settings in the CARD struct for the specified device in DEV.
- * We keep two separate sets of information, one for each device; the
- * hardware is not actually configured until a read or write is
- * attempted.
- */
-
-static int
-nm256_setInfo (int dev, struct nm256_info *card)
-{
- int x;
- int w;
- int targetrate;
-
- if (card->dev[0] == dev)
- w = 0;
- else if (card->dev[1] == dev)
- w = 1;
- else
- return -ENODEV;
-
- targetrate = card->sinfo[w].samplerate;
-
- if ((card->sinfo[w].bits != 8 && card->sinfo[w].bits != 16)
- || targetrate < samplerates[0]
- || targetrate > samplerates[7])
- return -EINVAL;
-
- for (x = 0; x < 8; x++)
- if (targetrate < ((samplerates[x] + samplerates[x + 1]) / 2))
- break;
-
- if (x < 8) {
- u8 ratebits = ((x << 4) & NM_RATE_MASK);
- if (card->sinfo[w].bits == 16)
- ratebits |= NM_RATE_BITS_16;
- if (card->sinfo[w].stereo)
- ratebits |= NM_RATE_STEREO;
-
- card->sinfo[w].samplerate = samplerates[x];
-
-
- if (card->dev_for_play == dev && card->playing) {
- if (nm256_debug)
- printk (KERN_DEBUG "Setting play ratebits to 0x%x\n",
- ratebits);
- nm256_loadCoefficient (card, 0, x);
- nm256_writePort8 (card, 2,
- NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
- ratebits);
- }
-
- if (card->dev_for_record == dev && card->recording) {
- if (nm256_debug)
- printk (KERN_DEBUG "Setting record ratebits to 0x%x\n",
- ratebits);
- nm256_loadCoefficient (card, 1, x);
- nm256_writePort8 (card, 2,
- NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
- ratebits);
- }
- return 0;
- }
- else
- return -EINVAL;
-}
-
-/* Start the play process going. */
-static void
-startPlay (struct nm256_info *card)
-{
- if (! card->playing) {
- card->playing = 1;
- if (nm256_grabInterrupt (card) == 0) {
- nm256_setInfo (card->dev_for_play, card);
-
- /* Enable playback engine and interrupts. */
- nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG,
- NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
-
- /* Enable both channels. */
- nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, 0x0);
- }
- }
-}
-
-/*
- * Request one chunk of AMT bytes from the recording device. When the
- * operation is complete, the data will be copied into BUFFER and the
- * function DMAbuf_inputintr will be invoked.
- */
-
-static void
-nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
-{
- u32 endpos;
- int enableEngine = 0;
- u32 ringsize = card->recordBufferSize;
- unsigned long flags;
-
- if (amt > (ringsize / 2)) {
- /*
- * Of course this won't actually work right, because the
- * caller is going to assume we will give what we got asked
- * for.
- */
- printk (KERN_ERR "NM256: Read request too large: %d\n", amt);
- amt = ringsize / 2;
- }
-
- if (amt < 8) {
- printk (KERN_ERR "NM256: Read request too small; %d\n", amt);
- return;
- }
-
- spin_lock_irqsave(&card->lock,flags);
- /*
- * If we're not currently recording, set up the start and end registers
- * for the recording engine.
- */
- if (! card->recording) {
- card->recording = 1;
- if (nm256_grabInterrupt (card) == 0) {
- card->curRecPos = 0;
- nm256_setInfo (card->dev_for_record, card);
- nm256_writePort32 (card, 2, NM_RBUFFER_START, card->abuf2);
- nm256_writePort32 (card, 2, NM_RBUFFER_END,
- card->abuf2 + ringsize);
-
- nm256_writePort32 (card, 2, NM_RBUFFER_CURRP,
- card->abuf2 + card->curRecPos);
- enableEngine = 1;
- }
- else {
- /* Not sure what else to do here. */
- spin_unlock_irqrestore(&card->lock,flags);
- return;
- }
- }
-
- /*
- * If we happen to go past the end of the buffer a bit (due to a
- * delayed interrupt) it's OK. So might as well set the watermark
- * right at the end of the data we want.
- */
- endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize);
-
- card->recBuf = buffer;
- card->requestedRecAmt = amt;
- nm256_writePort32 (card, 2, NM_RBUFFER_WMARK, endpos);
- /* Enable recording engine and interrupts. */
- if (enableEngine)
- nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG,
- NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN);
-
- spin_unlock_irqrestore(&card->lock,flags);
-}
-
-/* Stop the play engine. */
-static void
-stopPlay (struct nm256_info *card)
-{
- /* Shut off sound from both channels. */
- nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG,
- NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
- /* Disable play engine. */
- nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, 0);
- if (card->playing) {
- nm256_releaseInterrupt (card);
-
- /* Reset the relevant state bits. */
- card->playing = 0;
- card->curPlayPos = 0;
- }
-}
-
-/* Stop recording. */
-static void
-stopRecord (struct nm256_info *card)
-{
- /* Disable recording engine. */
- nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, 0);
-
- if (card->recording) {
- nm256_releaseInterrupt (card);
-
- card->recording = 0;
- card->curRecPos = 0;
- }
-}
-
-/*
- * Ring buffers, man. That's where the hip-hop, wild-n-wooly action's at.
- * 1972? (Well, I suppose it was cheep-n-easy to implement.)
- *
- * Write AMT bytes of BUFFER to the playback ring buffer, and start the
- * playback engine running. It will only accept up to 1/2 of the total
- * size of the ring buffer. No check is made that we're about to overwrite
- * the currently-playing sample.
- */
-
-static void
-nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
-{
- u32 ringsize = card->playbackBufferSize;
- u32 endstop;
- unsigned long flags;
-
- if (amt > (ringsize / 2)) {
- printk (KERN_ERR "NM256: Write request too large: %d\n", amt);
- amt = (ringsize / 2);
- }
-
- if (amt < NM256_PLAY_WMARK_SIZE) {
- printk (KERN_ERR "NM256: Write request too small: %d\n", amt);
- return;
- }
-
- card->curPlayPos %= ringsize;
-
- card->requested_amt = amt;
-
- spin_lock_irqsave(&card->lock,flags);
-
- if ((card->curPlayPos + amt) >= ringsize) {
- u32 rem = ringsize - card->curPlayPos;
-
- nm256_writeBuffer8 (card, buffer, 1,
- card->abuf1 + card->curPlayPos,
- rem);
- if (amt > rem)
- nm256_writeBuffer8 (card, buffer + rem, 1, card->abuf1,
- amt - rem);
- }
- else
- nm256_writeBuffer8 (card, buffer, 1,
- card->abuf1 + card->curPlayPos,
- amt);
-
- /*
- * Setup the start-n-stop-n-limit registers, and start that engine
- * goin'.
- *
- * Normally we just let it wrap around to avoid the click-click
- * action scene.
- */
- if (! card->playing) {
- /* The PBUFFER_END register in this case points to one sample
- before the end of the buffer. */
- int w = (card->dev_for_play == card->dev[0] ? 0 : 1);
- int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1);
-
- if (card->sinfo[w].stereo)
- sampsize *= 2;
-
- /* Need to set the not-normally-changing-registers up. */
- nm256_writePort32 (card, 2, NM_PBUFFER_START,
- card->abuf1 + card->curPlayPos);
- nm256_writePort32 (card, 2, NM_PBUFFER_END,
- card->abuf1 + ringsize - sampsize);
- nm256_writePort32 (card, 2, NM_PBUFFER_CURRP,
- card->abuf1 + card->curPlayPos);
- }
- endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize;
- nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
-
- if (! card->playing)
- startPlay (card);
-
- spin_unlock_irqrestore(&card->lock,flags);
-}
-
-/* We just got a card playback interrupt; process it. */
-static void
-nm256_get_new_block (struct nm256_info *card)
-{
- /* Check to see how much got played so far. */
- u32 amt = nm256_readPort32 (card, 2, NM_PBUFFER_CURRP) - card->abuf1;
-
- if (amt >= card->playbackBufferSize) {
- printk (KERN_ERR "NM256: Sound playback pointer invalid!\n");
- amt = 0;
- }
-
- if (amt < card->curPlayPos)
- amt = (card->playbackBufferSize - card->curPlayPos) + amt;
- else
- amt -= card->curPlayPos;
-
- if (card->requested_amt > (amt + NM256_PLAY_WMARK_SIZE)) {
- u32 endstop =
- card->curPlayPos + card->requested_amt - NM256_PLAY_WMARK_SIZE;
- nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
- }
- else {
- card->curPlayPos += card->requested_amt;
- /* Get a new block to write. This will eventually invoke
- nm256_write_block () or stopPlay (). */
- DMAbuf_outputintr (card->dev_for_play, 1);
- }
-}
-
-/*
- * Read the last-recorded block from the ring buffer, copy it into the
- * saved buffer pointer, and invoke DMAuf_inputintr() with the recording
- * device.
- */
-
-static void
-nm256_read_block (struct nm256_info *card)
-{
- /* Grab the current position of the recording pointer. */
- u32 currptr = nm256_readPort32 (card, 2, NM_RBUFFER_CURRP) - card->abuf2;
- u32 amtToRead = card->requestedRecAmt;
- u32 ringsize = card->recordBufferSize;
-
- if (currptr >= card->recordBufferSize) {
- printk (KERN_ERR "NM256: Sound buffer record pointer invalid!\n");
- currptr = 0;
- }
-
- /*
- * This test is probably redundant; we shouldn't be here unless
- * it's true.
- */
- if (card->recording) {
- /* If we wrapped around, copy everything from the start of our
- recording buffer to the end of the buffer. */
- if (currptr < card->curRecPos) {
- u32 amt = min (ringsize - card->curRecPos, amtToRead);
-
- nm256_readBuffer8 (card, card->recBuf, 1,
- card->abuf2 + card->curRecPos,
- amt);
- amtToRead -= amt;
- card->curRecPos += amt;
- card->recBuf += amt;
- if (card->curRecPos == ringsize)
- card->curRecPos = 0;
- }
-
- if ((card->curRecPos < currptr) && (amtToRead > 0)) {
- u32 amt = min (currptr - card->curRecPos, amtToRead);
- nm256_readBuffer8 (card, card->recBuf, 1,
- card->abuf2 + card->curRecPos, amt);
- card->curRecPos = ((card->curRecPos + amt) % ringsize);
- }
- card->recBuf = NULL;
- card->requestedRecAmt = 0;
- DMAbuf_inputintr (card->dev_for_record);
- }
-}
-
-/*
- * Initialize the hardware.
- */
-static void
-nm256_initHw (struct nm256_info *card)
-{
- /* Reset everything. */
- nm256_writePort8 (card, 2, 0x0, 0x11);
- nm256_writePort16 (card, 2, 0x214, 0);
-
- stopRecord (card);
- stopPlay (card);
-}
-
-/*
- * Handle a potential interrupt for the device referred to by DEV_ID.
- *
- * I don't like the cut-n-paste job here either between the two routines,
- * but there are sufficient differences between the two interrupt handlers
- * that parameterizing it isn't all that great either. (Could use a macro,
- * I suppose...yucky bleah.)
- */
-
-static irqreturn_t
-nm256_interrupt (int irq, void *dev_id)
-{
- struct nm256_info *card = (struct nm256_info *)dev_id;
- u16 status;
- static int badintrcount;
- int handled = 0;
-
- if ((card == NULL) || (card->magsig != NM_MAGIC_SIG)) {
- printk (KERN_ERR "NM256: Bad card pointer\n");
- return IRQ_NONE;
- }
-
- status = nm256_readPort16 (card, 2, NM_INT_REG);
-
- /* Not ours. */
- if (status == 0) {
- if (badintrcount++ > 1000) {
- /*
- * I'm not sure if the best thing is to stop the card from
- * playing or just release the interrupt (after all, we're in
- * a bad situation, so doing fancy stuff may not be such a good
- * idea).
- *
- * I worry about the card engine continuing to play noise
- * over and over, however--that could become a very
- * obnoxious problem. And we know that when this usually
- * happens things are fairly safe, it just means the user's
- * inserted a PCMCIA card and someone's spamming us with IRQ 9s.
- */
-
- handled = 1;
- if (card->playing)
- stopPlay (card);
- if (card->recording)
- stopRecord (card);
- badintrcount = 0;
- }
- return IRQ_RETVAL(handled);
- }
-
- badintrcount = 0;
-
- /* Rather boring; check for individual interrupts and process them. */
-
- if (status & NM_PLAYBACK_INT) {
- handled = 1;
- status &= ~NM_PLAYBACK_INT;
- NM_ACK_INT (card, NM_PLAYBACK_INT);
-
- if (card->playing)
- nm256_get_new_block (card);
- }
-
- if (status & NM_RECORD_INT) {
- handled = 1;
- status &= ~NM_RECORD_INT;
- NM_ACK_INT (card, NM_RECORD_INT);
-
- if (card->recording)
- nm256_read_block (card);
- }
-
- if (status & NM_MISC_INT_1) {
- u8 cbyte;
-
- handled = 1;
- status &= ~NM_MISC_INT_1;
- printk (KERN_ERR "NM256: Got misc interrupt #1\n");
- NM_ACK_INT (card, NM_MISC_INT_1);
- nm256_writePort16 (card, 2, NM_INT_REG, 0x8000);
- cbyte = nm256_readPort8 (card, 2, 0x400);
- nm256_writePort8 (card, 2, 0x400, cbyte | 2);
- }
-
- if (status & NM_MISC_INT_2) {
- u8 cbyte;
-
- handled = 1;
- status &= ~NM_MISC_INT_2;
- printk (KERN_ERR "NM256: Got misc interrupt #2\n");
- NM_ACK_INT (card, NM_MISC_INT_2);
- cbyte = nm256_readPort8 (card, 2, 0x400);
- nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
- }
-
- /* Unknown interrupt. */
- if (status) {
- handled = 1;
- printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
- status);
- /* Pray. */
- NM_ACK_INT (card, status);
- }
- return IRQ_RETVAL(handled);
-}
-
-/*
- * Handle a potential interrupt for the device referred to by DEV_ID.
- * This handler is for the 256ZX, and is very similar to the non-ZX
- * routine.
- */
-
-static irqreturn_t
-nm256_interrupt_zx (int irq, void *dev_id)
-{
- struct nm256_info *card = (struct nm256_info *)dev_id;
- u32 status;
- static int badintrcount;
- int handled = 0;
-
- if ((card == NULL) || (card->magsig != NM_MAGIC_SIG)) {
- printk (KERN_ERR "NM256: Bad card pointer\n");
- return IRQ_NONE;
- }
-
- status = nm256_readPort32 (card, 2, NM_INT_REG);
-
- /* Not ours. */
- if (status == 0) {
- if (badintrcount++ > 1000) {
- printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
- /*
- * I'm not sure if the best thing is to stop the card from
- * playing or just release the interrupt (after all, we're in
- * a bad situation, so doing fancy stuff may not be such a good
- * idea).
- *
- * I worry about the card engine continuing to play noise
- * over and over, however--that could become a very
- * obnoxious problem. And we know that when this usually
- * happens things are fairly safe, it just means the user's
- * inserted a PCMCIA card and someone's spamming us with
- * IRQ 9s.
- */
-
- handled = 1;
- if (card->playing)
- stopPlay (card);
- if (card->recording)
- stopRecord (card);
- badintrcount = 0;
- }
- return IRQ_RETVAL(handled);
- }
-
- badintrcount = 0;
-
- /* Rather boring; check for individual interrupts and process them. */
-
- if (status & NM2_PLAYBACK_INT) {
- handled = 1;
- status &= ~NM2_PLAYBACK_INT;
- NM2_ACK_INT (card, NM2_PLAYBACK_INT);
-
- if (card->playing)
- nm256_get_new_block (card);
- }
-
- if (status & NM2_RECORD_INT) {
- handled = 1;
- status &= ~NM2_RECORD_INT;
- NM2_ACK_INT (card, NM2_RECORD_INT);
-
- if (card->recording)
- nm256_read_block (card);
- }
-
- if (status & NM2_MISC_INT_1) {
- u8 cbyte;
-
- handled = 1;
- status &= ~NM2_MISC_INT_1;
- printk (KERN_ERR "NM256: Got misc interrupt #1\n");
- NM2_ACK_INT (card, NM2_MISC_INT_1);
- cbyte = nm256_readPort8 (card, 2, 0x400);
- nm256_writePort8 (card, 2, 0x400, cbyte | 2);
- }
-
- if (status & NM2_MISC_INT_2) {
- u8 cbyte;
-
- handled = 1;
- status &= ~NM2_MISC_INT_2;
- printk (KERN_ERR "NM256: Got misc interrupt #2\n");
- NM2_ACK_INT (card, NM2_MISC_INT_2);
- cbyte = nm256_readPort8 (card, 2, 0x400);
- nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
- }
-
- /* Unknown interrupt. */
- if (status) {
- handled = 1;
- printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
- status);
- /* Pray. */
- NM2_ACK_INT (card, status);
- }
- return IRQ_RETVAL(handled);
-}
-
-/*
- * Request our interrupt.
- */
-static int
-nm256_grabInterrupt (struct nm256_info *card)
-{
- if (card->has_irq++ == 0) {
- if (request_irq (card->irq, card->introutine, IRQF_SHARED,
- "NM256_audio", card) < 0) {
- printk (KERN_ERR "NM256: can't obtain IRQ %d\n", card->irq);
- return -1;
- }
- }
- return 0;
-}
-
-/*
- * Release our interrupt.
- */
-static int
-nm256_releaseInterrupt (struct nm256_info *card)
-{
- if (card->has_irq <= 0) {
- printk (KERN_ERR "nm256: too many calls to releaseInterrupt\n");
- return -1;
- }
- card->has_irq--;
- if (card->has_irq == 0) {
- free_irq (card->irq, card);
- }
- return 0;
-}
-
-/*
- * Waits for the mixer to become ready to be written; returns a zero value
- * if it timed out.
- */
-
-static int
-nm256_isReady (struct ac97_hwint *dev)
-{
- struct nm256_info *card = (struct nm256_info *)dev->driver_private;
- int t2 = 10;
- u32 testaddr;
- u16 testb;
- int done = 0;
-
- if (card->magsig != NM_MAGIC_SIG) {
- printk (KERN_ERR "NM256: Bad magic signature in isReady!\n");
- return 0;
- }
-
- testaddr = card->mixer_status_offset;
- testb = card->mixer_status_mask;
-
- /*
- * Loop around waiting for the mixer to become ready.
- */
- while (! done && t2-- > 0) {
- if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0)
- done = 1;
- else
- udelay (100);
- }
- return done;
-}
-
-/*
- * Return the contents of the AC97 mixer register REG. Returns a positive
- * value if successful, or a negative error code.
- */
-static int
-nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
-{
- struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-
- if (card->magsig != NM_MAGIC_SIG) {
- printk (KERN_ERR "NM256: Bad magic signature in readAC97Reg!\n");
- return -EINVAL;
- }
-
- if (reg < 128) {
- int res;
-
- nm256_isReady (dev);
- res = nm256_readPort16 (card, 2, card->mixer + reg);
- /* Magic delay. Bleah yucky. */
- udelay (1000);
- return res;
- }
- else
- return -EINVAL;
-}
-
-/*
- * Writes VALUE to AC97 mixer register REG. Returns 0 if successful, or
- * a negative error code.
- */
-static int
-nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value)
-{
- unsigned long flags;
- int tries = 2;
- int done = 0;
- u32 base;
-
- struct nm256_info *card = (struct nm256_info *)dev->driver_private;
-
- if (card->magsig != NM_MAGIC_SIG) {
- printk (KERN_ERR "NM256: Bad magic signature in writeAC97Reg!\n");
- return -EINVAL;
- }
-
- base = card->mixer;
-
- spin_lock_irqsave(&card->lock,flags);
-
- nm256_isReady (dev);
-
- /* Wait for the write to take, too. */
- while ((tries-- > 0) && !done) {
- nm256_writePort16 (card, 2, base + reg, value);
- if (nm256_isReady (dev)) {
- done = 1;
- break;
- }
-
- }
-
- spin_unlock_irqrestore(&card->lock,flags);
- udelay (1000);
-
- return ! done;
-}
-
-/*
- * Initial register values to be written to the AC97 mixer.
- * While most of these are identical to the reset values, we do this
- * so that we have most of the register contents cached--this avoids
- * reading from the mixer directly (which seems to be problematic,
- * probably due to ignorance).
- */
-struct initialValues
-{
- unsigned short port;
- unsigned short value;
-};
-
-static struct initialValues nm256_ac97_initial_values[] =
-{
- { AC97_MASTER_VOL_STEREO, 0x8000 },
- { AC97_HEADPHONE_VOL, 0x8000 },
- { AC97_MASTER_VOL_MONO, 0x0000 },
- { AC97_PCBEEP_VOL, 0x0000 },
- { AC97_PHONE_VOL, 0x0008 },
- { AC97_MIC_VOL, 0x8000 },
- { AC97_LINEIN_VOL, 0x8808 },
- { AC97_CD_VOL, 0x8808 },
- { AC97_VIDEO_VOL, 0x8808 },
- { AC97_AUX_VOL, 0x8808 },
- { AC97_PCMOUT_VOL, 0x0808 },
- { AC97_RECORD_SELECT, 0x0000 },
- { AC97_RECORD_GAIN, 0x0B0B },
- { AC97_GENERAL_PURPOSE, 0x0000 },
- { 0xffff, 0xffff }
-};
-
-/* Initialize the AC97 into a known state. */
-static int
-nm256_resetAC97 (struct ac97_hwint *dev)
-{
- struct nm256_info *card = (struct nm256_info *)dev->driver_private;
- int x;
-
- if (card->magsig != NM_MAGIC_SIG) {
- printk (KERN_ERR "NM256: Bad magic signature in resetAC97!\n");
- return -EINVAL;
- }
-
- /* Reset the mixer. 'Tis magic! */
- nm256_writePort8 (card, 2, 0x6c0, 1);
-// nm256_writePort8 (card, 2, 0x6cc, 0x87); /* This crashes Dell latitudes */
- nm256_writePort8 (card, 2, 0x6cc, 0x80);
- nm256_writePort8 (card, 2, 0x6cc, 0x0);
-
- if (! card->mixer_values_init) {
- for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
- ac97_put_register (dev,
- nm256_ac97_initial_values[x].port,
- nm256_ac97_initial_values[x].value);
- card->mixer_values_init = 1;
- }
- }
-
- return 0;
-}
-
-/*
- * We don't do anything particularly special here; it just passes the
- * mixer ioctl to the AC97 driver.
- */
-static int
-nm256_default_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
-{
- struct nm256_info *card = nm256_find_card_for_mixer (dev);
- if (card != NULL)
- return ac97_mixer_ioctl (&(card->mdev), cmd, arg);
- else
- return -ENODEV;
-}
-
-static struct mixer_operations nm256_mixer_operations = {
- .owner = THIS_MODULE,
- .id = "NeoMagic",
- .name = "NM256AC97Mixer",
- .ioctl = nm256_default_mixer_ioctl
-};
-
-/*
- * Default settings for the OSS mixer. These are set last, after the
- * mixer is initialized.
- *
- * I "love" C sometimes. Got braces?
- */
-static struct ac97_mixer_value_list mixer_defaults[] = {
- { SOUND_MIXER_VOLUME, { { 85, 85 } } },
- { SOUND_MIXER_SPEAKER, { { 100 } } },
- { SOUND_MIXER_PCM, { { 65, 65 } } },
- { SOUND_MIXER_CD, { { 65, 65 } } },
- { -1, { { 0, 0 } } }
-};
-
-
-/* Installs the AC97 mixer into CARD. */
-static int __devinit
-nm256_install_mixer (struct nm256_info *card)
-{
- int mixer;
-
- card->mdev.reset_device = nm256_resetAC97;
- card->mdev.read_reg = nm256_readAC97Reg;
- card->mdev.write_reg = nm256_writeAC97Reg;
- card->mdev.driver_private = (void *)card;
-
- if (ac97_init (&(card->mdev)))
- return -1;
-
- mixer = sound_alloc_mixerdev();
- if (num_mixers >= MAX_MIXER_DEV) {
- printk ("NM256 mixer: Unable to alloc mixerdev\n");
- return -1;
- }
-
- mixer_devs[mixer] = &nm256_mixer_operations;
- card->mixer_oss_dev = mixer;
-
- /* Some reasonable default values. */
- ac97_set_values (&(card->mdev), mixer_defaults);
-
- printk(KERN_INFO "Initialized AC97 mixer\n");
- return 0;
-}
-
-/*
- * See if the signature left by the NM256 BIOS is intact; if so, we use
- * the associated address as the end of our audio buffer in the video
- * RAM.
- */
-
-static void __devinit
-nm256_peek_for_sig (struct nm256_info *card)
-{
- u32 port1offset
- = card->port[0].physaddr + card->port[0].end_offset - 0x0400;
- /* The signature is located 1K below the end of video RAM. */
- char __iomem *temp = ioremap_nocache (port1offset, 16);
- /* Default buffer end is 5120 bytes below the top of RAM. */
- u32 default_value = card->port[0].end_offset - 0x1400;
- u32 sig;
-
- /* Install the default value first, so we don't have to repeatedly
- do it if there is a problem. */
- card->port[0].end_offset = default_value;
-
- if (temp == NULL) {
- printk (KERN_ERR "NM256: Unable to scan for card signature in video RAM\n");
- return;
- }
- sig = readl (temp);
- if ((sig & NM_SIG_MASK) == NM_SIGNATURE) {
- u32 pointer = readl (temp + 4);
-
- /*
- * If it's obviously invalid, don't use it (the port already has a
- * suitable default value set).
- */
- if (pointer != 0xffffffff)
- card->port[0].end_offset = pointer;
-
- printk (KERN_INFO "NM256: Found card signature in video RAM: 0x%x\n",
- pointer);
- }
-
- iounmap (temp);
-}
-
-/*
- * Install a driver for the PCI device referenced by PCIDEV.
- * VERSTR is a human-readable version string.
- */
-
-static int __devinit
-nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
-{
- struct nm256_info *card;
- int x;
-
- if (pci_enable_device(pcidev))
- return 0;
-
- card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
- if (card == NULL) {
- printk (KERN_ERR "NM256: out of memory!\n");
- return 0;
- }
-
- card->magsig = NM_MAGIC_SIG;
- card->playing = 0;
- card->recording = 0;
- card->rev = rev;
- spin_lock_init(&card->lock);
-
- /* Init the memory port info. */
- for (x = 0; x < 2; x++) {
- card->port[x].physaddr = pci_resource_start (pcidev, x);
- card->port[x].ptr = NULL;
- card->port[x].start_offset = 0;
- card->port[x].end_offset = 0;
- }
-
- /* Port 2 is easy. */
- card->port[1].start_offset = 0;
- card->port[1].end_offset = NM_PORT2_SIZE;
-
- /* Yuck. But we have to map in port 2 so we can check how much RAM the
- card has. */
- if (nm256_remap_ports (card)) {
- kfree (card);
- return 0;
- }
-
- /*
- * The NM256 has two memory ports. The first port is nothing
- * more than a chunk of video RAM, which is used as the I/O ring
- * buffer. The second port has the actual juicy stuff (like the
- * mixer and the playback engine control registers).
- */
-
- if (card->rev == REV_NM256AV) {
- /* Ok, try to see if this is a non-AC97 version of the hardware. */
- int pval = nm256_readPort16 (card, 2, NM_MIXER_PRESENCE);
- if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
- if (! force_load) {
- printk (KERN_ERR "NM256: This doesn't look to me like the AC97-compatible version.\n");
- printk (KERN_ERR " You can force the driver to load by passing in the module\n");
- printk (KERN_ERR " parameter:\n");
- printk (KERN_ERR " force_load = 1\n");
- printk (KERN_ERR "\n");
- printk (KERN_ERR " More likely, you should be using the appropriate SB-16 or\n");
- printk (KERN_ERR " CS4232 driver instead. (If your BIOS has settings for\n");
- printk (KERN_ERR " IRQ and/or DMA for the sound card, this is *not* the correct\n");
- printk (KERN_ERR " driver to use.)\n");
- nm256_release_ports (card);
- kfree (card);
- return 0;
- }
- else {
- printk (KERN_INFO "NM256: Forcing driver load as per user request.\n");
- }
- }
- else {
- /* printk (KERN_INFO "NM256: Congratulations. You're not running Eunice.\n")*/;
- }
- card->port[0].end_offset = 2560 * 1024;
- card->introutine = nm256_interrupt;
- card->mixer_status_offset = NM_MIXER_STATUS_OFFSET;
- card->mixer_status_mask = NM_MIXER_READY_MASK;
- }
- else {
- /* Not sure if there is any relevant detect for the ZX or not. */
- if (nm256_readPort8 (card, 2, 0xa0b) != 0)
- card->port[0].end_offset = 6144 * 1024;
- else
- card->port[0].end_offset = 4096 * 1024;
-
- card->introutine = nm256_interrupt_zx;
- card->mixer_status_offset = NM2_MIXER_STATUS_OFFSET;
- card->mixer_status_mask = NM2_MIXER_READY_MASK;
- }
-
- if (buffertop >= 98304 && buffertop < card->port[0].end_offset)
- card->port[0].end_offset = buffertop;
- else
- nm256_peek_for_sig (card);
-
- card->port[0].start_offset = card->port[0].end_offset - 98304;
-
- printk (KERN_INFO "NM256: Mapping port 1 from 0x%x - 0x%x\n",
- card->port[0].start_offset, card->port[0].end_offset);
-
- if (nm256_remap_ports (card)) {
- kfree (card);
- return 0;
- }
-
- /* See if we can get the interrupt. */
-
- card->irq = pcidev->irq;
- card->has_irq = 0;
-
- if (nm256_grabInterrupt (card) != 0) {
- nm256_release_ports (card);
- kfree (card);
- return 0;
- }
-
- nm256_releaseInterrupt (card);
-
- /*
- * Init the board.
- */
-
- card->playbackBufferSize = 16384;
- card->recordBufferSize = 16384;
-
- card->coeffBuf = card->port[0].end_offset - NM_MAX_COEFFICIENT;
- card->abuf2 = card->coeffBuf - card->recordBufferSize;
- card->abuf1 = card->abuf2 - card->playbackBufferSize;
- card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
-
- /* Fixed setting. */
- card->mixer = NM_MIXER_OFFSET;
- card->mixer_values_init = 0;
-
- card->is_open_play = 0;
- card->is_open_record = 0;
-
- card->coeffsCurrent = 0;
-
- card->opencnt[0] = 0; card->opencnt[1] = 0;
-
- /* Reasonable default settings, but largely unnecessary. */
- for (x = 0; x < 2; x++) {
- card->sinfo[x].bits = 8;
- card->sinfo[x].stereo = 0;
- card->sinfo[x].samplerate = 8000;
- }
-
- nm256_initHw (card);
-
- for (x = 0; x < 2; x++) {
- if ((card->dev[x] =
- sound_install_audiodrv(AUDIO_DRIVER_VERSION,
- "NM256", &nm256_audio_driver,
- sizeof(struct audio_driver),
- DMA_NODMA, AFMT_U8 | AFMT_S16_LE,
- NULL, -1, -1)) >= 0) {
- /* 1K minimum buffer size. */
- audio_devs[card->dev[x]]->min_fragment = 10;
- /* Maximum of 8K buffer size. */
- audio_devs[card->dev[x]]->max_fragment = 13;
- }
- else {
- printk(KERN_ERR "NM256: Too many PCM devices available\n");
- nm256_release_ports (card);
- kfree (card);
- return 0;
- }
- }
-
- pci_set_drvdata(pcidev,card);
-
- /* Insert the card in the list. */
- card->next_card = nmcard_list;
- nmcard_list = card;
-
- printk(KERN_INFO "Initialized NeoMagic %s audio in PCI native mode\n",
- verstr);
-
- /*
- * And our mixer. (We should allow support for other mixers, maybe.)
- */
-
- nm256_install_mixer (card);
-
- return 1;
-}
-
-
-static int __devinit
-nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid)
-{
- if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO)
- return nm256_install(pcidev, REV_NM256AV, "256AV");
- if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO)
- return nm256_install(pcidev, REV_NM256ZX, "256ZX");
- if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO)
- return nm256_install(pcidev, REV_NM256ZX, "256XL+");
- return -1; /* should not come here ... */
-}
-
-static void __devinit
-nm256_remove(struct pci_dev *pcidev) {
- struct nm256_info *xcard = pci_get_drvdata(pcidev);
- struct nm256_info *card,*next_card = NULL;
-
- for (card = nmcard_list; card != NULL; card = next_card) {
- next_card = card->next_card;
- if (card == xcard) {
- stopPlay (card);
- stopRecord (card);
- if (card->has_irq)
- free_irq (card->irq, card);
- nm256_release_ports (card);
- sound_unload_mixerdev (card->mixer_oss_dev);
- sound_unload_audiodev (card->dev[0]);
- sound_unload_audiodev (card->dev[1]);
- kfree (card);
- break;
- }
- }
- if (nmcard_list == card)
- nmcard_list = next_card;
-}
-
-/*
- * Open the device
- *
- * DEV - device
- * MODE - mode to open device (logical OR of OPEN_READ and OPEN_WRITE)
- *
- * Called when opening the DMAbuf (dmabuf.c:259)
- */
-static int
-nm256_audio_open(int dev, int mode)
-{
- struct nm256_info *card = nm256_find_card (dev);
- int w;
-
- if (card == NULL)
- return -ENODEV;
-
- if (card->dev[0] == dev)
- w = 0;
- else if (card->dev[1] == dev)
- w = 1;
- else
- return -ENODEV;
-
- if (card->opencnt[w] > 0)
- return -EBUSY;
-
- /* No bits set? Huh? */
- if (! ((mode & OPEN_READ) || (mode & OPEN_WRITE)))
- return -EIO;
-
- /*
- * If it's open for both read and write, and the card's currently
- * being read or written to, then do the opposite of what has
- * already been done. Otherwise, don't specify any mode until the
- * user actually tries to do I/O. (Some programs open the device
- * for both read and write, but only actually do reading or writing.)
- */
-
- if ((mode & OPEN_WRITE) && (mode & OPEN_READ)) {
- if (card->is_open_play)
- mode = OPEN_WRITE;
- else if (card->is_open_record)
- mode = OPEN_READ;
- else mode = 0;
- }
-
- if (mode & OPEN_WRITE) {
- if (card->is_open_play == 0) {
- card->dev_for_play = dev;
- card->is_open_play = 1;
- }
- else
- return -EBUSY;
- }
-
- if (mode & OPEN_READ) {
- if (card->is_open_record == 0) {
- card->dev_for_record = dev;
- card->is_open_record = 1;
- }
- else
- return -EBUSY;
- }
-
- card->opencnt[w]++;
- return 0;
-}
-
-/*
- * Close the device
- *
- * DEV - device
- *
- * Called when closing the DMAbuf (dmabuf.c:477)
- * after halt_xfer
- */
-static void
-nm256_audio_close(int dev)
-{
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card != NULL) {
- int w;
-
- if (card->dev[0] == dev)
- w = 0;
- else if (card->dev[1] == dev)
- w = 1;
- else
- return;
-
- card->opencnt[w]--;
- if (card->opencnt[w] <= 0) {
- card->opencnt[w] = 0;
-
- if (card->dev_for_play == dev) {
- stopPlay (card);
- card->is_open_play = 0;
- card->dev_for_play = -1;
- }
-
- if (card->dev_for_record == dev) {
- stopRecord (card);
- card->is_open_record = 0;
- card->dev_for_record = -1;
- }
- }
- }
-}
-
-/* Standard ioctl handler. */
-static int
-nm256_audio_ioctl(int dev, unsigned int cmd, void __user *arg)
-{
- int ret;
- u32 oldinfo;
- int w;
-
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card == NULL)
- return -ENODEV;
-
- if (dev == card->dev[0])
- w = 0;
- else
- w = 1;
-
- /*
- * The code here is messy. There are probably better ways to do
- * it. (It should be possible to handle it the same way the AC97 mixer
- * is done.)
- */
- switch (cmd)
- {
- case SOUND_PCM_WRITE_RATE:
- if (get_user(ret, (int __user *) arg))
- return -EFAULT;
-
- if (ret != 0) {
- oldinfo = card->sinfo[w].samplerate;
- card->sinfo[w].samplerate = ret;
- ret = nm256_setInfo(dev, card);
- if (ret != 0)
- card->sinfo[w].samplerate = oldinfo;
- }
- if (ret == 0)
- ret = card->sinfo[w].samplerate;
- break;
-
- case SOUND_PCM_READ_RATE:
- ret = card->sinfo[w].samplerate;
- break;
-
- case SNDCTL_DSP_STEREO:
- if (get_user(ret, (int __user *) arg))
- return -EFAULT;
-
- card->sinfo[w].stereo = ret ? 1 : 0;
- ret = nm256_setInfo (dev, card);
- if (ret == 0)
- ret = card->sinfo[w].stereo;
-
- break;
-
- case SOUND_PCM_WRITE_CHANNELS:
- if (get_user(ret, (int __user *) arg))
- return -EFAULT;
-
- if (ret < 1 || ret > 3)
- ret = card->sinfo[w].stereo + 1;
- else {
- card->sinfo[w].stereo = ret - 1;
- ret = nm256_setInfo (dev, card);
- if (ret == 0)
- ret = card->sinfo[w].stereo + 1;
- }
- break;
-
- case SOUND_PCM_READ_CHANNELS:
- ret = card->sinfo[w].stereo + 1;
- break;
-
- case SNDCTL_DSP_SETFMT:
- if (get_user(ret, (int __user *) arg))
- return -EFAULT;
-
- if (ret != 0) {
- oldinfo = card->sinfo[w].bits;
- card->sinfo[w].bits = ret;
- ret = nm256_setInfo (dev, card);
- if (ret != 0)
- card->sinfo[w].bits = oldinfo;
- }
- if (ret == 0)
- ret = card->sinfo[w].bits;
- break;
-
- case SOUND_PCM_READ_BITS:
- ret = card->sinfo[w].bits;
- break;
-
- default:
- return -EINVAL;
- }
- return put_user(ret, (int __user *) arg);
-}
-
-/*
- * Given the sound device DEV and an associated physical buffer PHYSBUF,
- * return a pointer to the actual buffer in kernel space.
- *
- * This routine should exist as part of the soundcore routines.
- */
-
-static char *
-nm256_getDMAbuffer (int dev, unsigned long physbuf)
-{
- struct audio_operations *adev = audio_devs[dev];
- struct dma_buffparms *dmap = adev->dmap_out;
- char *dma_start =
- (char *)(physbuf - (unsigned long)dmap->raw_buf_phys
- + (unsigned long)dmap->raw_buf);
-
- return dma_start;
-}
-
-
-/*
- * Output a block to sound device
- *
- * dev - device number
- * buf - physical address of buffer
- * total_count - total byte count in buffer
- * intrflag - set if this has been called from an interrupt
- * (via DMAbuf_outputintr)
- * restart_dma - set if engine needs to be re-initialised
- *
- * Called when:
- * 1. Starting output (dmabuf.c:1327)
- * 2. (dmabuf.c:1504)
- * 3. A new buffer needs to be sent to the device (dmabuf.c:1579)
- */
-static void
-nm256_audio_output_block(int dev, unsigned long physbuf,
- int total_count, int intrflag)
-{
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card != NULL) {
- char *dma_buf = nm256_getDMAbuffer (dev, physbuf);
- card->is_open_play = 1;
- card->dev_for_play = dev;
- nm256_write_block (card, dma_buf, total_count);
- }
-}
-
-/* Ditto, but do recording instead. */
-static void
-nm256_audio_start_input(int dev, unsigned long physbuf, int count,
- int intrflag)
-{
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card != NULL) {
- char *dma_buf = nm256_getDMAbuffer (dev, physbuf);
- card->is_open_record = 1;
- card->dev_for_record = dev;
- nm256_startRecording (card, dma_buf, count);
- }
-}
-
-/*
- * Prepare for inputting samples to DEV.
- * Each requested buffer will be BSIZE byes long, with a total of
- * BCOUNT buffers.
- */
-
-static int
-nm256_audio_prepare_for_input(int dev, int bsize, int bcount)
-{
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card == NULL)
- return -ENODEV;
-
- if (card->is_open_record && card->dev_for_record != dev)
- return -EBUSY;
-
- audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
- return 0;
-}
-
-/*
- * Prepare for outputting samples to `dev'
- *
- * Each buffer that will be passed will be `bsize' bytes long,
- * with a total of `bcount' buffers.
- *
- * Called when:
- * 1. A trigger enables audio output (dmabuf.c:978)
- * 2. We get a write buffer without dma_mode setup (dmabuf.c:1152)
- * 3. We restart a transfer (dmabuf.c:1324)
- */
-
-static int
-nm256_audio_prepare_for_output(int dev, int bsize, int bcount)
-{
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card == NULL)
- return -ENODEV;
-
- if (card->is_open_play && card->dev_for_play != dev)
- return -EBUSY;
-
- audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
- return 0;
-}
-
-/* Stop the current operations associated with DEV. */
-static void
-nm256_audio_reset(int dev)
-{
- struct nm256_info *card = nm256_find_card (dev);
-
- if (card != NULL) {
- if (card->dev_for_play == dev)
- stopPlay (card);
- if (card->dev_for_record == dev)
- stopRecord (card);
- }
-}
-
-static int
-nm256_audio_local_qlen(int dev)
-{
- return 0;
-}
-
-static struct audio_driver nm256_audio_driver =
-{
- .owner = THIS_MODULE,
- .open = nm256_audio_open,
- .close = nm256_audio_close,
- .output_block = nm256_audio_output_block,
- .start_input = nm256_audio_start_input,
- .ioctl = nm256_audio_ioctl,
- .prepare_for_input = nm256_audio_prepare_for_input,
- .prepare_for_output = nm256_audio_prepare_for_output,
- .halt_io = nm256_audio_reset,
- .local_qlen = nm256_audio_local_qlen,
-};
-
-static struct pci_device_id nm256_pci_tbl[] = {
- {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0},
- {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0},
- {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0},
- {0,}
-};
-MODULE_DEVICE_TABLE(pci, nm256_pci_tbl);
-MODULE_LICENSE("GPL");
-
-
-static struct pci_driver nm256_pci_driver = {
- .name = "nm256_audio",
- .id_table = nm256_pci_tbl,
- .probe = nm256_probe,
- .remove = nm256_remove,
-};
-
-module_param(usecache, bool, 0);
-module_param(buffertop, int, 0);
-module_param(nm256_debug, bool, 0644);
-module_param(force_load, bool, 0);
-
-static int __init do_init_nm256(void)
-{
- printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1p\n");
- return pci_register_driver(&nm256_pci_driver);
-}
-
-static void __exit cleanup_nm256 (void)
-{
- pci_unregister_driver(&nm256_pci_driver);
-}
-
-module_init(do_init_nm256);
-module_exit(cleanup_nm256);
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/nm256_coeff.h b/sound/oss/nm256_coeff.h
deleted file mode 100644
index 6fc07f3cb33b..000000000000
--- a/sound/oss/nm256_coeff.h
+++ /dev/null
@@ -1,4697 +0,0 @@
-#ifndef NM256_COEFF_H
-#define NM256_COEFF_H
-
-#define NM_TOTAL_COEFF_COUNT 0x3158
-
-static char coefficients[NM_TOTAL_COEFF_COUNT * 4] = {
- 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21,
- 0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01,
- 0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD,
- 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06,
- 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1,
- 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFD, 0xFF,
- 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E,
- 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC,
- 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x02, 0x00, 0x05,
- 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
- 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
- 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
- 0x60, 0x00, 0xA4, 0xFF, 0xDE, 0xFF, 0xB5, 0x01, 0x5E, 0xF9, 0xE9,
- 0x45, 0x62, 0x11, 0x87, 0xF7, 0x21, 0x05, 0xEF, 0xFC, 0xA5, 0x01,
- 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84,
- 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
- 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
- 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
- 0xCA, 0x01, 0x95, 0xFC, 0xEA, 0x05, 0xBB, 0xF5, 0x25, 0x17, 0x3C,
- 0x43, 0x8D, 0xF6, 0x43, 0x03, 0xF5, 0xFE, 0x26, 0x00, 0x20, 0x00,
- 0xE2, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5,
- 0x01, 0x4C, 0xFC, 0x26, 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33,
- 0x8F, 0xF1, 0xCA, 0x06, 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24,
- 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD5, 0xFF, 0xBC, 0x00,
- 0xF0, 0xFD, 0xEC, 0x04, 0xD9, 0xF3, 0xB1, 0x3E, 0xCD, 0x1E, 0xC1,
- 0xF3, 0xAF, 0x06, 0x49, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00,
- 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38,
- 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA,
- 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0x98, 0x01, 0x0D, 0xFD,
- 0xE0, 0x04, 0x14, 0xF8, 0xC3, 0x0F, 0x89, 0x46, 0x4C, 0xFA, 0x38,
- 0x01, 0x25, 0x00, 0x7D, 0xFF, 0x73, 0x00, 0xC2, 0xFF, 0x0F, 0x00,
- 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F,
- 0x07, 0x84, 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05,
- 0x41, 0xFD, 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x15, 0x00, 0x97, 0xFF, 0x37, 0x01, 0x22, 0xFD, 0x23, 0x06,
- 0x2F, 0xF2, 0x11, 0x39, 0x7B, 0x26, 0x50, 0xF2, 0x1B, 0x07, 0x32,
- 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
- 0xC8, 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93,
- 0xF9, 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC,
- 0xA2, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
- 0x00, 0x6A, 0xFF, 0x53, 0x01, 0xA6, 0xFD, 0xA6, 0x03, 0xA1, 0xFA,
- 0xDE, 0x08, 0x76, 0x48, 0x0C, 0xFF, 0xDE, 0xFE, 0x73, 0x01, 0xC9,
- 0xFE, 0xCA, 0x00, 0xA0, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
- 0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
- 0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x68,
- 0xFF, 0x93, 0x01, 0x92, 0xFC, 0xE2, 0x06, 0x83, 0xF1, 0x8C, 0x32,
- 0xED, 0x2D, 0x90, 0xF1, 0x1E, 0x07, 0x57, 0xFC, 0xBD, 0x01, 0x51,
- 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00,
- 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76,
- 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF,
- 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, 0x03, 0x01, 0x53,
- 0xFE, 0x53, 0x02, 0x39, 0xFD, 0xA9, 0x02, 0xF2, 0x48, 0xB9, 0x04,
- 0x54, 0xFC, 0xCA, 0x02, 0x16, 0xFE, 0x20, 0x01, 0x7F, 0xFF, 0x20,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC3, 0x01,
- 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, 0x43, 0x20,
- 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, 0xDD, 0xFF,
- 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCD, 0x01, 0x43,
- 0xFC, 0x2A, 0x07, 0xBC, 0xF1, 0x64, 0x2B, 0xE3, 0x34, 0xA3, 0xF1,
- 0xAE, 0x06, 0xBD, 0xFC, 0x77, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
- 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, 0xFD,
- 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, 0xC8,
- 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x14, 0x00, 0xAC, 0xFF, 0xAC, 0x00, 0x08, 0xFF, 0xFD, 0x00, 0xB5,
- 0xFF, 0x4B, 0xFD, 0xF4, 0x47, 0x30, 0x0B, 0xBC, 0xF9, 0x17, 0x04,
- 0x6E, 0xFD, 0x6D, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, 0x26, 0xFD, 0xAD, 0x04,
- 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, 0xFB, 0xD4, 0x00, 0x5D,
- 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0x01, 0x07, 0xBE,
- 0xF2, 0xD6, 0x23, 0x1F, 0x3B, 0xA5, 0xF2, 0xC5, 0x05, 0x62, 0xFD,
- 0x10, 0x01, 0xAB, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19,
- 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, 0x4D, 0x06, 0x00, 0xF2,
- 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, 0x07, 0x34, 0xFC, 0xDD,
- 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF,
- 0x56, 0x00, 0xB9, 0xFF, 0xB8, 0xFF, 0xF7, 0x01, 0xE2, 0xF8, 0x8D,
- 0x45, 0x46, 0x12, 0x3C, 0xF7, 0x43, 0x05, 0xDF, 0xFC, 0xAC, 0x01,
- 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70,
- 0xFF, 0x46, 0x01, 0xC3, 0xFD, 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07,
- 0xA6, 0x48, 0xF8, 0xFF, 0x70, 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9,
- 0x00, 0x9A, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
- 0xDE, 0x01, 0x5D, 0xFC, 0x74, 0x06, 0x63, 0xF4, 0x23, 0x1C, 0x66,
- 0x40, 0xAA, 0xF4, 0x65, 0x04, 0x44, 0xFE, 0x8B, 0x00, 0xEE, 0xFF,
- 0xF5, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F,
- 0x01, 0x80, 0xFC, 0xF7, 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F,
- 0x83, 0xF1, 0x13, 0x07, 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C,
- 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xED, 0xFF, 0x05, 0x00, 0x5D, 0x00,
- 0x95, 0xFE, 0xE2, 0x03, 0x7F, 0xF5, 0xCC, 0x41, 0xC7, 0x19, 0xFF,
- 0xF4, 0x37, 0x06, 0x75, 0xFC, 0xD6, 0x01, 0x39, 0xFF, 0x35, 0x00,
- 0xFE, 0xFF, 0x1B, 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18,
- 0x02, 0xAA, 0xFD, 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB,
- 0x05, 0x03, 0xF7, 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBB, 0x01, 0xBA, 0xFC,
- 0x95, 0x05, 0x83, 0xF6, 0x8C, 0x14, 0x87, 0x44, 0xBB, 0xF7, 0x98,
- 0x02, 0x5A, 0xFF, 0xEE, 0xFF, 0x3C, 0x00, 0xD8, 0xFF, 0x0A, 0x00,
- 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A,
- 0x07, 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06,
- 0xD5, 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01,
- 0x00, 0x07, 0x00, 0xBE, 0xFF, 0xEA, 0x00, 0xA2, 0xFD, 0x65, 0x05,
- 0x28, 0xF3, 0xDB, 0x3C, 0x78, 0x21, 0x30, 0xF3, 0xDF, 0x06, 0x3A,
- 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
- 0xB2, 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76,
- 0xFC, 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD,
- 0x79, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
- 0x00, 0x58, 0xFF, 0x82, 0x01, 0x3F, 0xFD, 0x78, 0x04, 0xF2, 0xF8,
- 0x50, 0x0D, 0x5E, 0x47, 0xD5, 0xFB, 0x6F, 0x00, 0x96, 0x00, 0x40,
- 0xFF, 0x91, 0x00, 0xB7, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00,
- 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
- 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
- 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x85,
- 0xFF, 0x5B, 0x01, 0xE9, 0xFC, 0x73, 0x06, 0xD8, 0xF1, 0xE5, 0x36,
- 0x19, 0x29, 0xF8, 0xF1, 0x29, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x42,
- 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, 0xFF, 0x47, 0x00,
- 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, 0x8D,
- 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, 0xFF,
- 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x75, 0xFF, 0x39,
- 0x01, 0xE0, 0xFD, 0x33, 0x03, 0x87, 0xFB, 0xA2, 0x06, 0xCB, 0x48,
- 0xEA, 0x00, 0x01, 0xFE, 0xE9, 0x01, 0x8A, 0xFE, 0xE8, 0x00, 0x95,
- 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, 0xDA, 0x01,
- 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, 0x41, 0x1F,
- 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, 0xF0, 0xFF,
- 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5B, 0xFF, 0xAB, 0x01, 0x6F,
- 0xFC, 0x08, 0x07, 0x7E, 0xF1, 0x21, 0x30, 0x67, 0x30, 0x7D, 0xF1,
- 0x05, 0x07, 0x73, 0xFC, 0xA8, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD,
- 0xFF, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0x67, 0xFE,
- 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, 0xA6, 0xF4, 0x5A,
- 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
- 0x1A, 0x00, 0x96, 0xFF, 0xE5, 0x00, 0x91, 0xFE, 0xDC, 0x01, 0x1A,
- 0xFE, 0xB3, 0x00, 0xC3, 0x48, 0xE1, 0x06, 0x6E, 0xFB, 0x40, 0x03,
- 0xDA, 0xFD, 0x3C, 0x01, 0x74, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05,
- 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E,
- 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
- 0x33, 0x00, 0x41, 0xFF, 0xD9, 0x01, 0x36, 0xFC, 0x28, 0x07, 0x01,
- 0xF2, 0xCE, 0x28, 0x23, 0x37, 0xE0, 0xF1, 0x6B, 0x06, 0xEF, 0xFC,
- 0x57, 0x01, 0x87, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B,
- 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, 0xFD, 0x9C, 0x05, 0xDC, 0xF2,
- 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, 0xF3, 0x06, 0x35, 0xFC, 0xE6,
- 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xB8, 0xFF,
- 0x8E, 0x00, 0x46, 0xFF, 0x8A, 0x00, 0x86, 0x00, 0xA7, 0xFB, 0x48,
- 0x47, 0x95, 0x0D, 0xD9, 0xF8, 0x84, 0x04, 0x39, 0xFD, 0x85, 0x01,
- 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
- 0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
- 0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
- 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
- 0xE6, 0x01, 0x3B, 0xFC, 0xDA, 0x06, 0x3F, 0xF3, 0x2C, 0x21, 0x11,
- 0x3D, 0x3A, 0xF3, 0x58, 0x05, 0xAA, 0xFD, 0xE5, 0x00, 0xC1, 0xFF,
- 0x06, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B,
- 0x01, 0xCF, 0xFC, 0x96, 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A,
- 0xD4, 0xF1, 0x2B, 0x07, 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32,
- 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD9, 0xFF, 0x39, 0x00, 0xF4, 0xFF,
- 0x4E, 0xFF, 0xAC, 0x02, 0x98, 0xF7, 0x65, 0x44, 0xD6, 0x14, 0x6C,
- 0xF6, 0x9F, 0x05, 0xB6, 0xFC, 0xBD, 0x01, 0x42, 0xFF, 0x32, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE,
- 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01,
- 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C,
- 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD5, 0x01, 0x78, 0xFC,
- 0x2F, 0x06, 0x13, 0xF5, 0x7C, 0x19, 0xF7, 0x41, 0x9B, 0xF5, 0xD1,
- 0x03, 0x9F, 0xFE, 0x57, 0x00, 0x08, 0x00, 0xEC, 0xFF, 0x06, 0x00,
- 0xFD, 0xFF, 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16,
- 0x07, 0x85, 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06,
- 0x84, 0xFC, 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04,
- 0x00, 0xF6, 0xFF, 0xEB, 0xFF, 0x91, 0x00, 0x3B, 0xFE, 0x75, 0x04,
- 0x92, 0xF4, 0x36, 0x40, 0x6E, 0x1C, 0x50, 0xF4, 0x7B, 0x06, 0x5B,
- 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00,
- 0x9C, 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3,
- 0xFF, 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD,
- 0x49, 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
- 0x00, 0x49, 0xFF, 0xAA, 0x01, 0xE4, 0xFC, 0x38, 0x05, 0x54, 0xF7,
- 0xFE, 0x11, 0xAA, 0x45, 0x09, 0xF9, 0xE2, 0x01, 0xC4, 0xFF, 0xB3,
- 0xFF, 0x59, 0x00, 0xCD, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00,
- 0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
- 0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
- 0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA9,
- 0xFF, 0x15, 0x01, 0x5B, 0xFD, 0xD0, 0x05, 0x97, 0xF2, 0xE6, 0x3A,
- 0x21, 0x24, 0xB1, 0xF2, 0x04, 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x39,
- 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00,
- 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD,
- 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF,
- 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x6A,
- 0x01, 0x74, 0xFD, 0x0A, 0x04, 0xD5, 0xF9, 0xED, 0x0A, 0x03, 0x48,
- 0x7C, 0xFD, 0x9E, 0xFF, 0x0A, 0x01, 0x01, 0xFF, 0xAF, 0x00, 0xAB,
- 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01,
- 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, 0x3D, 0x91,
- 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, 0x02, 0x00,
- 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x75, 0xFF, 0x7A, 0x01, 0xB8,
- 0xFC, 0xB4, 0x06, 0x9E, 0xF1, 0xA2, 0x34, 0xAD, 0x2B, 0xB6, 0xF1,
- 0x29, 0x07, 0x45, 0xFC, 0xCB, 0x01, 0x49, 0xFF, 0x31, 0x00, 0xFD,
- 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, 0xFF,
- 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, 0xCA,
- 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x20, 0x00, 0x80, 0xFF, 0x1C, 0x01, 0x1C, 0xFE, 0xBD,
- 0x02, 0x6E, 0xFC, 0x7D, 0x04, 0xF3, 0x48, 0xE2, 0x02, 0x1F, 0xFD,
- 0x60, 0x02, 0x4C, 0xFE, 0x06, 0x01, 0x89, 0xFF, 0x1D, 0x00, 0xFE,
- 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, 0x88, 0xFC, 0x09, 0x06,
- 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, 0xF6, 0x83, 0x03, 0xCF,
- 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
- 0x2E, 0x00, 0x50, 0xFF, 0xBF, 0x01, 0x54, 0xFC, 0x20, 0x07, 0x94,
- 0xF1, 0xA6, 0x2D, 0xD0, 0x32, 0x85, 0xF1, 0xDD, 0x06, 0x96, 0xFC,
- 0x90, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB,
- 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, 0xB9, 0x04, 0x27, 0xF4,
- 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, 0x06, 0x50, 0xFC, 0xE2,
- 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA2, 0xFF,
- 0xC7, 0x00, 0xD0, 0xFE, 0x65, 0x01, 0xF6, 0xFE, 0xD9, 0xFE, 0x6A,
- 0x48, 0x1F, 0x09, 0x87, 0xFA, 0xB3, 0x03, 0xA0, 0xFD, 0x56, 0x01,
- 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4D,
- 0xFF, 0xA0, 0x01, 0xFB, 0xFC, 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10,
- 0x2B, 0x46, 0xBB, 0xF9, 0x83, 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68,
- 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
- 0xE1, 0x01, 0x31, 0xFC, 0x19, 0x07, 0x5B, 0xF2, 0x30, 0x26, 0x4B,
- 0x39, 0x3B, 0xF2, 0x1A, 0x06, 0x29, 0xFD, 0x33, 0x01, 0x99, 0xFF,
- 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28,
- 0x01, 0x3A, 0xFD, 0x00, 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25,
- 0x79, 0xF2, 0x12, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35,
- 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC4, 0xFF, 0x70, 0x00, 0x84, 0xFF,
- 0x19, 0x00, 0x4D, 0x01, 0x22, 0xFA, 0x70, 0x46, 0x0A, 0x10, 0xFC,
- 0xF7, 0xEB, 0x04, 0x08, 0xFD, 0x9A, 0x01, 0x4F, 0xFF, 0x2E, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90,
- 0xFD, 0xD2, 0x03, 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE,
- 0x33, 0xFF, 0x45, 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16,
- 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4B, 0xFC,
- 0xA9, 0x06, 0xD2, 0xF3, 0x81, 0x1E, 0xE4, 0x3E, 0xEF, 0xF3, 0xDE,
- 0x04, 0xF9, 0xFD, 0xB7, 0x00, 0xD8, 0xFF, 0xFD, 0xFF, 0x03, 0x00,
- 0xFD, 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0,
- 0x06, 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07,
- 0x4E, 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08,
- 0x00, 0xE4, 0xFF, 0x1D, 0x00, 0x2D, 0x00, 0xEA, 0xFE, 0x56, 0x03,
- 0x6D, 0xF6, 0x17, 0x43, 0x70, 0x17, 0xA6, 0xF5, 0xF3, 0x05, 0x91,
- 0xFC, 0xCC, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
- 0x86, 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73,
- 0x03, 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE,
- 0x14, 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33,
- 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x99, 0xFC, 0xE1, 0x05, 0xD1, 0xF5,
- 0xDC, 0x16, 0x65, 0x43, 0xAD, 0xF6, 0x31, 0x03, 0x00, 0xFF, 0x20,
- 0x00, 0x23, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00,
- 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
- 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
- 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xD3,
- 0xFF, 0xC1, 0x00, 0xE7, 0xFD, 0xFA, 0x04, 0xC4, 0xF3, 0x7E, 0x3E,
- 0x19, 0x1F, 0xB0, 0xF3, 0xB5, 0x06, 0x47, 0xFC, 0xE4, 0x01, 0x36,
- 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, 0x00,
- 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, 0x47,
- 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, 0xFF,
- 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x96,
- 0x01, 0x13, 0xFD, 0xD5, 0x04, 0x2C, 0xF8, 0x7D, 0x0F, 0xA3, 0x46,
- 0x76, 0xFA, 0x22, 0x01, 0x32, 0x00, 0x76, 0xFF, 0x76, 0x00, 0xC1,
- 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, 0xE4, 0x01,
- 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, 0x3A, 0x74,
- 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, 0x11, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x95, 0xFF, 0x3B, 0x01, 0x1B,
- 0xFD, 0x2D, 0x06, 0x24, 0xF2, 0xD3, 0x38, 0xC6, 0x26, 0x45, 0xF2,
- 0x1D, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
- 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, 0xFF, 0xE2, 0xFF,
- 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, 0x8F, 0xF7, 0x1D,
- 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x51, 0x01, 0xAC, 0xFD, 0x9A,
- 0x03, 0xBA, 0xFA, 0x9E, 0x08, 0x81, 0x48, 0x40, 0xFF, 0xC6, 0xFE,
- 0x80, 0x01, 0xC2, 0xFE, 0xCE, 0x00, 0x9F, 0xFF, 0x17, 0x00, 0xFE,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06,
- 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23,
- 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFD, 0xFF,
- 0x27, 0x00, 0x66, 0xFF, 0x96, 0x01, 0x8E, 0xFC, 0xE7, 0x06, 0x81,
- 0xF1, 0x48, 0x32, 0x34, 0x2E, 0x8D, 0xF1, 0x1C, 0x07, 0x5A, 0xFC,
- 0xBB, 0x01, 0x53, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9,
- 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, 0xFE, 0xA6, 0x03, 0xE4, 0xF5,
- 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, 0x1A, 0x06, 0x81, 0xFC, 0xD2,
- 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8B, 0xFF,
- 0xFF, 0x00, 0x5A, 0xFE, 0x46, 0x02, 0x52, 0xFD, 0x70, 0x02, 0xED,
- 0x48, 0xF5, 0x04, 0x3B, 0xFC, 0xD7, 0x02, 0x0F, 0xFE, 0x23, 0x01,
- 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
- 0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
- 0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
- 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF,
- 0xCE, 0x01, 0x41, 0xFC, 0x2A, 0x07, 0xC2, 0xF1, 0x1B, 0x2B, 0x25,
- 0x35, 0xA8, 0xF1, 0xA7, 0x06, 0xC2, 0xFC, 0x74, 0x01, 0x78, 0xFF,
- 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9,
- 0x00, 0xBF, 0xFD, 0x38, 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20,
- 0x66, 0xF3, 0xCE, 0x06, 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAE, 0xFF, 0xA9, 0x00, 0x0F, 0xFF,
- 0xF0, 0x00, 0xCD, 0xFF, 0x1B, 0xFD, 0xE4, 0x47, 0x73, 0x0B, 0xA2,
- 0xF9, 0x23, 0x04, 0x68, 0xFD, 0x70, 0x01, 0x5F, 0xFF, 0x29, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B,
- 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB,
- 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10,
- 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC,
- 0xFD, 0x06, 0xCB, 0xF2, 0x8A, 0x23, 0x58, 0x3B, 0xB4, 0xF2, 0xBA,
- 0x05, 0x6A, 0xFD, 0x0B, 0x01, 0xAE, 0xFF, 0x0D, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56,
- 0x06, 0xF7, 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07,
- 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
- 0x00, 0xCF, 0xFF, 0x52, 0x00, 0xC0, 0xFF, 0xAC, 0xFF, 0x0C, 0x02,
- 0xBC, 0xF8, 0x6D, 0x45, 0x8E, 0x12, 0x24, 0xF7, 0x4D, 0x05, 0xDB,
- 0xFC, 0xAE, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x24, 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E,
- 0xFB, 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01,
- 0xA3, 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36,
- 0x00, 0x37, 0xFF, 0xDD, 0x01, 0x60, 0xFC, 0x6D, 0x06, 0x76, 0xF4,
- 0xD8, 0x1B, 0x95, 0x40, 0xC3, 0xF4, 0x56, 0x04, 0x4E, 0xFE, 0x85,
- 0x00, 0xF1, 0xFF, 0xF4, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00,
- 0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
- 0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
- 0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x02,
- 0x00, 0x63, 0x00, 0x8A, 0xFE, 0xF3, 0x03, 0x63, 0xF5, 0xA1, 0x41,
- 0x12, 0x1A, 0xEB, 0xF4, 0x3F, 0x06, 0x72, 0xFC, 0xD7, 0x01, 0x39,
- 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00,
- 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07,
- 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF,
- 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBA,
- 0x01, 0xBF, 0xFC, 0x8B, 0x05, 0x99, 0xF6, 0x43, 0x14, 0xA9, 0x44,
- 0xDE, 0xF7, 0x85, 0x02, 0x65, 0xFF, 0xE7, 0xFF, 0x3F, 0x00, 0xD6,
- 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD5, 0x01,
- 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, 0x36, 0xC5,
- 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, 0x1E, 0x00,
- 0xFE, 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBC, 0xFF, 0xEF, 0x00, 0x9A,
- 0xFD, 0x72, 0x05, 0x16, 0xF3, 0xA5, 0x3C, 0xC4, 0x21, 0x21, 0xF3,
- 0xE4, 0x06, 0x39, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, 0x00,
- 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, 0x5A,
- 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x80, 0x01, 0x45, 0xFD, 0x6C,
- 0x04, 0x0B, 0xF9, 0x0B, 0x0D, 0x73, 0x47, 0x02, 0xFC, 0x58, 0x00,
- 0xA3, 0x00, 0x39, 0xFF, 0x94, 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, 0xFC, 0xEB, 0x06,
- 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, 0xF2, 0x84, 0x05, 0x8D,
- 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF,
- 0x1D, 0x00, 0x83, 0xFF, 0x5E, 0x01, 0xE3, 0xFC, 0x7B, 0x06, 0xD0,
- 0xF1, 0xA5, 0x36, 0x62, 0x29, 0xEF, 0xF1, 0x29, 0x07, 0x39, 0xFC,
- 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5,
- 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, 0x67, 0x02, 0x14, 0xF8,
- 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, 0x05, 0xC5, 0xFC, 0xB7,
- 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00,
- 0x76, 0xFF, 0x35, 0x01, 0xE7, 0xFD, 0x26, 0x03, 0xA1, 0xFB, 0x64,
- 0x06, 0xD2, 0x48, 0x21, 0x01, 0xE8, 0xFD, 0xF7, 0x01, 0x83, 0xFE,
- 0xEC, 0x00, 0x93, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39,
- 0xFF, 0xD9, 0x01, 0x6D, 0xFC, 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A,
- 0x5F, 0x41, 0x3A, 0xF5, 0x0C, 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE,
- 0xFF, 0xEF, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF,
- 0xAD, 0x01, 0x6C, 0xFC, 0x0C, 0x07, 0x7F, 0xF1, 0xDC, 0x2F, 0xAD,
- 0x30, 0x7D, 0xF1, 0x01, 0x07, 0x76, 0xFC, 0xA6, 0x01, 0x5E, 0xFF,
- 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D,
- 0x00, 0x5D, 0xFE, 0x3E, 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B,
- 0x93, 0xF4, 0x62, 0x06, 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36,
- 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x97, 0xFF, 0xE2, 0x00, 0x98, 0xFE,
- 0xCF, 0x01, 0x33, 0xFE, 0x7D, 0x00, 0xBB, 0x48, 0x1F, 0x07, 0x54,
- 0xFB, 0x4C, 0x03, 0xD3, 0xFD, 0x3F, 0x01, 0x73, 0xFF, 0x23, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3,
- 0xFC, 0x5D, 0x05, 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8,
- 0x2A, 0x02, 0x9A, 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C,
- 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDA, 0x01, 0x35, 0xFC,
- 0x27, 0x07, 0x09, 0xF2, 0x85, 0x28, 0x63, 0x37, 0xE9, 0xF1, 0x63,
- 0x06, 0xF5, 0xFC, 0x53, 0x01, 0x89, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
- 0x00, 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8,
- 0x05, 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06,
- 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
- 0x00, 0xB9, 0xFF, 0x8A, 0x00, 0x4D, 0xFF, 0x7D, 0x00, 0x9C, 0x00,
- 0x7B, 0xFB, 0x31, 0x47, 0xD9, 0x0D, 0xC0, 0xF8, 0x8F, 0x04, 0x34,
- 0xFD, 0x87, 0x01, 0x56, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x29, 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C,
- 0xF9, 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00,
- 0x19, 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
- 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD5, 0x06, 0x4F, 0xF3,
- 0xE0, 0x20, 0x45, 0x3D, 0x4D, 0xF3, 0x4B, 0x05, 0xB3, 0xFD, 0xE0,
- 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00,
- 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
- 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
- 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xDA, 0xFF, 0x36,
- 0x00, 0xFA, 0xFF, 0x43, 0xFF, 0xBF, 0x02, 0x75, 0xF7, 0x42, 0x44,
- 0x20, 0x15, 0x55, 0xF6, 0xA9, 0x05, 0xB2, 0xFC, 0xBF, 0x01, 0x41,
- 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF,
- 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, 0xEA,
- 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, 0x00,
- 0x8D, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD4,
- 0x01, 0x7C, 0xFC, 0x27, 0x06, 0x28, 0xF5, 0x31, 0x19, 0x21, 0x42,
- 0xB8, 0xF5, 0xC0, 0x03, 0xAA, 0xFE, 0x51, 0x00, 0x0B, 0x00, 0xEA,
- 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, 0xB7, 0x01,
- 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, 0x31, 0x7E,
- 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, 0x28, 0x00,
- 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xE8, 0xFF, 0x96, 0x00, 0x31,
- 0xFE, 0x84, 0x04, 0x79, 0xF4, 0x07, 0x40, 0xBA, 0x1C, 0x3E, 0xF4,
- 0x82, 0x06, 0x58, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
- 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, 0xFE, 0x93, 0x01,
- 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, 0xE1, 0xFA, 0x86,
- 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA8, 0x01, 0xE9, 0xFC, 0x2D,
- 0x05, 0x6B, 0xF7, 0xB6, 0x11, 0xC8, 0x45, 0x30, 0xF9, 0xCD, 0x01,
- 0xD0, 0xFF, 0xAC, 0xFF, 0x5C, 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD,
- 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07,
- 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11,
- 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x10, 0x00, 0xA7, 0xFF, 0x19, 0x01, 0x53, 0xFD, 0xDB, 0x05, 0x88,
- 0xF2, 0xAD, 0x3A, 0x6D, 0x24, 0xA4, 0xF2, 0x08, 0x07, 0x32, 0xFC,
- 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBF,
- 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, 0x00, 0x01, 0x01, 0xB6, 0xFA,
- 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, 0xC4, 0x04, 0x1B, 0xFD, 0x92,
- 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
- 0x63, 0xFF, 0x67, 0x01, 0x7A, 0xFD, 0xFE, 0x03, 0xEE, 0xF9, 0xAA,
- 0x0A, 0x16, 0x48, 0xAC, 0xFD, 0x86, 0xFF, 0x17, 0x01, 0xFA, 0xFE,
- 0xB3, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
- 0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
- 0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
- 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x73, 0xFF,
- 0x7D, 0x01, 0xB3, 0xFC, 0xBB, 0x06, 0x9A, 0xF1, 0x60, 0x34, 0xF5,
- 0x2B, 0xB0, 0xF1, 0x28, 0x07, 0x47, 0xFC, 0xCA, 0x01, 0x4A, 0xFF,
- 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17,
- 0x00, 0x10, 0xFF, 0x15, 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16,
- 0xF1, 0xF5, 0xD3, 0x05, 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x19, 0x01,
- 0x23, 0xFE, 0xB0, 0x02, 0x87, 0xFC, 0x41, 0x04, 0xF4, 0x48, 0x1C,
- 0x03, 0x06, 0xFD, 0x6E, 0x02, 0x45, 0xFE, 0x09, 0x01, 0x88, 0xFF,
- 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C,
- 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6,
- 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07,
- 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4F, 0xFF, 0xC1, 0x01, 0x52, 0xFC,
- 0x22, 0x07, 0x98, 0xF1, 0x5E, 0x2D, 0x13, 0x33, 0x87, 0xF1, 0xD8,
- 0x06, 0x9B, 0xFC, 0x8D, 0x01, 0x6B, 0xFF, 0x25, 0x00, 0xFD, 0xFF,
- 0x03, 0x00, 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8,
- 0x04, 0x10, 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06,
- 0x4E, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16,
- 0x00, 0xA3, 0xFF, 0xC3, 0x00, 0xD7, 0xFE, 0x58, 0x01, 0x0F, 0xFF,
- 0xA6, 0xFE, 0x5D, 0x48, 0x61, 0x09, 0x6E, 0xFA, 0xC0, 0x03, 0x99,
- 0xFD, 0x59, 0x01, 0x68, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x2E, 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7,
- 0xF7, 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00,
- 0x8E, 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
- 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x16, 0x07, 0x67, 0xF2,
- 0xE5, 0x25, 0x87, 0x39, 0x47, 0xF2, 0x10, 0x06, 0x30, 0xFD, 0x2F,
- 0x01, 0x9C, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x00,
- 0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
- 0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
- 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC5, 0xFF, 0x6D,
- 0x00, 0x8B, 0xFF, 0x0D, 0x00, 0x63, 0x01, 0xF9, 0xF9, 0x55, 0x46,
- 0x51, 0x10, 0xE3, 0xF7, 0xF7, 0x04, 0x03, 0xFD, 0x9D, 0x01, 0x4E,
- 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF,
- 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57,
- 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00,
- 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3,
- 0x01, 0x4D, 0xFC, 0xA3, 0x06, 0xE4, 0xF3, 0x36, 0x1E, 0x16, 0x3F,
- 0x05, 0xF4, 0xCF, 0x04, 0x02, 0xFE, 0xB2, 0x00, 0xDB, 0xFF, 0xFC,
- 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, 0x8B, 0x01,
- 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, 0x2D, 0x9A,
- 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, 0x2F, 0x00,
- 0xFD, 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x1A, 0x00, 0x33, 0x00, 0xDF,
- 0xFE, 0x68, 0x03, 0x4E, 0xF6, 0xEE, 0x42, 0xBB, 0x17, 0x90, 0xF5,
- 0xFC, 0x05, 0x8E, 0xFC, 0xCD, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
- 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, 0x02,
- 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, 0xA9,
- 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC7, 0x01, 0x9D, 0xFC, 0xD8,
- 0x05, 0xE7, 0xF5, 0x91, 0x16, 0x89, 0x43, 0xCD, 0xF6, 0x1E, 0x03,
- 0x0B, 0xFF, 0x1A, 0x00, 0x26, 0x00, 0xE0, 0xFF, 0x08, 0x00, 0xFD,
- 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, 0x48, 0xFC, 0x28, 0x07,
- 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, 0xF1, 0xBE, 0x06, 0xB0,
- 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00,
- 0x00, 0x00, 0xD0, 0xFF, 0xC7, 0x00, 0xDE, 0xFD, 0x08, 0x05, 0xB0,
- 0xF3, 0x4A, 0x3E, 0x64, 0x1F, 0xA0, 0xF3, 0xBB, 0x06, 0x45, 0xFC,
- 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA9,
- 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, 0x7A, 0xFF, 0xC5, 0xFD,
- 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, 0x03, 0x7D, 0xFD, 0x66,
- 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
- 0x52, 0xFF, 0x93, 0x01, 0x18, 0xFD, 0xC9, 0x04, 0x45, 0xF8, 0x36,
- 0x0F, 0xBB, 0x46, 0xA1, 0xFA, 0x0C, 0x01, 0x3E, 0x00, 0x70, 0xFF,
- 0x7A, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39,
- 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24,
- 0x8F, 0x3A, 0x82, 0xF2, 0xE1, 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6,
- 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x17, 0x00, 0x93, 0xFF,
- 0x3F, 0x01, 0x15, 0xFD, 0x36, 0x06, 0x19, 0xF2, 0x97, 0x38, 0x11,
- 0x27, 0x3B, 0xF2, 0x1F, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF,
- 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9,
- 0xFF, 0xD6, 0xFF, 0xC3, 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11,
- 0x77, 0xF7, 0x28, 0x05, 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6D, 0xFF, 0x4E, 0x01,
- 0xB3, 0xFD, 0x8D, 0x03, 0xD4, 0xFA, 0x5D, 0x08, 0x8D, 0x48, 0x74,
- 0xFF, 0xAE, 0xFE, 0x8D, 0x01, 0xBB, 0xFE, 0xD1, 0x00, 0x9E, 0xFF,
- 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57,
- 0xFC, 0x85, 0x06, 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4,
- 0x8C, 0x04, 0x2C, 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04,
- 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x65, 0xFF, 0x98, 0x01, 0x8A, 0xFC,
- 0xEC, 0x06, 0x7F, 0xF1, 0x04, 0x32, 0x7B, 0x2E, 0x8A, 0xF1, 0x1A,
- 0x07, 0x5D, 0xFC, 0xB8, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF,
- 0x06, 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8,
- 0x03, 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06,
- 0x7D, 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C,
- 0x00, 0x8D, 0xFF, 0xFC, 0x00, 0x61, 0xFE, 0x39, 0x02, 0x6B, 0xFD,
- 0x37, 0x02, 0xEB, 0x48, 0x31, 0x05, 0x21, 0xFC, 0xE4, 0x02, 0x08,
- 0xFE, 0x26, 0x01, 0x7C, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x32, 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A,
- 0xF6, 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF,
- 0xFE, 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x32,
- 0x00, 0x47, 0xFF, 0xD0, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xCA, 0xF1,
- 0xD1, 0x2A, 0x65, 0x35, 0xAE, 0xF1, 0xA0, 0x06, 0xC7, 0xFC, 0x70,
- 0x01, 0x7A, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00,
- 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
- 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
- 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA5,
- 0x00, 0x16, 0xFF, 0xE3, 0x00, 0xE4, 0xFF, 0xEB, 0xFC, 0xD2, 0x47,
- 0xB6, 0x0B, 0x89, 0xF9, 0x2F, 0x04, 0x62, 0xFD, 0x72, 0x01, 0x5E,
- 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x56, 0xFF,
- 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, 0x26,
- 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, 0x00,
- 0xBA, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6,
- 0x01, 0x34, 0xFC, 0xF9, 0x06, 0xD9, 0xF2, 0x3F, 0x23, 0x90, 0x3B,
- 0xC4, 0xF2, 0xAE, 0x05, 0x72, 0xFD, 0x07, 0x01, 0xB0, 0xFF, 0x0C,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, 0x51, 0x01,
- 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, 0x28, 0x0E,
- 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, 0x34, 0x00,
- 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x4F, 0x00, 0xC7, 0xFF, 0xA0,
- 0xFF, 0x20, 0x02, 0x96, 0xF8, 0x4E, 0x45, 0xD7, 0x12, 0x0D, 0xF7,
- 0x58, 0x05, 0xD6, 0xFC, 0xB0, 0x01, 0x47, 0xFF, 0x30, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, 0x01, 0xD0, 0xFD,
- 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, 0x62, 0x00, 0x3F,
- 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, 0xFF, 0x19, 0x00,
- 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x63, 0xFC, 0x66,
- 0x06, 0x89, 0xF4, 0x8C, 0x1B, 0xC3, 0x40, 0xDD, 0xF4, 0x46, 0x04,
- 0x58, 0xFE, 0x80, 0x00, 0xF4, 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD,
- 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06,
- 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A,
- 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00,
- 0xEF, 0xFF, 0xFF, 0xFF, 0x69, 0x00, 0x80, 0xFE, 0x04, 0x04, 0x48,
- 0xF5, 0x74, 0x41, 0x5D, 0x1A, 0xD7, 0xF4, 0x47, 0x06, 0x6F, 0xFC,
- 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x93,
- 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, 0x01, 0xDC, 0xFD, 0x3C, 0x01,
- 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, 0x1F, 0x03, 0xEA, 0xFD, 0x34,
- 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00,
- 0x44, 0xFF, 0xB8, 0x01, 0xC3, 0xFC, 0x81, 0x05, 0xB0, 0xF6, 0xFA,
- 0x13, 0xCC, 0x44, 0x02, 0xF8, 0x71, 0x02, 0x71, 0xFF, 0xE1, 0xFF,
- 0x42, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43,
- 0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
- 0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
- 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x09, 0x00, 0xBA, 0xFF,
- 0xF4, 0x00, 0x91, 0xFD, 0x7E, 0x05, 0x05, 0xF3, 0x6E, 0x3C, 0x10,
- 0x22, 0x12, 0xF3, 0xE9, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
- 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35,
- 0xFF, 0xA9, 0x00, 0x4D, 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C,
- 0x18, 0xF9, 0x66, 0x04, 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5A, 0xFF, 0x7D, 0x01,
- 0x4B, 0xFD, 0x60, 0x04, 0x24, 0xF9, 0xC6, 0x0C, 0x86, 0x47, 0x30,
- 0xFC, 0x41, 0x00, 0xB0, 0x00, 0x32, 0xFF, 0x98, 0x00, 0xB4, 0xFF,
- 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38,
- 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3,
- 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01,
- 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x81, 0xFF, 0x62, 0x01, 0xDD, 0xFC,
- 0x83, 0x06, 0xC9, 0xF1, 0x66, 0x36, 0xAC, 0x29, 0xE7, 0xF1, 0x2A,
- 0x07, 0x3A, 0xFC, 0xD5, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
- 0x0B, 0x00, 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B,
- 0x02, 0xF0, 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05,
- 0xC1, 0xFC, 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x22, 0x00, 0x77, 0xFF, 0x32, 0x01, 0xED, 0xFD, 0x19, 0x03,
- 0xBB, 0xFB, 0x26, 0x06, 0xD7, 0x48, 0x58, 0x01, 0xCF, 0xFD, 0x04,
- 0x02, 0x7D, 0xFE, 0xEF, 0x00, 0x92, 0xFF, 0x1B, 0x00, 0xFE, 0xFF,
- 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1,
- 0xF4, 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE,
- 0x66, 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2B,
- 0x00, 0x59, 0xFF, 0xB0, 0x01, 0x69, 0xFC, 0x0F, 0x07, 0x80, 0xF1,
- 0x96, 0x2F, 0xF2, 0x30, 0x7C, 0xF1, 0xFD, 0x06, 0x7A, 0xFC, 0xA3,
- 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF4, 0xFF,
- 0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
- 0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
- 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x98, 0xFF, 0xDE,
- 0x00, 0x9F, 0xFE, 0xC2, 0x01, 0x4B, 0xFE, 0x48, 0x00, 0xB3, 0x48,
- 0x5E, 0x07, 0x3B, 0xFB, 0x59, 0x03, 0xCD, 0xFD, 0x42, 0x01, 0x71,
- 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF,
- 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C,
- 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00,
- 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDB,
- 0x01, 0x35, 0xFC, 0x25, 0x07, 0x13, 0xF2, 0x3A, 0x28, 0xA0, 0x37,
- 0xF2, 0xF1, 0x5A, 0x06, 0xFB, 0xFC, 0x4F, 0x01, 0x8B, 0xFF, 0x1A,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, 0x09, 0x01,
- 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, 0x23, 0xD2,
- 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
- 0xFD, 0xFF, 0x11, 0x00, 0xBB, 0xFF, 0x87, 0x00, 0x54, 0xFF, 0x70,
- 0x00, 0xB3, 0x00, 0x4E, 0xFB, 0x1A, 0x47, 0x1F, 0x0E, 0xA8, 0xF8,
- 0x9B, 0x04, 0x2E, 0xFD, 0x8A, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, 0xFD,
- 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, 0xD9,
- 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, 0x00,
- 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD0,
- 0x06, 0x5E, 0xF3, 0x94, 0x20, 0x7B, 0x3D, 0x60, 0xF3, 0x3E, 0x05,
- 0xBB, 0xFD, 0xDB, 0x00, 0xC6, 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE,
- 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, 0xC4, 0xFC, 0xA4, 0x06,
- 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, 0xF1, 0x2A, 0x07, 0x40,
- 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00,
- 0xDB, 0xFF, 0x33, 0x00, 0x01, 0x00, 0x38, 0xFF, 0xD3, 0x02, 0x53,
- 0xF7, 0x1F, 0x44, 0x69, 0x15, 0x3F, 0xF6, 0xB2, 0x05, 0xAD, 0xFC,
- 0xC1, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20,
- 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, 0xDE, 0x02, 0x2E, 0xFC,
- 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, 0xFD, 0x3F, 0x02, 0x5D,
- 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
- 0x3B, 0xFF, 0xD3, 0x01, 0x7F, 0xFC, 0x1F, 0x06, 0x3C, 0xF5, 0xE6,
- 0x18, 0x4D, 0x42, 0xD5, 0xF5, 0xAF, 0x03, 0xB4, 0xFE, 0x4B, 0x00,
- 0x0E, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53,
- 0xFF, 0xBA, 0x01, 0x5B, 0xFC, 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E,
- 0x26, 0x32, 0x80, 0xF1, 0xEA, 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66,
- 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, 0xFF, 0xE6, 0xFF,
- 0x9C, 0x00, 0x27, 0xFE, 0x94, 0x04, 0x61, 0xF4, 0xD7, 0x3F, 0x06,
- 0x1D, 0x2B, 0xF4, 0x89, 0x06, 0x56, 0xFC, 0xE0, 0x01, 0x37, 0xFF,
- 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF,
- 0xFE, 0x86, 0x01, 0xBA, 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08,
- 0xC7, 0xFA, 0x93, 0x03, 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA6, 0x01,
- 0xEE, 0xFC, 0x23, 0x05, 0x83, 0xF7, 0x6E, 0x11, 0xE5, 0x45, 0x57,
- 0xF9, 0xB8, 0x01, 0xDC, 0xFF, 0xA5, 0xFF, 0x5F, 0x00, 0xCA, 0xFF,
- 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32,
- 0xFC, 0x1E, 0x07, 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2,
- 0x32, 0x06, 0x18, 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA4, 0xFF, 0x1D, 0x01, 0x4C, 0xFD,
- 0xE6, 0x05, 0x7B, 0xF2, 0x71, 0x3A, 0xB8, 0x24, 0x97, 0xF2, 0x0B,
- 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x0F, 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17,
- 0x01, 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04,
- 0x15, 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x28, 0x00, 0x64, 0xFF, 0x65, 0x01, 0x81, 0xFD, 0xF2, 0x03,
- 0x08, 0xFA, 0x68, 0x0A, 0x25, 0x48, 0xDE, 0xFD, 0x6E, 0xFF, 0x24,
- 0x01, 0xF3, 0xFE, 0xB6, 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8,
- 0xF3, 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD,
- 0xC4, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x23,
- 0x00, 0x71, 0xFF, 0x81, 0x01, 0xAE, 0xFC, 0xC1, 0x06, 0x95, 0xF1,
- 0x1E, 0x34, 0x3E, 0x2C, 0xAB, 0xF1, 0x27, 0x07, 0x49, 0xFC, 0xC8,
- 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF,
- 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
- 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
- 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83,
- 0xFF, 0x16, 0x01, 0x2A, 0xFE, 0xA3, 0x02, 0xA1, 0xFC, 0x06, 0x04,
- 0xF5, 0x48, 0x56, 0x03, 0xED, 0xFC, 0x7B, 0x02, 0x3E, 0xFE, 0x0C,
- 0x01, 0x86, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
- 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, 0x02,
- 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, 0x00,
- 0xE4, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3,
- 0x01, 0x4F, 0xFC, 0x24, 0x07, 0x9C, 0xF1, 0x17, 0x2D, 0x57, 0x33,
- 0x8A, 0xF1, 0xD3, 0x06, 0x9F, 0xFC, 0x8A, 0x01, 0x6D, 0xFF, 0x25,
- 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, 0xB4, 0x00,
- 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, 0x1E, 0xDB,
- 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00,
- 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC0, 0x00, 0xDE, 0xFE, 0x4B,
- 0x01, 0x27, 0xFF, 0x73, 0xFE, 0x4F, 0x48, 0xA2, 0x09, 0x54, 0xFA,
- 0xCC, 0x03, 0x93, 0xFD, 0x5C, 0x01, 0x67, 0xFF, 0x27, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, 0x01, 0x05, 0xFD,
- 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, 0x0D, 0xFA, 0x58,
- 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, 0xFF, 0x0E, 0x00,
- 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x14,
- 0x07, 0x73, 0xF2, 0x99, 0x25, 0xC2, 0x39, 0x54, 0xF2, 0x05, 0x06,
- 0x37, 0xFD, 0x2B, 0x01, 0x9E, 0xFF, 0x13, 0x00, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06,
- 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31,
- 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
- 0xC6, 0xFF, 0x69, 0x00, 0x91, 0xFF, 0x00, 0x00, 0x78, 0x01, 0xD0,
- 0xF9, 0x39, 0x46, 0x98, 0x10, 0xCB, 0xF7, 0x02, 0x05, 0xFE, 0xFC,
- 0x9F, 0x01, 0x4D, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
- 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, 0xFD, 0xB9, 0x03, 0x7B, 0xFA,
- 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, 0x03, 0xFF, 0x5F, 0x01, 0xD4,
- 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE2, 0x01, 0x4F, 0xFC, 0x9C, 0x06, 0xF5, 0xF3, 0xEA,
- 0x1D, 0x47, 0x3F, 0x1B, 0xF4, 0xC1, 0x04, 0x0B, 0xFE, 0xAC, 0x00,
- 0xDE, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
- 0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
- 0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
- 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE6, 0xFF, 0x17, 0x00,
- 0x39, 0x00, 0xD4, 0xFE, 0x7A, 0x03, 0x2F, 0xF6, 0xC7, 0x42, 0x06,
- 0x18, 0x7B, 0xF5, 0x05, 0x06, 0x8A, 0xFC, 0xCF, 0x01, 0x3C, 0xFF,
- 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49,
- 0xFE, 0x67, 0x02, 0x13, 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04,
- 0x7A, 0xFC, 0xB6, 0x02, 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01,
- 0xA1, 0xFC, 0xCF, 0x05, 0xFC, 0xF5, 0x47, 0x16, 0xB0, 0x43, 0xEE,
- 0xF6, 0x0C, 0x03, 0x16, 0xFF, 0x14, 0x00, 0x29, 0x00, 0xDF, 0xFF,
- 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46,
- 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1,
- 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE,
- 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCE, 0xFF, 0xCC, 0x00, 0xD5, 0xFD,
- 0x16, 0x05, 0x9B, 0xF3, 0x18, 0x3E, 0xB1, 0x1F, 0x8F, 0xF3, 0xC0,
- 0x06, 0x43, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x15, 0x00, 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92,
- 0xFF, 0x94, 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04,
- 0x77, 0xFD, 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x91, 0x01, 0x1E, 0xFD, 0xBE, 0x04,
- 0x5E, 0xF8, 0xF0, 0x0E, 0xD3, 0x46, 0xCB, 0xFA, 0xF6, 0x00, 0x4B,
- 0x00, 0x69, 0xFF, 0x7D, 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA,
- 0xF2, 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD,
- 0x17, 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18,
- 0x00, 0x91, 0xFF, 0x43, 0x01, 0x0E, 0xFD, 0x40, 0x06, 0x0F, 0xF2,
- 0x5B, 0x38, 0x5C, 0x27, 0x30, 0xF2, 0x21, 0x07, 0x33, 0xFC, 0xDE,
- 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCC, 0xFF,
- 0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
- 0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
- 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6E,
- 0xFF, 0x4B, 0x01, 0xB9, 0xFD, 0x80, 0x03, 0xEE, 0xFA, 0x1D, 0x08,
- 0x98, 0x48, 0xA8, 0xFF, 0x95, 0xFE, 0x9A, 0x01, 0xB4, 0xFE, 0xD4,
- 0x00, 0x9C, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
- 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F,
- 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF,
- 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9B,
- 0x01, 0x86, 0xFC, 0xF1, 0x06, 0x7E, 0xF1, 0xC0, 0x31, 0xC2, 0x2E,
- 0x87, 0xF1, 0x17, 0x07, 0x5F, 0xFC, 0xB6, 0x01, 0x55, 0xFF, 0x2D,
- 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, 0x54, 0x00,
- 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, 0x19, 0x1E,
- 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, 0x35, 0x00,
- 0xFE, 0xFF, 0x1C, 0x00, 0x8E, 0xFF, 0xF9, 0x00, 0x68, 0xFE, 0x2C,
- 0x02, 0x84, 0xFD, 0xFF, 0x01, 0xE6, 0x48, 0x6E, 0x05, 0x07, 0xFC,
- 0xF1, 0x02, 0x01, 0xFE, 0x29, 0x01, 0x7B, 0xFF, 0x21, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, 0xFC,
- 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, 0xB6,
- 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, 0x00,
- 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3E, 0xFC, 0x2B,
- 0x07, 0xD0, 0xF1, 0x89, 0x2A, 0xA6, 0x35, 0xB4, 0xF1, 0x99, 0x06,
- 0xCD, 0xFC, 0x6D, 0x01, 0x7C, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01,
- 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, 0xAE, 0xFD, 0x52, 0x05,
- 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, 0xF3, 0xD8, 0x06, 0x3C,
- 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
- 0xB0, 0xFF, 0xA2, 0x00, 0x1D, 0xFF, 0xD6, 0x00, 0xFC, 0xFF, 0xBC,
- 0xFC, 0xC0, 0x47, 0xFA, 0x0B, 0x70, 0xF9, 0x3C, 0x04, 0x5C, 0xFD,
- 0x75, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
- 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, 0x89, 0x04, 0xCD, 0xF8,
- 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, 0x00, 0x83, 0x00, 0x4A,
- 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
- 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF5, 0x06, 0xE7, 0xF2, 0xF2,
- 0x22, 0xC7, 0x3B, 0xD4, 0xF2, 0xA2, 0x05, 0x7A, 0xFD, 0x02, 0x01,
- 0xB2, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88,
- 0xFF, 0x55, 0x01, 0xF2, 0xFC, 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37,
- 0xAA, 0x28, 0x05, 0xF2, 0x27, 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41,
- 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD2, 0xFF, 0x4C, 0x00,
- 0xCD, 0xFF, 0x94, 0xFF, 0x34, 0x02, 0x70, 0xF8, 0x2E, 0x45, 0x20,
- 0x13, 0xF6, 0xF6, 0x62, 0x05, 0xD1, 0xFC, 0xB2, 0x01, 0x46, 0xFF,
- 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D,
- 0x01, 0xD6, 0xFD, 0x46, 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48,
- 0x98, 0x00, 0x26, 0xFE, 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96,
- 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01,
- 0x66, 0xFC, 0x5E, 0x06, 0x9C, 0xF4, 0x40, 0x1B, 0xEF, 0x40, 0xF7,
- 0xF4, 0x35, 0x04, 0x62, 0xFE, 0x7A, 0x00, 0xF7, 0xFF, 0xF2, 0xFF,
- 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75,
- 0xFC, 0x03, 0x07, 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1,
- 0x0A, 0x07, 0x6E, 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD,
- 0xFF, 0x05, 0x00, 0xF0, 0xFF, 0xFC, 0xFF, 0x6E, 0x00, 0x76, 0xFE,
- 0x15, 0x04, 0x2C, 0xF5, 0x49, 0x41, 0xA9, 0x1A, 0xC3, 0xF4, 0x4F,
- 0x06, 0x6C, 0xFC, 0xD9, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
- 0x1A, 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5,
- 0xFD, 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03,
- 0xE4, 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB6, 0x01, 0xC8, 0xFC, 0x77, 0x05,
- 0xC7, 0xF6, 0xB1, 0x13, 0xED, 0x44, 0x26, 0xF8, 0x5D, 0x02, 0x7D,
- 0xFF, 0xDA, 0xFF, 0x46, 0x00, 0xD4, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
- 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3,
- 0xF1, 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC,
- 0x5C, 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
- 0x00, 0xB7, 0xFF, 0xF9, 0x00, 0x89, 0xFD, 0x8A, 0x05, 0xF4, 0xF2,
- 0x37, 0x3C, 0x5B, 0x22, 0x03, 0xF3, 0xED, 0x06, 0x37, 0xFC, 0xE6,
- 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
- 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
- 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
- 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B,
- 0xFF, 0x7A, 0x01, 0x50, 0xFD, 0x54, 0x04, 0x3D, 0xF9, 0x82, 0x0C,
- 0x9A, 0x47, 0x5E, 0xFC, 0x2A, 0x00, 0xBD, 0x00, 0x2B, 0xFF, 0x9B,
- 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
- 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, 0xC0,
- 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, 0xFF,
- 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x80, 0xFF, 0x66,
- 0x01, 0xD8, 0xFC, 0x8B, 0x06, 0xC1, 0xF1, 0x27, 0x36, 0xF6, 0x29,
- 0xDF, 0xF1, 0x2A, 0x07, 0x3B, 0xFC, 0xD4, 0x01, 0x44, 0xFF, 0x32,
- 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, 0xEA, 0xFF,
- 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, 0x14, 0x8E,
- 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, 0x32, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x79, 0xFF, 0x2F, 0x01, 0xF4,
- 0xFD, 0x0C, 0x03, 0xD4, 0xFB, 0xE9, 0x05, 0xDE, 0x48, 0x8F, 0x01,
- 0xB6, 0xFD, 0x11, 0x02, 0x76, 0xFE, 0xF2, 0x00, 0x91, 0xFF, 0x1B,
- 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, 0x01, 0x73, 0xFC,
- 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, 0x71, 0xF5, 0xEB,
- 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, 0xFF, 0x06, 0x00,
- 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB2, 0x01, 0x65, 0xFC, 0x12,
- 0x07, 0x82, 0xF1, 0x50, 0x2F, 0x38, 0x31, 0x7C, 0xF1, 0xF9, 0x06,
- 0x7E, 0xFC, 0xA1, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04,
- 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04,
- 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F,
- 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
- 0x9A, 0xFF, 0xDB, 0x00, 0xA6, 0xFE, 0xB4, 0x01, 0x64, 0xFE, 0x12,
- 0x00, 0xAA, 0x48, 0x9E, 0x07, 0x21, 0xFB, 0x66, 0x03, 0xC6, 0xFD,
- 0x45, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
- 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, 0xFC, 0x48, 0x05, 0x30, 0xF7,
- 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, 0x01, 0x02, 0xB2, 0xFF, 0xBD,
- 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
- 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x24, 0x07, 0x1C, 0xF2, 0xF0,
- 0x27, 0xDF, 0x37, 0xFB, 0xF1, 0x51, 0x06, 0x01, 0xFD, 0x4B, 0x01,
- 0x8D, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
- 0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
- 0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
- 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0x84, 0x00,
- 0x5B, 0xFF, 0x64, 0x00, 0xC9, 0x00, 0x22, 0xFB, 0x02, 0x47, 0x64,
- 0x0E, 0x8F, 0xF8, 0xA7, 0x04, 0x29, 0xFD, 0x8C, 0x01, 0x54, 0xFF,
- 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E,
- 0x01, 0x6B, 0xFD, 0x1D, 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47,
- 0x33, 0xFD, 0xC1, 0xFF, 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD,
- 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
- 0x40, 0xFC, 0xCB, 0x06, 0x6E, 0xF3, 0x49, 0x20, 0xB0, 0x3D, 0x73,
- 0xF3, 0x31, 0x05, 0xC4, 0xFD, 0xD6, 0x00, 0xC8, 0xFF, 0x03, 0x00,
- 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF,
- 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1,
- 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD,
- 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x2F, 0x00, 0x07, 0x00, 0x2C, 0xFF,
- 0xE6, 0x02, 0x31, 0xF7, 0xFA, 0x43, 0xB3, 0x15, 0x29, 0xF6, 0xBC,
- 0x05, 0xA9, 0xFC, 0xC2, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1,
- 0x02, 0x47, 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD,
- 0x4D, 0x02, 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFE,
- 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, 0x83, 0xFC, 0x16, 0x06,
- 0x51, 0xF5, 0x9B, 0x18, 0x75, 0x42, 0xF3, 0xF5, 0x9D, 0x03, 0xBF,
- 0xFE, 0x45, 0x00, 0x11, 0x00, 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
- 0x2E, 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E,
- 0xF1, 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC,
- 0x94, 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF9,
- 0xFF, 0xE3, 0xFF, 0xA1, 0x00, 0x1E, 0xFE, 0xA3, 0x04, 0x49, 0xF4,
- 0xA8, 0x3F, 0x52, 0x1D, 0x19, 0xF4, 0x90, 0x06, 0x53, 0xFC, 0xE1,
- 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
- 0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
- 0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
- 0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C,
- 0xFF, 0xA3, 0x01, 0xF3, 0xFC, 0x18, 0x05, 0x9B, 0xF7, 0x27, 0x11,
- 0x02, 0x46, 0x7F, 0xF9, 0xA3, 0x01, 0xE8, 0xFF, 0x9F, 0xFF, 0x63,
- 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
- 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2,
- 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF,
- 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA2, 0xFF, 0x22,
- 0x01, 0x45, 0xFD, 0xF1, 0x05, 0x6D, 0xF2, 0x38, 0x3A, 0x03, 0x25,
- 0x8B, 0xF2, 0x0E, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x3A, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, 0x7A, 0xFF,
- 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, 0x0F, 0x20,
- 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, 0x2E, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x62, 0x01, 0x87,
- 0xFD, 0xE5, 0x03, 0x21, 0xFA, 0x25, 0x0A, 0x33, 0x48, 0x0F, 0xFE,
- 0x57, 0xFF, 0x31, 0x01, 0xEC, 0xFE, 0xB9, 0x00, 0xA7, 0xFF, 0x15,
- 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, 0xFC,
- 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, 0xF3,
- 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
- 0xFE, 0xFF, 0x23, 0x00, 0x70, 0xFF, 0x84, 0x01, 0xA9, 0xFC, 0xC7,
- 0x06, 0x91, 0xF1, 0xDC, 0x33, 0x87, 0x2C, 0xA5, 0xF1, 0x26, 0x07,
- 0x4B, 0xFC, 0xC6, 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
- 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, 0xFA, 0xFE, 0x3A, 0x03,
- 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, 0xF5, 0xE6, 0x05, 0x97,
- 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00,
- 0x1E, 0x00, 0x84, 0xFF, 0x13, 0x01, 0x31, 0xFE, 0x95, 0x02, 0xBA,
- 0xFC, 0xCB, 0x03, 0xF7, 0x48, 0x91, 0x03, 0xD3, 0xFC, 0x88, 0x02,
- 0x38, 0xFE, 0x10, 0x01, 0x85, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
- 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, 0xEF, 0x05, 0xB0, 0xF5,
- 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, 0x03, 0xEF, 0xFE, 0x2A,
- 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
- 0x4D, 0xFF, 0xC4, 0x01, 0x4D, 0xFC, 0x25, 0x07, 0xA1, 0xF1, 0xCE,
- 0x2C, 0x99, 0x33, 0x8E, 0xF1, 0xCD, 0x06, 0xA4, 0xFC, 0x87, 0x01,
- 0x6E, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD7,
- 0xFF, 0xBA, 0x00, 0xF4, 0xFD, 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E,
- 0xA7, 0x1E, 0xCA, 0xF3, 0xAC, 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36,
- 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBD, 0x00,
- 0xE5, 0xFE, 0x3E, 0x01, 0x3F, 0xFF, 0x41, 0xFE, 0x41, 0x48, 0xE4,
- 0x09, 0x3B, 0xFA, 0xD9, 0x03, 0x8D, 0xFD, 0x5F, 0x01, 0x66, 0xFF,
- 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99,
- 0x01, 0x0B, 0xFD, 0xE6, 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46,
- 0x37, 0xFA, 0x42, 0x01, 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3,
- 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01,
- 0x31, 0xFC, 0x11, 0x07, 0x7F, 0xF2, 0x4E, 0x25, 0xFD, 0x39, 0x60,
- 0xF2, 0xFB, 0x05, 0x3E, 0xFD, 0x26, 0x01, 0xA0, 0xFF, 0x12, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25,
- 0xFD, 0x1E, 0x06, 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2,
- 0x1A, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD,
- 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x66, 0x00, 0x98, 0xFF, 0xF4, 0xFF,
- 0x8E, 0x01, 0xA7, 0xF9, 0x1D, 0x46, 0xDF, 0x10, 0xB3, 0xF7, 0x0D,
- 0x05, 0xF8, 0xFC, 0xA1, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD,
- 0x03, 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE,
- 0x6C, 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFE,
- 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x51, 0xFC, 0x96, 0x06,
- 0x07, 0xF4, 0x9E, 0x1D, 0x77, 0x3F, 0x32, 0xF4, 0xB2, 0x04, 0x15,
- 0xFE, 0xA7, 0x00, 0xE0, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
- 0x26, 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84,
- 0xF1, 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC,
- 0xBE, 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE7,
- 0xFF, 0x14, 0x00, 0x3F, 0x00, 0xC9, 0xFE, 0x8C, 0x03, 0x11, 0xF6,
- 0x9E, 0x42, 0x50, 0x18, 0x66, 0xF5, 0x0D, 0x06, 0x86, 0xFC, 0xD0,
- 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
- 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
- 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
- 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
- 0xFF, 0xC4, 0x01, 0xA5, 0xFC, 0xC5, 0x05, 0x13, 0xF6, 0xFD, 0x15,
- 0xD4, 0x43, 0x0F, 0xF7, 0xF9, 0x02, 0x21, 0xFF, 0x0D, 0x00, 0x2C,
- 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, 0xFF,
- 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, 0xC3,
- 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, 0xFF,
- 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, 0xCB, 0xFF, 0xD1,
- 0x00, 0xCC, 0xFD, 0x24, 0x05, 0x87, 0xF3, 0xE4, 0x3D, 0xFD, 0x1F,
- 0x7F, 0xF3, 0xC6, 0x06, 0x41, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, 0x05, 0xFF,
- 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, 0x0B, 0xC8,
- 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, 0x28, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x8F, 0x01, 0x23,
- 0xFD, 0xB2, 0x04, 0x76, 0xF8, 0xAA, 0x0E, 0xED, 0x46, 0xF7, 0xFA,
- 0xDF, 0x00, 0x57, 0x00, 0x62, 0xFF, 0x80, 0x00, 0xBD, 0xFF, 0x10,
- 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x33, 0xFC,
- 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, 0x9E, 0xF2, 0xCB,
- 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x18, 0x00, 0x8F, 0xFF, 0x47, 0x01, 0x08, 0xFD, 0x49,
- 0x06, 0x05, 0xF2, 0x1D, 0x38, 0xA6, 0x27, 0x26, 0xF2, 0x23, 0x07,
- 0x33, 0xFC, 0xDD, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
- 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01,
- 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2,
- 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x24, 0x00, 0x6F, 0xFF, 0x48, 0x01, 0xC0, 0xFD, 0x73, 0x03, 0x07,
- 0xFB, 0xDD, 0x07, 0xA1, 0x48, 0xDD, 0xFF, 0x7D, 0xFE, 0xA7, 0x01,
- 0xAD, 0xFE, 0xD8, 0x00, 0x9B, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
- 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, 0xFC, 0x78, 0x06, 0x5A, 0xF4,
- 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, 0x6D, 0x04, 0x3F, 0xFE, 0x8E,
- 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
- 0x62, 0xFF, 0x9E, 0x01, 0x82, 0xFC, 0xF5, 0x06, 0x7D, 0xF1, 0x7B,
- 0x31, 0x09, 0x2F, 0x84, 0xF1, 0x15, 0x07, 0x62, 0xFC, 0xB4, 0x01,
- 0x56, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
- 0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
- 0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
- 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x8F, 0xFF, 0xF5, 0x00,
- 0x6F, 0xFE, 0x1E, 0x02, 0x9D, 0xFD, 0xC7, 0x01, 0xE1, 0x48, 0xAB,
- 0x05, 0xEE, 0xFB, 0xFE, 0x02, 0xFB, 0xFD, 0x2C, 0x01, 0x7A, 0xFF,
- 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC,
- 0x01, 0xB8, 0xFC, 0x9A, 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44,
- 0xA9, 0xF7, 0xA2, 0x02, 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8,
- 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD3, 0x01,
- 0x3C, 0xFC, 0x2A, 0x07, 0xD8, 0xF1, 0x3F, 0x2A, 0xE6, 0x35, 0xBB,
- 0xF1, 0x92, 0x06, 0xD2, 0xFC, 0x69, 0x01, 0x7E, 0xFF, 0x1F, 0x00,
- 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6,
- 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3,
- 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0x9F, 0x00, 0x24, 0xFF, 0xC9, 0x00,
- 0x13, 0x00, 0x8D, 0xFC, 0xAE, 0x47, 0x3E, 0x0C, 0x56, 0xF9, 0x48,
- 0x04, 0x56, 0xFD, 0x78, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E,
- 0x04, 0xE6, 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00,
- 0x90, 0x00, 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFD,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xF1, 0x06,
- 0xF5, 0xF2, 0xA7, 0x22, 0xFF, 0x3B, 0xE4, 0xF2, 0x96, 0x05, 0x81,
- 0xFD, 0xFD, 0x00, 0xB5, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF,
- 0x1C, 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC,
- 0xF1, 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC,
- 0xD8, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3,
- 0xFF, 0x49, 0x00, 0xD4, 0xFF, 0x88, 0xFF, 0x49, 0x02, 0x4B, 0xF8,
- 0x0D, 0x45, 0x68, 0x13, 0xDF, 0xF6, 0x6C, 0x05, 0xCC, 0xFC, 0xB4,
- 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
- 0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
- 0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
- 0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
- 0xFF, 0xDA, 0x01, 0x69, 0xFC, 0x57, 0x06, 0xAF, 0xF4, 0xF5, 0x1A,
- 0x1D, 0x41, 0x11, 0xF5, 0x25, 0x04, 0x6C, 0xFE, 0x74, 0x00, 0xF9,
- 0xFF, 0xF1, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF,
- 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44,
- 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF,
- 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF1, 0xFF, 0xF9, 0xFF, 0x74,
- 0x00, 0x6C, 0xFE, 0x25, 0x04, 0x11, 0xF5, 0x1D, 0x41, 0xF5, 0x1A,
- 0xAF, 0xF4, 0x57, 0x06, 0x69, 0xFC, 0xDA, 0x01, 0x38, 0xFF, 0x36,
- 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, 0x8E, 0xFE,
- 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, 0x06, 0x7B,
- 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, 0x23, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB4, 0x01, 0xCC,
- 0xFC, 0x6C, 0x05, 0xDF, 0xF6, 0x68, 0x13, 0x0D, 0x45, 0x4B, 0xF8,
- 0x49, 0x02, 0x88, 0xFF, 0xD4, 0xFF, 0x49, 0x00, 0xD3, 0xFF, 0x0B,
- 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, 0xFC,
- 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, 0x6F,
- 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, 0xFF,
- 0x01, 0x00, 0x0B, 0x00, 0xB5, 0xFF, 0xFD, 0x00, 0x81, 0xFD, 0x96,
- 0x05, 0xE4, 0xF2, 0xFF, 0x3B, 0xA7, 0x22, 0xF5, 0xF2, 0xF1, 0x06,
- 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
- 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, 0x90, 0x00, 0x7A, 0x00,
- 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, 0xF8, 0x7E, 0x04, 0x3C,
- 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2A, 0x00, 0x5C, 0xFF, 0x78, 0x01, 0x56, 0xFD, 0x48, 0x04, 0x56,
- 0xF9, 0x3E, 0x0C, 0xAE, 0x47, 0x8D, 0xFC, 0x13, 0x00, 0xC9, 0x00,
- 0x24, 0xFF, 0x9F, 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
- 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, 0xDD, 0x06, 0x37, 0xF3,
- 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, 0x05, 0xA6, 0xFD, 0xE8,
- 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00,
- 0x7E, 0xFF, 0x69, 0x01, 0xD2, 0xFC, 0x92, 0x06, 0xBB, 0xF1, 0xE6,
- 0x35, 0x3F, 0x2A, 0xD8, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
- 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD8, 0xFF, 0x3A,
- 0x00, 0xF1, 0xFF, 0x54, 0xFF, 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44,
- 0xB1, 0x14, 0x77, 0xF6, 0x9A, 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42,
- 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
- 0x2C, 0x01, 0xFB, 0xFD, 0xFE, 0x02, 0xEE, 0xFB, 0xAB, 0x05, 0xE1,
- 0x48, 0xC7, 0x01, 0x9D, 0xFD, 0x1E, 0x02, 0x6F, 0xFE, 0xF5, 0x00,
- 0x8F, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6,
- 0x01, 0x77, 0xFC, 0x33, 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41,
- 0x8D, 0xF5, 0xDA, 0x03, 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC,
- 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x56, 0xFF, 0xB4, 0x01,
- 0x62, 0xFC, 0x15, 0x07, 0x84, 0xF1, 0x09, 0x2F, 0x7B, 0x31, 0x7D,
- 0xF1, 0xF5, 0x06, 0x82, 0xFC, 0x9E, 0x01, 0x62, 0xFF, 0x28, 0x00,
- 0xFD, 0xFF, 0x04, 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F,
- 0xFE, 0x6D, 0x04, 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4,
- 0x78, 0x06, 0x5C, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
- 0xFF, 0x18, 0x00, 0x9B, 0xFF, 0xD8, 0x00, 0xAD, 0xFE, 0xA7, 0x01,
- 0x7D, 0xFE, 0xDD, 0xFF, 0xA1, 0x48, 0xDD, 0x07, 0x07, 0xFB, 0x73,
- 0x03, 0xC0, 0xFD, 0x48, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D,
- 0x05, 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01,
- 0xBE, 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0xFD,
- 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDD, 0x01, 0x33, 0xFC, 0x23, 0x07,
- 0x26, 0xF2, 0xA6, 0x27, 0x1D, 0x38, 0x05, 0xF2, 0x49, 0x06, 0x08,
- 0xFD, 0x47, 0x01, 0x8F, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x0E, 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E,
- 0xF2, 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC,
- 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBD,
- 0xFF, 0x80, 0x00, 0x62, 0xFF, 0x57, 0x00, 0xDF, 0x00, 0xF7, 0xFA,
- 0xED, 0x46, 0xAA, 0x0E, 0x76, 0xF8, 0xB2, 0x04, 0x23, 0xFD, 0x8F,
- 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
- 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
- 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
- 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
- 0xFF, 0xE5, 0x01, 0x41, 0xFC, 0xC6, 0x06, 0x7F, 0xF3, 0xFD, 0x1F,
- 0xE4, 0x3D, 0x87, 0xF3, 0x24, 0x05, 0xCC, 0xFD, 0xD1, 0x00, 0xCB,
- 0xFF, 0x02, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, 0xFF,
- 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, 0x89,
- 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, 0xFF,
- 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2C, 0x00, 0x0D,
- 0x00, 0x21, 0xFF, 0xF9, 0x02, 0x0F, 0xF7, 0xD4, 0x43, 0xFD, 0x15,
- 0x13, 0xF6, 0xC5, 0x05, 0xA5, 0xFC, 0xC4, 0x01, 0x40, 0xFF, 0x33,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0x1E, 0x01,
- 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, 0x48, 0xC6,
- 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, 0x8A, 0xFF,
- 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD0, 0x01, 0x86,
- 0xFC, 0x0D, 0x06, 0x66, 0xF5, 0x50, 0x18, 0x9E, 0x42, 0x11, 0xF6,
- 0x8C, 0x03, 0xC9, 0xFE, 0x3F, 0x00, 0x14, 0x00, 0xE7, 0xFF, 0x07,
- 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, 0x01, 0x56, 0xFC,
- 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, 0x84, 0xF1, 0xE0,
- 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF,
- 0x03, 0x00, 0xFA, 0xFF, 0xE0, 0xFF, 0xA7, 0x00, 0x15, 0xFE, 0xB2,
- 0x04, 0x32, 0xF4, 0x77, 0x3F, 0x9E, 0x1D, 0x07, 0xF4, 0x96, 0x06,
- 0x51, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
- 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE,
- 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3,
- 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x2F, 0x00, 0x4C, 0xFF, 0xA1, 0x01, 0xF8, 0xFC, 0x0D, 0x05, 0xB3,
- 0xF7, 0xDF, 0x10, 0x1D, 0x46, 0xA7, 0xF9, 0x8E, 0x01, 0xF4, 0xFF,
- 0x98, 0xFF, 0x66, 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
- 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, 0xFC, 0x1A, 0x07, 0x56, 0xF2,
- 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, 0x1E, 0x06, 0x25, 0xFD, 0x35,
- 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x12, 0x00,
- 0xA0, 0xFF, 0x26, 0x01, 0x3E, 0xFD, 0xFB, 0x05, 0x60, 0xF2, 0xFD,
- 0x39, 0x4E, 0x25, 0x7F, 0xF2, 0x11, 0x07, 0x31, 0xFC, 0xE3, 0x01,
- 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
- 0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
- 0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
- 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF,
- 0x5F, 0x01, 0x8D, 0xFD, 0xD9, 0x03, 0x3B, 0xFA, 0xE4, 0x09, 0x41,
- 0x48, 0x41, 0xFE, 0x3F, 0xFF, 0x3E, 0x01, 0xE5, 0xFE, 0xBD, 0x00,
- 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
- 0x01, 0x4A, 0xFC, 0xAC, 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E,
- 0xE4, 0xF3, 0xE5, 0x04, 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE,
- 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6E, 0xFF, 0x87, 0x01,
- 0xA4, 0xFC, 0xCD, 0x06, 0x8E, 0xF1, 0x99, 0x33, 0xCE, 0x2C, 0xA1,
- 0xF1, 0x25, 0x07, 0x4D, 0xFC, 0xC4, 0x01, 0x4D, 0xFF, 0x2F, 0x00,
- 0xFD, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF,
- 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5,
- 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE,
- 0xFF, 0x1E, 0x00, 0x85, 0xFF, 0x10, 0x01, 0x38, 0xFE, 0x88, 0x02,
- 0xD3, 0xFC, 0x91, 0x03, 0xF7, 0x48, 0xCB, 0x03, 0xBA, 0xFC, 0x95,
- 0x02, 0x31, 0xFE, 0x13, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, 0x00,
- 0xFE, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6,
- 0x05, 0xC6, 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03,
- 0xFA, 0xFE, 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0xFD,
- 0xFF, 0x30, 0x00, 0x4C, 0xFF, 0xC6, 0x01, 0x4B, 0xFC, 0x26, 0x07,
- 0xA5, 0xF1, 0x87, 0x2C, 0xDC, 0x33, 0x91, 0xF1, 0xC7, 0x06, 0xA9,
- 0xFC, 0x84, 0x01, 0x70, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x03, 0x00,
- 0xFF, 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF,
- 0xF3, 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC,
- 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA7,
- 0xFF, 0xB9, 0x00, 0xEC, 0xFE, 0x31, 0x01, 0x57, 0xFF, 0x0F, 0xFE,
- 0x33, 0x48, 0x25, 0x0A, 0x21, 0xFA, 0xE5, 0x03, 0x87, 0xFD, 0x62,
- 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
- 0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
- 0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
- 0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A,
- 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0E, 0x07, 0x8B, 0xF2, 0x03, 0x25,
- 0x38, 0x3A, 0x6D, 0xF2, 0xF1, 0x05, 0x45, 0xFD, 0x22, 0x01, 0xA2,
- 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF,
- 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0,
- 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF,
- 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x63, 0x00, 0x9F,
- 0xFF, 0xE8, 0xFF, 0xA3, 0x01, 0x7F, 0xF9, 0x02, 0x46, 0x27, 0x11,
- 0x9B, 0xF7, 0x18, 0x05, 0xF3, 0xFC, 0xA3, 0x01, 0x4C, 0xFF, 0x2F,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, 0x52, 0x01,
- 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, 0x48, 0x26,
- 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, 0xA0, 0xFF,
- 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE1, 0x01, 0x53,
- 0xFC, 0x90, 0x06, 0x19, 0xF4, 0x52, 0x1D, 0xA8, 0x3F, 0x49, 0xF4,
- 0xA3, 0x04, 0x1E, 0xFE, 0xA1, 0x00, 0xE3, 0xFF, 0xF9, 0xFF, 0x04,
- 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, 0xFC,
- 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, 0x1D,
- 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
- 0x07, 0x00, 0xE8, 0xFF, 0x11, 0x00, 0x45, 0x00, 0xBF, 0xFE, 0x9D,
- 0x03, 0xF3, 0xF5, 0x75, 0x42, 0x9B, 0x18, 0x51, 0xF5, 0x16, 0x06,
- 0x83, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
- 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, 0x4D, 0x02, 0x45, 0xFD,
- 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, 0xFC, 0xD1, 0x02, 0x12,
- 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x33, 0x00, 0x40, 0xFF, 0xC2, 0x01, 0xA9, 0xFC, 0xBC, 0x05, 0x29,
- 0xF6, 0xB3, 0x15, 0xFA, 0x43, 0x31, 0xF7, 0xE6, 0x02, 0x2C, 0xFF,
- 0x07, 0x00, 0x2F, 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
- 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, 0x2A, 0x07, 0xBF, 0xF1,
- 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, 0x06, 0xBF, 0xFC, 0x75,
- 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00,
- 0xC8, 0xFF, 0xD6, 0x00, 0xC4, 0xFD, 0x31, 0x05, 0x73, 0xF3, 0xB0,
- 0x3D, 0x49, 0x20, 0x6E, 0xF3, 0xCB, 0x06, 0x40, 0xFC, 0xE6, 0x01,
- 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA,
- 0x00, 0x0C, 0xFF, 0xF7, 0x00, 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47,
- 0x51, 0x0B, 0xAF, 0xF9, 0x1D, 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60,
- 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF,
- 0x8C, 0x01, 0x29, 0xFD, 0xA7, 0x04, 0x8F, 0xF8, 0x64, 0x0E, 0x02,
- 0x47, 0x22, 0xFB, 0xC9, 0x00, 0x64, 0x00, 0x5B, 0xFF, 0x84, 0x00,
- 0xBC, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5,
- 0x01, 0x33, 0xFC, 0xFF, 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B,
- 0xAD, 0xF2, 0xBF, 0x05, 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8D, 0xFF, 0x4B, 0x01,
- 0x01, 0xFD, 0x51, 0x06, 0xFB, 0xF1, 0xDF, 0x37, 0xF0, 0x27, 0x1C,
- 0xF2, 0x24, 0x07, 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00,
- 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2,
- 0xFF, 0x01, 0x02, 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7,
- 0x48, 0x05, 0xDD, 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x45, 0x01, 0xC6, 0xFD,
- 0x66, 0x03, 0x21, 0xFB, 0x9E, 0x07, 0xAA, 0x48, 0x12, 0x00, 0x64,
- 0xFE, 0xB4, 0x01, 0xA6, 0xFE, 0xDB, 0x00, 0x9A, 0xFF, 0x19, 0x00,
- 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70,
- 0x06, 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04,
- 0x49, 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFD,
- 0xFF, 0x29, 0x00, 0x61, 0xFF, 0xA1, 0x01, 0x7E, 0xFC, 0xF9, 0x06,
- 0x7C, 0xF1, 0x38, 0x31, 0x50, 0x2F, 0x82, 0xF1, 0x12, 0x07, 0x65,
- 0xFC, 0xB2, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00,
- 0xED, 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71,
- 0xF5, 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC,
- 0xD7, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91,
- 0xFF, 0xF2, 0x00, 0x76, 0xFE, 0x11, 0x02, 0xB6, 0xFD, 0x8F, 0x01,
- 0xDE, 0x48, 0xE9, 0x05, 0xD4, 0xFB, 0x0C, 0x03, 0xF4, 0xFD, 0x2F,
- 0x01, 0x79, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
- 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
- 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
- 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44,
- 0xFF, 0xD4, 0x01, 0x3B, 0xFC, 0x2A, 0x07, 0xDF, 0xF1, 0xF6, 0x29,
- 0x27, 0x36, 0xC1, 0xF1, 0x8B, 0x06, 0xD8, 0xFC, 0x66, 0x01, 0x80,
- 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xBD, 0xFF,
- 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, 0x9E,
- 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
- 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x9B, 0x00, 0x2B,
- 0xFF, 0xBD, 0x00, 0x2A, 0x00, 0x5E, 0xFC, 0x9A, 0x47, 0x82, 0x0C,
- 0x3D, 0xF9, 0x54, 0x04, 0x50, 0xFD, 0x7A, 0x01, 0x5B, 0xFF, 0x2A,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x81, 0x01,
- 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, 0x47, 0xEB,
- 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, 0xB6, 0xFF,
- 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37,
- 0xFC, 0xED, 0x06, 0x03, 0xF3, 0x5B, 0x22, 0x37, 0x3C, 0xF4, 0xF2,
- 0x8A, 0x05, 0x89, 0xFD, 0xF9, 0x00, 0xB7, 0xFF, 0x0A, 0x00, 0x01,
- 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, 0x01, 0xE6, 0xFC,
- 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, 0xF3, 0xF1, 0x29,
- 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
- 0x0B, 0x00, 0xD4, 0xFF, 0x46, 0x00, 0xDA, 0xFF, 0x7D, 0xFF, 0x5D,
- 0x02, 0x26, 0xF8, 0xED, 0x44, 0xB1, 0x13, 0xC7, 0xF6, 0x77, 0x05,
- 0xC8, 0xFC, 0xB6, 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03,
- 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0,
- 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
- 0x35, 0x00, 0x38, 0xFF, 0xD9, 0x01, 0x6C, 0xFC, 0x4F, 0x06, 0xC3,
- 0xF4, 0xA9, 0x1A, 0x49, 0x41, 0x2C, 0xF5, 0x15, 0x04, 0x76, 0xFE,
- 0x6E, 0x00, 0xFC, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B,
- 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, 0xFC, 0x0A, 0x07, 0x7E, 0xF1,
- 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, 0x03, 0x07, 0x75, 0xFC, 0xA7,
- 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF2, 0xFF,
- 0xF7, 0xFF, 0x7A, 0x00, 0x62, 0xFE, 0x35, 0x04, 0xF7, 0xF4, 0xEF,
- 0x40, 0x40, 0x1B, 0x9C, 0xF4, 0x5E, 0x06, 0x66, 0xFC, 0xDB, 0x01,
- 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
- 0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
- 0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
- 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF,
- 0xB2, 0x01, 0xD1, 0xFC, 0x62, 0x05, 0xF6, 0xF6, 0x20, 0x13, 0x2E,
- 0x45, 0x70, 0xF8, 0x34, 0x02, 0x94, 0xFF, 0xCD, 0xFF, 0x4C, 0x00,
- 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA,
- 0x01, 0x36, 0xFC, 0x27, 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37,
- 0xE4, 0xF1, 0x67, 0x06, 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B,
- 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, 0x00, 0xB2, 0xFF, 0x02, 0x01,
- 0x7A, 0xFD, 0xA2, 0x05, 0xD4, 0xF2, 0xC7, 0x3B, 0xF2, 0x22, 0xE7,
- 0xF2, 0xF5, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
- 0xFD, 0xFF, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83,
- 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8,
- 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x75, 0x01, 0x5C, 0xFD,
- 0x3C, 0x04, 0x70, 0xF9, 0xFA, 0x0B, 0xC0, 0x47, 0xBC, 0xFC, 0xFC,
- 0xFF, 0xD6, 0x00, 0x1D, 0xFF, 0xA2, 0x00, 0xB0, 0xFF, 0x13, 0x00,
- 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8,
- 0x06, 0x47, 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05,
- 0xAE, 0xFD, 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0xFE,
- 0xFF, 0x1F, 0x00, 0x7C, 0xFF, 0x6D, 0x01, 0xCD, 0xFC, 0x99, 0x06,
- 0xB4, 0xF1, 0xA6, 0x35, 0x89, 0x2A, 0xD0, 0xF1, 0x2B, 0x07, 0x3E,
- 0xFC, 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
- 0xD9, 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86,
- 0xF7, 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC,
- 0xBE, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
- 0x00, 0x7B, 0xFF, 0x29, 0x01, 0x01, 0xFE, 0xF1, 0x02, 0x07, 0xFC,
- 0x6E, 0x05, 0xE6, 0x48, 0xFF, 0x01, 0x84, 0xFD, 0x2C, 0x02, 0x68,
- 0xFE, 0xF9, 0x00, 0x8E, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
- 0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
- 0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
- 0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x55,
- 0xFF, 0xB6, 0x01, 0x5F, 0xFC, 0x17, 0x07, 0x87, 0xF1, 0xC2, 0x2E,
- 0xC0, 0x31, 0x7E, 0xF1, 0xF1, 0x06, 0x86, 0xFC, 0x9B, 0x01, 0x63,
- 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF,
- 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94,
- 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF,
- 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9C, 0xFF, 0xD4, 0x00, 0xB4,
- 0xFE, 0x9A, 0x01, 0x95, 0xFE, 0xA8, 0xFF, 0x98, 0x48, 0x1D, 0x08,
- 0xEE, 0xFA, 0x80, 0x03, 0xB9, 0xFD, 0x4B, 0x01, 0x6E, 0xFF, 0x25,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA9, 0x01,
- 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, 0x45, 0x1C,
- 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, 0xCC, 0xFF,
- 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDE, 0x01, 0x33,
- 0xFC, 0x21, 0x07, 0x30, 0xF2, 0x5C, 0x27, 0x5B, 0x38, 0x0F, 0xF2,
- 0x40, 0x06, 0x0E, 0xFD, 0x43, 0x01, 0x91, 0xFF, 0x18, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, 0xFD,
- 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, 0x06,
- 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x10, 0x00, 0xBE, 0xFF, 0x7D, 0x00, 0x69, 0xFF, 0x4B, 0x00, 0xF6,
- 0x00, 0xCB, 0xFA, 0xD3, 0x46, 0xF0, 0x0E, 0x5E, 0xF8, 0xBE, 0x04,
- 0x1E, 0xFD, 0x91, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, 0x77, 0xFD, 0x04, 0x04,
- 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, 0xFD, 0x92, 0xFF, 0x10,
- 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x43, 0xFC, 0xC0, 0x06, 0x8F,
- 0xF3, 0xB1, 0x1F, 0x18, 0x3E, 0x9B, 0xF3, 0x16, 0x05, 0xD5, 0xFD,
- 0xCC, 0x00, 0xCE, 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22,
- 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, 0xB8, 0x06, 0x9C, 0xF1,
- 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, 0x07, 0x46, 0xFC, 0xCA,
- 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF,
- 0x29, 0x00, 0x14, 0x00, 0x16, 0xFF, 0x0C, 0x03, 0xEE, 0xF6, 0xB0,
- 0x43, 0x47, 0x16, 0xFC, 0xF5, 0xCF, 0x05, 0xA1, 0xFC, 0xC6, 0x01,
- 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81,
- 0xFF, 0x1B, 0x01, 0x20, 0xFE, 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04,
- 0xF4, 0x48, 0xFF, 0x02, 0x13, 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07,
- 0x01, 0x88, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
- 0xCF, 0x01, 0x8A, 0xFC, 0x05, 0x06, 0x7B, 0xF5, 0x06, 0x18, 0xC7,
- 0x42, 0x2F, 0xF6, 0x7A, 0x03, 0xD4, 0xFE, 0x39, 0x00, 0x17, 0x00,
- 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0,
- 0x01, 0x53, 0xFC, 0x21, 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32,
- 0x86, 0xF1, 0xDB, 0x06, 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25,
- 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDE, 0xFF, 0xAC, 0x00,
- 0x0B, 0xFE, 0xC1, 0x04, 0x1B, 0xF4, 0x47, 0x3F, 0xEA, 0x1D, 0xF5,
- 0xF3, 0x9C, 0x06, 0x4F, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00,
- 0xFE, 0xFF, 0x16, 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F,
- 0x01, 0x03, 0xFF, 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA,
- 0xB9, 0x03, 0x9D, 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4D, 0xFF, 0x9F, 0x01, 0xFE, 0xFC,
- 0x02, 0x05, 0xCB, 0xF7, 0x98, 0x10, 0x39, 0x46, 0xD0, 0xF9, 0x78,
- 0x01, 0x00, 0x00, 0x91, 0xFF, 0x69, 0x00, 0xC6, 0xFF, 0x0E, 0x00,
- 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17,
- 0x07, 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06,
- 0x2C, 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x13, 0x00, 0x9E, 0xFF, 0x2B, 0x01, 0x37, 0xFD, 0x05, 0x06,
- 0x54, 0xF2, 0xC2, 0x39, 0x99, 0x25, 0x73, 0xF2, 0x14, 0x07, 0x31,
- 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
- 0xC4, 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D,
- 0xFA, 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD,
- 0x9C, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
- 0x00, 0x67, 0xFF, 0x5C, 0x01, 0x93, 0xFD, 0xCC, 0x03, 0x54, 0xFA,
- 0xA2, 0x09, 0x4F, 0x48, 0x73, 0xFE, 0x27, 0xFF, 0x4B, 0x01, 0xDE,
- 0xFE, 0xC0, 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
- 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
- 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6D,
- 0xFF, 0x8A, 0x01, 0x9F, 0xFC, 0xD3, 0x06, 0x8A, 0xF1, 0x57, 0x33,
- 0x17, 0x2D, 0x9C, 0xF1, 0x24, 0x07, 0x4F, 0xFC, 0xC3, 0x01, 0x4E,
- 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE4, 0xFF, 0x1B, 0x00,
- 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, 0x96,
- 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, 0xFF,
- 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x86, 0xFF, 0x0C, 0x01, 0x3E,
- 0xFE, 0x7B, 0x02, 0xED, 0xFC, 0x56, 0x03, 0xF5, 0x48, 0x06, 0x04,
- 0xA1, 0xFC, 0xA3, 0x02, 0x2A, 0xFE, 0x16, 0x01, 0x83, 0xFF, 0x1F,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC8, 0x01,
- 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, 0x43, 0xBD,
- 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, 0xE1, 0xFF,
- 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC8, 0x01, 0x49,
- 0xFC, 0x27, 0x07, 0xAB, 0xF1, 0x3E, 0x2C, 0x1E, 0x34, 0x95, 0xF1,
- 0xC1, 0x06, 0xAE, 0xFC, 0x81, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE,
- 0xFF, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, 0x00, 0xE2, 0xFD,
- 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, 0xA8, 0xF3, 0xB8,
- 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x15, 0x00, 0xA8, 0xFF, 0xB6, 0x00, 0xF3, 0xFE, 0x24, 0x01, 0x6E,
- 0xFF, 0xDE, 0xFD, 0x25, 0x48, 0x68, 0x0A, 0x08, 0xFA, 0xF2, 0x03,
- 0x81, 0xFD, 0x65, 0x01, 0x64, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04,
- 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38,
- 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0B, 0x07, 0x97,
- 0xF2, 0xB8, 0x24, 0x71, 0x3A, 0x7B, 0xF2, 0xE6, 0x05, 0x4C, 0xFD,
- 0x1D, 0x01, 0xA4, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16,
- 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, 0xFD, 0x32, 0x06, 0x1F, 0xF2,
- 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, 0x1E, 0x07, 0x32, 0xFC, 0xDF,
- 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
- 0x5F, 0x00, 0xA5, 0xFF, 0xDC, 0xFF, 0xB8, 0x01, 0x57, 0xF9, 0xE5,
- 0x45, 0x6E, 0x11, 0x83, 0xF7, 0x23, 0x05, 0xEE, 0xFC, 0xA6, 0x01,
- 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C,
- 0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
- 0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
- 0x00, 0x9E, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
- 0xE0, 0x01, 0x56, 0xFC, 0x89, 0x06, 0x2B, 0xF4, 0x06, 0x1D, 0xD7,
- 0x3F, 0x61, 0xF4, 0x94, 0x04, 0x27, 0xFE, 0x9C, 0x00, 0xE6, 0xFF,
- 0xF8, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97,
- 0x01, 0x8C, 0xFC, 0xEA, 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E,
- 0x8B, 0xF1, 0x1B, 0x07, 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D,
- 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, 0xFF, 0x0E, 0x00, 0x4B, 0x00,
- 0xB4, 0xFE, 0xAF, 0x03, 0xD5, 0xF5, 0x4D, 0x42, 0xE6, 0x18, 0x3C,
- 0xF5, 0x1F, 0x06, 0x7F, 0xFC, 0xD3, 0x01, 0x3B, 0xFF, 0x35, 0x00,
- 0xFE, 0xFF, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F,
- 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC,
- 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xC1, 0x01, 0xAD, 0xFC,
- 0xB2, 0x05, 0x3F, 0xF6, 0x69, 0x15, 0x1F, 0x44, 0x53, 0xF7, 0xD3,
- 0x02, 0x38, 0xFF, 0x01, 0x00, 0x33, 0x00, 0xDB, 0xFF, 0x09, 0x00,
- 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A,
- 0x07, 0xC6, 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06,
- 0xC4, 0xFC, 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02,
- 0x00, 0x04, 0x00, 0xC6, 0xFF, 0xDB, 0x00, 0xBB, 0xFD, 0x3E, 0x05,
- 0x60, 0xF3, 0x7B, 0x3D, 0x94, 0x20, 0x5E, 0xF3, 0xD0, 0x06, 0x3E,
- 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00,
- 0xAE, 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03,
- 0xFD, 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD,
- 0x71, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C,
- 0x00, 0x55, 0xFF, 0x8A, 0x01, 0x2E, 0xFD, 0x9B, 0x04, 0xA8, 0xF8,
- 0x1F, 0x0E, 0x1A, 0x47, 0x4E, 0xFB, 0xB3, 0x00, 0x70, 0x00, 0x54,
- 0xFF, 0x87, 0x00, 0xBB, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
- 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
- 0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
- 0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8B,
- 0xFF, 0x4F, 0x01, 0xFB, 0xFC, 0x5A, 0x06, 0xF2, 0xF1, 0xA0, 0x37,
- 0x3A, 0x28, 0x13, 0xF2, 0x25, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40,
- 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00,
- 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2,
- 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF,
- 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x42,
- 0x01, 0xCD, 0xFD, 0x59, 0x03, 0x3B, 0xFB, 0x5E, 0x07, 0xB3, 0x48,
- 0x48, 0x00, 0x4B, 0xFE, 0xC2, 0x01, 0x9F, 0xFE, 0xDE, 0x00, 0x98,
- 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDD, 0x01,
- 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, 0x40, 0xD0,
- 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, 0xF4, 0xFF,
- 0x05, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA3, 0x01, 0x7A,
- 0xFC, 0xFD, 0x06, 0x7C, 0xF1, 0xF2, 0x30, 0x96, 0x2F, 0x80, 0xF1,
- 0x0F, 0x07, 0x69, 0xFC, 0xB0, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD,
- 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, 0xFE,
- 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, 0x43,
- 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
- 0x1B, 0x00, 0x92, 0xFF, 0xEF, 0x00, 0x7D, 0xFE, 0x04, 0x02, 0xCF,
- 0xFD, 0x58, 0x01, 0xD7, 0x48, 0x26, 0x06, 0xBB, 0xFB, 0x19, 0x03,
- 0xED, 0xFD, 0x32, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, 0xC1, 0xFC, 0x86, 0x05,
- 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, 0xF7, 0x7B, 0x02, 0x6B,
- 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
- 0x33, 0x00, 0x43, 0xFF, 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE7,
- 0xF1, 0xAC, 0x29, 0x66, 0x36, 0xC9, 0xF1, 0x83, 0x06, 0xDD, 0xFC,
- 0x62, 0x01, 0x81, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x08,
- 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, 0x78, 0x05, 0x0E, 0xF3,
- 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, 0x06, 0x38, 0xFC, 0xE6,
- 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB4, 0xFF,
- 0x98, 0x00, 0x32, 0xFF, 0xB0, 0x00, 0x41, 0x00, 0x30, 0xFC, 0x86,
- 0x47, 0xC6, 0x0C, 0x24, 0xF9, 0x60, 0x04, 0x4B, 0xFD, 0x7D, 0x01,
- 0x5A, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x5A,
- 0xFF, 0x7E, 0x01, 0x48, 0xFD, 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C,
- 0x7C, 0x47, 0x19, 0xFC, 0x4D, 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96,
- 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
- 0xE6, 0x01, 0x38, 0xFC, 0xE9, 0x06, 0x12, 0xF3, 0x10, 0x22, 0x6E,
- 0x3C, 0x05, 0xF3, 0x7E, 0x05, 0x91, 0xFD, 0xF4, 0x00, 0xBA, 0xFF,
- 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60,
- 0x01, 0xE0, 0xFC, 0x7F, 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29,
- 0xEB, 0xF1, 0x2A, 0x07, 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33,
- 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, 0xFF, 0x42, 0x00, 0xE1, 0xFF,
- 0x71, 0xFF, 0x71, 0x02, 0x02, 0xF8, 0xCC, 0x44, 0xFA, 0x13, 0xB0,
- 0xF6, 0x81, 0x05, 0xC3, 0xFC, 0xB8, 0x01, 0x44, 0xFF, 0x31, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA,
- 0xFD, 0x1F, 0x03, 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01,
- 0xDC, 0xFD, 0xFD, 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B,
- 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x6F, 0xFC,
- 0x47, 0x06, 0xD7, 0xF4, 0x5D, 0x1A, 0x74, 0x41, 0x48, 0xF5, 0x04,
- 0x04, 0x80, 0xFE, 0x69, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
- 0xFD, 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D,
- 0x07, 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06,
- 0x78, 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05,
- 0x00, 0xF3, 0xFF, 0xF4, 0xFF, 0x80, 0x00, 0x58, 0xFE, 0x46, 0x04,
- 0xDD, 0xF4, 0xC3, 0x40, 0x8C, 0x1B, 0x89, 0xF4, 0x66, 0x06, 0x63,
- 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
- 0x98, 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62,
- 0x00, 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD,
- 0x40, 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
- 0x00, 0x47, 0xFF, 0xB0, 0x01, 0xD6, 0xFC, 0x58, 0x05, 0x0D, 0xF7,
- 0xD7, 0x12, 0x4E, 0x45, 0x96, 0xF8, 0x20, 0x02, 0xA0, 0xFF, 0xC7,
- 0xFF, 0x4F, 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
- 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
- 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
- 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xB0,
- 0xFF, 0x07, 0x01, 0x72, 0xFD, 0xAE, 0x05, 0xC4, 0xF2, 0x90, 0x3B,
- 0x3F, 0x23, 0xD9, 0xF2, 0xF9, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38,
- 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, 0x00,
- 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, 0xFC,
- 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, 0xFF,
- 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5E, 0xFF, 0x72,
- 0x01, 0x62, 0xFD, 0x2F, 0x04, 0x89, 0xF9, 0xB6, 0x0B, 0xD2, 0x47,
- 0xEB, 0xFC, 0xE4, 0xFF, 0xE3, 0x00, 0x16, 0xFF, 0xA5, 0x00, 0xAF,
- 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
- 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, 0x3D, 0x56,
- 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, 0x05, 0x00,
- 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x7A, 0xFF, 0x70, 0x01, 0xC7,
- 0xFC, 0xA0, 0x06, 0xAE, 0xF1, 0x65, 0x35, 0xD1, 0x2A, 0xCA, 0xF1,
- 0x2A, 0x07, 0x40, 0xFC, 0xD0, 0x01, 0x47, 0xFF, 0x32, 0x00, 0xFD,
- 0xFF, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x3D, 0xFF,
- 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, 0x4A, 0xF6, 0xAD,
- 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, 0x26, 0x01, 0x08, 0xFE, 0xE4,
- 0x02, 0x21, 0xFC, 0x31, 0x05, 0xEB, 0x48, 0x37, 0x02, 0x6B, 0xFD,
- 0x39, 0x02, 0x61, 0xFE, 0xFC, 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFE,
- 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06,
- 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF,
- 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFD, 0xFF,
- 0x2D, 0x00, 0x54, 0xFF, 0xB8, 0x01, 0x5D, 0xFC, 0x1A, 0x07, 0x8A,
- 0xF1, 0x7B, 0x2E, 0x04, 0x32, 0x7F, 0xF1, 0xEC, 0x06, 0x8A, 0xFC,
- 0x98, 0x01, 0x65, 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8,
- 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, 0xFE, 0x8C, 0x04, 0x6D, 0xF4,
- 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, 0x85, 0x06, 0x57, 0xFC, 0xE0,
- 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9E, 0xFF,
- 0xD1, 0x00, 0xBB, 0xFE, 0x8D, 0x01, 0xAE, 0xFE, 0x74, 0xFF, 0x8D,
- 0x48, 0x5D, 0x08, 0xD4, 0xFA, 0x8D, 0x03, 0xB3, 0xFD, 0x4E, 0x01,
- 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
- 0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
- 0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
- 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
- 0xDF, 0x01, 0x32, 0xFC, 0x1F, 0x07, 0x3B, 0xF2, 0x11, 0x27, 0x97,
- 0x38, 0x19, 0xF2, 0x36, 0x06, 0x15, 0xFD, 0x3F, 0x01, 0x93, 0xFF,
- 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B,
- 0x01, 0x50, 0xFD, 0xE1, 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24,
- 0x9D, 0xF2, 0x09, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x7A, 0x00, 0x70, 0xFF,
- 0x3E, 0x00, 0x0C, 0x01, 0xA1, 0xFA, 0xBB, 0x46, 0x36, 0x0F, 0x45,
- 0xF8, 0xC9, 0x04, 0x18, 0xFD, 0x93, 0x01, 0x52, 0xFF, 0x2D, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D,
- 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD,
- 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15,
- 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x45, 0xFC,
- 0xBB, 0x06, 0xA0, 0xF3, 0x64, 0x1F, 0x4A, 0x3E, 0xB0, 0xF3, 0x08,
- 0x05, 0xDE, 0xFD, 0xC7, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x02, 0x00,
- 0xFE, 0xFF, 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE,
- 0x06, 0x97, 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07,
- 0x48, 0xFC, 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
- 0x00, 0xE0, 0xFF, 0x26, 0x00, 0x1A, 0x00, 0x0B, 0xFF, 0x1E, 0x03,
- 0xCD, 0xF6, 0x89, 0x43, 0x91, 0x16, 0xE7, 0xF5, 0xD8, 0x05, 0x9D,
- 0xFC, 0xC7, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x1F, 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94,
- 0xFC, 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02,
- 0x42, 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
- 0x00, 0x3C, 0xFF, 0xCD, 0x01, 0x8E, 0xFC, 0xFC, 0x05, 0x90, 0xF5,
- 0xBB, 0x17, 0xEE, 0x42, 0x4E, 0xF6, 0x68, 0x03, 0xDF, 0xFE, 0x33,
- 0x00, 0x1A, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
- 0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
- 0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
- 0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFC, 0xFF, 0xDB,
- 0xFF, 0xB2, 0x00, 0x02, 0xFE, 0xCF, 0x04, 0x05, 0xF4, 0x16, 0x3F,
- 0x36, 0x1E, 0xE4, 0xF3, 0xA3, 0x06, 0x4D, 0xFC, 0xE3, 0x01, 0x36,
- 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00,
- 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81,
- 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF,
- 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9D,
- 0x01, 0x03, 0xFD, 0xF7, 0x04, 0xE3, 0xF7, 0x51, 0x10, 0x55, 0x46,
- 0xF9, 0xF9, 0x63, 0x01, 0x0D, 0x00, 0x8B, 0xFF, 0x6D, 0x00, 0xC5,
- 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01,
- 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, 0x39, 0x4D,
- 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, 0x13, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x9C, 0xFF, 0x2F, 0x01, 0x30,
- 0xFD, 0x10, 0x06, 0x47, 0xF2, 0x87, 0x39, 0xE5, 0x25, 0x67, 0xF2,
- 0x16, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD,
- 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, 0x00,
- 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, 0xFC,
- 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x59, 0x01, 0x99, 0xFD, 0xC0,
- 0x03, 0x6E, 0xFA, 0x61, 0x09, 0x5D, 0x48, 0xA6, 0xFE, 0x0F, 0xFF,
- 0x58, 0x01, 0xD7, 0xFE, 0xC3, 0x00, 0xA3, 0xFF, 0x16, 0x00, 0xFE,
- 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4E, 0xFC, 0xA0, 0x06,
- 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, 0xF4, 0xC8, 0x04, 0x07,
- 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
- 0x25, 0x00, 0x6B, 0xFF, 0x8D, 0x01, 0x9B, 0xFC, 0xD8, 0x06, 0x87,
- 0xF1, 0x13, 0x33, 0x5E, 0x2D, 0x98, 0xF1, 0x22, 0x07, 0x52, 0xFC,
- 0xC1, 0x01, 0x4F, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE5,
- 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, 0x71, 0x03, 0x3F, 0xF6,
- 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, 0x06, 0x8C, 0xFC, 0xCE,
- 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF,
- 0x09, 0x01, 0x45, 0xFE, 0x6E, 0x02, 0x06, 0xFD, 0x1C, 0x03, 0xF4,
- 0x48, 0x41, 0x04, 0x87, 0xFC, 0xB0, 0x02, 0x23, 0xFE, 0x19, 0x01,
- 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F,
- 0xFF, 0xC6, 0x01, 0x9F, 0xFC, 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16,
- 0x9E, 0x43, 0xDD, 0xF6, 0x15, 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28,
- 0x00, 0xDF, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
- 0xCA, 0x01, 0x47, 0xFC, 0x28, 0x07, 0xB0, 0xF1, 0xF5, 0x2B, 0x60,
- 0x34, 0x9A, 0xF1, 0xBB, 0x06, 0xB3, 0xFC, 0x7D, 0x01, 0x73, 0xFF,
- 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9,
- 0x00, 0xDA, 0xFD, 0x0F, 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F,
- 0x97, 0xF3, 0xBD, 0x06, 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xAA, 0xFF, 0xB3, 0x00, 0xFA, 0xFE,
- 0x17, 0x01, 0x86, 0xFF, 0xAC, 0xFD, 0x16, 0x48, 0xAA, 0x0A, 0xEE,
- 0xF9, 0xFE, 0x03, 0x7A, 0xFD, 0x67, 0x01, 0x63, 0xFF, 0x28, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B,
- 0xFD, 0xC4, 0x04, 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA,
- 0x01, 0x01, 0x44, 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10,
- 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC,
- 0x08, 0x07, 0xA4, 0xF2, 0x6D, 0x24, 0xAD, 0x3A, 0x88, 0xF2, 0xDB,
- 0x05, 0x53, 0xFD, 0x19, 0x01, 0xA7, 0xFF, 0x10, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B,
- 0x06, 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07,
- 0x33, 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D,
- 0x00, 0xCB, 0xFF, 0x5C, 0x00, 0xAC, 0xFF, 0xD0, 0xFF, 0xCD, 0x01,
- 0x30, 0xF9, 0xC8, 0x45, 0xB6, 0x11, 0x6B, 0xF7, 0x2D, 0x05, 0xE9,
- 0xFC, 0xA8, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x25, 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1,
- 0xFA, 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01,
- 0xB8, 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
- 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x58, 0xFC, 0x82, 0x06, 0x3E, 0xF4,
- 0xBA, 0x1C, 0x07, 0x40, 0x79, 0xF4, 0x84, 0x04, 0x31, 0xFE, 0x96,
- 0x00, 0xE8, 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
- 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
- 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
- 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEA, 0xFF, 0x0B,
- 0x00, 0x51, 0x00, 0xAA, 0xFE, 0xC0, 0x03, 0xB8, 0xF5, 0x21, 0x42,
- 0x31, 0x19, 0x28, 0xF5, 0x27, 0x06, 0x7C, 0xFC, 0xD4, 0x01, 0x3A,
- 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, 0x00,
- 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, 0x50,
- 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, 0xFF,
- 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xBF,
- 0x01, 0xB2, 0xFC, 0xA9, 0x05, 0x55, 0xF6, 0x20, 0x15, 0x42, 0x44,
- 0x75, 0xF7, 0xBF, 0x02, 0x43, 0xFF, 0xFA, 0xFF, 0x36, 0x00, 0xDA,
- 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01,
- 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, 0x35, 0xB1,
- 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, 0x20, 0x00,
- 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE0, 0x00, 0xB3,
- 0xFD, 0x4B, 0x05, 0x4D, 0xF3, 0x45, 0x3D, 0xE0, 0x20, 0x4F, 0xF3,
- 0xD5, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, 0xFF, 0xDD, 0x00,
- 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, 0x7C, 0xF9, 0x35,
- 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x2C, 0x00, 0x56, 0xFF, 0x87, 0x01, 0x34, 0xFD, 0x8F,
- 0x04, 0xC0, 0xF8, 0xD9, 0x0D, 0x31, 0x47, 0x7B, 0xFB, 0x9C, 0x00,
- 0x7D, 0x00, 0x4D, 0xFF, 0x8A, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD,
- 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06,
- 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76,
- 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF,
- 0x1A, 0x00, 0x89, 0xFF, 0x53, 0x01, 0xF5, 0xFC, 0x63, 0x06, 0xE9,
- 0xF1, 0x63, 0x37, 0x85, 0x28, 0x09, 0xF2, 0x27, 0x07, 0x35, 0xFC,
- 0xDA, 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD1,
- 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, 0xFF, 0x2A, 0x02, 0x83, 0xF8,
- 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, 0x5D, 0x05, 0xD3, 0xFC, 0xB1,
- 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
- 0x73, 0xFF, 0x3F, 0x01, 0xD3, 0xFD, 0x4C, 0x03, 0x54, 0xFB, 0x1F,
- 0x07, 0xBB, 0x48, 0x7D, 0x00, 0x33, 0xFE, 0xCF, 0x01, 0x98, 0xFE,
- 0xE2, 0x00, 0x97, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
- 0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
- 0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
- 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5E, 0xFF,
- 0xA6, 0x01, 0x76, 0xFC, 0x01, 0x07, 0x7D, 0xF1, 0xAD, 0x30, 0xDC,
- 0x2F, 0x7F, 0xF1, 0x0C, 0x07, 0x6C, 0xFC, 0xAD, 0x01, 0x5A, 0xFF,
- 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C,
- 0x00, 0x7B, 0xFE, 0x0C, 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A,
- 0xCD, 0xF4, 0x4B, 0x06, 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35,
- 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x93, 0xFF, 0xEC, 0x00, 0x83, 0xFE,
- 0xF7, 0x01, 0xE8, 0xFD, 0x21, 0x01, 0xD2, 0x48, 0x64, 0x06, 0xA1,
- 0xFB, 0x26, 0x03, 0xE7, 0xFD, 0x35, 0x01, 0x76, 0xFF, 0x22, 0x00,
- 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5,
- 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8,
- 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B,
- 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x39, 0xFC,
- 0x29, 0x07, 0xEF, 0xF1, 0x62, 0x29, 0xA5, 0x36, 0xD0, 0xF1, 0x7B,
- 0x06, 0xE3, 0xFC, 0x5E, 0x01, 0x83, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
- 0x01, 0x00, 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84,
- 0x05, 0xFD, 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06,
- 0x37, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12,
- 0x00, 0xB5, 0xFF, 0x94, 0x00, 0x39, 0xFF, 0xA3, 0x00, 0x58, 0x00,
- 0x02, 0xFC, 0x73, 0x47, 0x0B, 0x0D, 0x0B, 0xF9, 0x6C, 0x04, 0x45,
- 0xFD, 0x80, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2A, 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31,
- 0xF9, 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00,
- 0x2E, 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36,
- 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x39, 0xFC, 0xE4, 0x06, 0x21, 0xF3,
- 0xC4, 0x21, 0xA5, 0x3C, 0x16, 0xF3, 0x72, 0x05, 0x9A, 0xFD, 0xEF,
- 0x00, 0xBC, 0xFF, 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
- 0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
- 0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
- 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD6, 0xFF, 0x3F,
- 0x00, 0xE7, 0xFF, 0x65, 0xFF, 0x85, 0x02, 0xDE, 0xF7, 0xA9, 0x44,
- 0x43, 0x14, 0x99, 0xF6, 0x8B, 0x05, 0xBF, 0xFC, 0xBA, 0x01, 0x43,
- 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF,
- 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB,
- 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00,
- 0x91, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
- 0x01, 0x72, 0xFC, 0x3F, 0x06, 0xEB, 0xF4, 0x12, 0x1A, 0xA1, 0x41,
- 0x63, 0xF5, 0xF3, 0x03, 0x8A, 0xFE, 0x63, 0x00, 0x02, 0x00, 0xEE,
- 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, 0xB1, 0x01,
- 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, 0x31, 0x7C,
- 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, 0x29, 0x00,
- 0xFD, 0xFF, 0x04, 0x00, 0xF4, 0xFF, 0xF1, 0xFF, 0x85, 0x00, 0x4E,
- 0xFE, 0x56, 0x04, 0xC3, 0xF4, 0x95, 0x40, 0xD8, 0x1B, 0x76, 0xF4,
- 0x6D, 0x06, 0x60, 0xFC, 0xDD, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
- 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, 0x01,
- 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, 0x60,
- 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAE, 0x01, 0xDB, 0xFC, 0x4D,
- 0x05, 0x24, 0xF7, 0x8E, 0x12, 0x6D, 0x45, 0xBC, 0xF8, 0x0C, 0x02,
- 0xAC, 0xFF, 0xC0, 0xFF, 0x52, 0x00, 0xCF, 0xFF, 0x0C, 0x00, 0xFD,
- 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x25, 0x07,
- 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, 0xF1, 0x56, 0x06, 0xFE,
- 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0x0D, 0x00, 0xAE, 0xFF, 0x0B, 0x01, 0x6A, 0xFD, 0xBA, 0x05, 0xB4,
- 0xF2, 0x58, 0x3B, 0x8A, 0x23, 0xCB, 0xF2, 0xFD, 0x06, 0x34, 0xFC,
- 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBB,
- 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, 0xBE, 0x00, 0x38, 0xFB,
- 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, 0x04, 0x2B, 0xFD, 0x8B,
- 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00,
- 0x5F, 0xFF, 0x70, 0x01, 0x68, 0xFD, 0x23, 0x04, 0xA2, 0xF9, 0x73,
- 0x0B, 0xE4, 0x47, 0x1B, 0xFD, 0xCD, 0xFF, 0xF0, 0x00, 0x0F, 0xFF,
- 0xA9, 0x00, 0xAE, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
- 0xFF, 0xE6, 0x01, 0x3F, 0xFC, 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20,
- 0x96, 0x3D, 0x69, 0xF3, 0x38, 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7,
- 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x78, 0xFF,
- 0x74, 0x01, 0xC2, 0xFC, 0xA7, 0x06, 0xA8, 0xF1, 0x25, 0x35, 0x1B,
- 0x2B, 0xC2, 0xF1, 0x2A, 0x07, 0x41, 0xFC, 0xCE, 0x01, 0x47, 0xFF,
- 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04,
- 0x00, 0x32, 0xFF, 0xDC, 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15,
- 0x34, 0xF6, 0xB7, 0x05, 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x23, 0x01,
- 0x0F, 0xFE, 0xD7, 0x02, 0x3B, 0xFC, 0xF5, 0x04, 0xED, 0x48, 0x70,
- 0x02, 0x52, 0xFD, 0x46, 0x02, 0x5A, 0xFE, 0xFF, 0x00, 0x8B, 0xFF,
- 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81,
- 0xFC, 0x1A, 0x06, 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5,
- 0xA6, 0x03, 0xB9, 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07,
- 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x53, 0xFF, 0xBB, 0x01, 0x5A, 0xFC,
- 0x1C, 0x07, 0x8D, 0xF1, 0x34, 0x2E, 0x48, 0x32, 0x81, 0xF1, 0xE7,
- 0x06, 0x8E, 0xFC, 0x96, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
- 0x04, 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B,
- 0x04, 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06,
- 0x55, 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
- 0x00, 0x9F, 0xFF, 0xCE, 0x00, 0xC2, 0xFE, 0x80, 0x01, 0xC6, 0xFE,
- 0x40, 0xFF, 0x81, 0x48, 0x9E, 0x08, 0xBA, 0xFA, 0x9A, 0x03, 0xAC,
- 0xFD, 0x51, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x2F, 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F,
- 0xF7, 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF,
- 0xA2, 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35,
- 0x00, 0x3D, 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1D, 0x07, 0x45, 0xF2,
- 0xC6, 0x26, 0xD3, 0x38, 0x24, 0xF2, 0x2D, 0x06, 0x1B, 0xFD, 0x3B,
- 0x01, 0x95, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00,
- 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
- 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
- 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC1, 0xFF, 0x76,
- 0x00, 0x76, 0xFF, 0x32, 0x00, 0x22, 0x01, 0x76, 0xFA, 0xA3, 0x46,
- 0x7D, 0x0F, 0x2C, 0xF8, 0xD5, 0x04, 0x13, 0xFD, 0x96, 0x01, 0x51,
- 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, 0xFF,
- 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, 0x2C,
- 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, 0x00,
- 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
- 0x01, 0x47, 0xFC, 0xB5, 0x06, 0xB0, 0xF3, 0x19, 0x1F, 0x7E, 0x3E,
- 0xC4, 0xF3, 0xFA, 0x04, 0xE7, 0xFD, 0xC1, 0x00, 0xD3, 0xFF, 0xFF,
- 0xFF, 0x02, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, 0x82, 0x01,
- 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, 0x2C, 0xA8,
- 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, 0x30, 0x00,
- 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, 0x23, 0x00, 0x20, 0x00, 0x00,
- 0xFF, 0x31, 0x03, 0xAD, 0xF6, 0x65, 0x43, 0xDC, 0x16, 0xD1, 0xF5,
- 0xE1, 0x05, 0x99, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, 0x01, 0x2D, 0xFE,
- 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, 0x73, 0x03, 0xE0,
- 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, 0xFF, 0x1E, 0x00,
- 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCC, 0x01, 0x91, 0xFC, 0xF3,
- 0x05, 0xA6, 0xF5, 0x70, 0x17, 0x17, 0x43, 0x6D, 0xF6, 0x56, 0x03,
- 0xEA, 0xFE, 0x2D, 0x00, 0x1D, 0x00, 0xE4, 0xFF, 0x08, 0x00, 0xFD,
- 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07,
- 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2,
- 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00,
- 0xFD, 0xFF, 0xD8, 0xFF, 0xB7, 0x00, 0xF9, 0xFD, 0xDE, 0x04, 0xEF,
- 0xF3, 0xE4, 0x3E, 0x81, 0x1E, 0xD2, 0xF3, 0xA9, 0x06, 0x4B, 0xFC,
- 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA5,
- 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, 0x01, 0x33, 0xFF, 0x5A, 0xFE,
- 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, 0xD2, 0x03, 0x90, 0xFD, 0x5E,
- 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
- 0x4F, 0xFF, 0x9A, 0x01, 0x08, 0xFD, 0xEB, 0x04, 0xFC, 0xF7, 0x0A,
- 0x10, 0x70, 0x46, 0x22, 0xFA, 0x4D, 0x01, 0x19, 0x00, 0x84, 0xFF,
- 0x70, 0x00, 0xC4, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
- 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
- 0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
- 0xFF, 0x13, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x99, 0xFF,
- 0x33, 0x01, 0x29, 0xFD, 0x1A, 0x06, 0x3B, 0xF2, 0x4B, 0x39, 0x30,
- 0x26, 0x5B, 0xF2, 0x19, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF,
- 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95,
- 0xFF, 0xFA, 0xFF, 0x83, 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10,
- 0xBF, 0xF7, 0x07, 0x05, 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x56, 0x01,
- 0xA0, 0xFD, 0xB3, 0x03, 0x87, 0xFA, 0x1F, 0x09, 0x6A, 0x48, 0xD9,
- 0xFE, 0xF6, 0xFE, 0x65, 0x01, 0xD0, 0xFE, 0xC7, 0x00, 0xA2, 0xFF,
- 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50,
- 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4,
- 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03,
- 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x69, 0xFF, 0x90, 0x01, 0x96, 0xFC,
- 0xDD, 0x06, 0x85, 0xF1, 0xD0, 0x32, 0xA6, 0x2D, 0x94, 0xF1, 0x20,
- 0x07, 0x54, 0xFC, 0xBF, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
- 0x07, 0x00, 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83,
- 0x03, 0x20, 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06,
- 0x88, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
- 0x00, 0x89, 0xFF, 0x06, 0x01, 0x4C, 0xFE, 0x60, 0x02, 0x1F, 0xFD,
- 0xE2, 0x02, 0xF3, 0x48, 0x7D, 0x04, 0x6E, 0xFC, 0xBD, 0x02, 0x1C,
- 0xFE, 0x1C, 0x01, 0x80, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0x33, 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07,
- 0xF6, 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF,
- 0x11, 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
- 0x00, 0x49, 0xFF, 0xCB, 0x01, 0x45, 0xFC, 0x29, 0x07, 0xB6, 0xF1,
- 0xAD, 0x2B, 0xA2, 0x34, 0x9E, 0xF1, 0xB4, 0x06, 0xB8, 0xFC, 0x7A,
- 0x01, 0x75, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00,
- 0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
- 0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
- 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAB, 0xFF, 0xAF,
- 0x00, 0x01, 0xFF, 0x0A, 0x01, 0x9E, 0xFF, 0x7C, 0xFD, 0x03, 0x48,
- 0xED, 0x0A, 0xD5, 0xF9, 0x0A, 0x04, 0x74, 0xFD, 0x6A, 0x01, 0x62,
- 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF,
- 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1,
- 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00,
- 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
- 0x01, 0x33, 0xFC, 0x04, 0x07, 0xB1, 0xF2, 0x21, 0x24, 0xE6, 0x3A,
- 0x97, 0xF2, 0xD0, 0x05, 0x5B, 0xFD, 0x15, 0x01, 0xA9, 0xFF, 0x0F,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, 0x45, 0x01,
- 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, 0x27, 0x2B,
- 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, 0x34, 0x00,
- 0xFD, 0xFF, 0x0D, 0x00, 0xCD, 0xFF, 0x59, 0x00, 0xB3, 0xFF, 0xC4,
- 0xFF, 0xE2, 0x01, 0x09, 0xF9, 0xAA, 0x45, 0xFE, 0x11, 0x54, 0xF7,
- 0x38, 0x05, 0xE4, 0xFC, 0xAA, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, 0xFD,
- 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, 0x89,
- 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, 0x00,
- 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5B, 0xFC, 0x7B,
- 0x06, 0x50, 0xF4, 0x6E, 0x1C, 0x36, 0x40, 0x92, 0xF4, 0x75, 0x04,
- 0x3B, 0xFE, 0x91, 0x00, 0xEB, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD,
- 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, 0x84, 0xFC, 0xF3, 0x06,
- 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, 0xF1, 0x16, 0x07, 0x61,
- 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00,
- 0xEC, 0xFF, 0x08, 0x00, 0x57, 0x00, 0x9F, 0xFE, 0xD1, 0x03, 0x9B,
- 0xF5, 0xF7, 0x41, 0x7C, 0x19, 0x13, 0xF5, 0x2F, 0x06, 0x78, 0xFC,
- 0xD5, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8F,
- 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, 0x91, 0xFD, 0xE3, 0x01,
- 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, 0x02, 0xFE, 0xFD, 0x2B,
- 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
- 0x42, 0xFF, 0xBD, 0x01, 0xB6, 0xFC, 0x9F, 0x05, 0x6C, 0xF6, 0xD6,
- 0x14, 0x65, 0x44, 0x98, 0xF7, 0xAC, 0x02, 0x4E, 0xFF, 0xF4, 0xFF,
- 0x39, 0x00, 0xD9, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45,
- 0xFF, 0xD2, 0x01, 0x3D, 0xFC, 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A,
- 0xC6, 0x35, 0xB7, 0xF1, 0x96, 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D,
- 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xC1, 0xFF,
- 0xE5, 0x00, 0xAA, 0xFD, 0x58, 0x05, 0x3A, 0xF3, 0x11, 0x3D, 0x2C,
- 0x21, 0x3F, 0xF3, 0xDA, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
- 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20,
- 0xFF, 0xD0, 0x00, 0x07, 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C,
- 0x63, 0xF9, 0x42, 0x04, 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x85, 0x01,
- 0x39, 0xFD, 0x84, 0x04, 0xD9, 0xF8, 0x95, 0x0D, 0x48, 0x47, 0xA7,
- 0xFB, 0x86, 0x00, 0x8A, 0x00, 0x46, 0xFF, 0x8E, 0x00, 0xB8, 0xFF,
- 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35,
- 0xFC, 0xF3, 0x06, 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2,
- 0x9C, 0x05, 0x7E, 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01,
- 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x87, 0xFF, 0x57, 0x01, 0xEF, 0xFC,
- 0x6B, 0x06, 0xE0, 0xF1, 0x23, 0x37, 0xCE, 0x28, 0x01, 0xF2, 0x28,
- 0x07, 0x36, 0xFC, 0xD9, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
- 0x0B, 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F,
- 0x02, 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05,
- 0xCF, 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x23, 0x00, 0x74, 0xFF, 0x3C, 0x01, 0xDA, 0xFD, 0x40, 0x03,
- 0x6E, 0xFB, 0xE1, 0x06, 0xC3, 0x48, 0xB3, 0x00, 0x1A, 0xFE, 0xDC,
- 0x01, 0x91, 0xFE, 0xE5, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
- 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6,
- 0xF4, 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE,
- 0x77, 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A,
- 0x00, 0x5C, 0xFF, 0xA8, 0x01, 0x73, 0xFC, 0x05, 0x07, 0x7D, 0xF1,
- 0x67, 0x30, 0x21, 0x30, 0x7E, 0xF1, 0x08, 0x07, 0x6F, 0xFC, 0xAB,
- 0x01, 0x5B, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF0, 0xFF,
- 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
- 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
- 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE8,
- 0x00, 0x8A, 0xFE, 0xE9, 0x01, 0x01, 0xFE, 0xEA, 0x00, 0xCB, 0x48,
- 0xA2, 0x06, 0x87, 0xFB, 0x33, 0x03, 0xE0, 0xFD, 0x39, 0x01, 0x75,
- 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF,
- 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, 0xFD,
- 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, 0x00,
- 0xD3, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD8,
- 0x01, 0x37, 0xFC, 0x29, 0x07, 0xF8, 0xF1, 0x19, 0x29, 0xE5, 0x36,
- 0xD8, 0xF1, 0x73, 0x06, 0xE9, 0xFC, 0x5B, 0x01, 0x85, 0xFF, 0x1C,
- 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, 0xFB, 0x00,
- 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, 0x22, 0xFC,
- 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00,
- 0xFD, 0xFF, 0x12, 0x00, 0xB7, 0xFF, 0x91, 0x00, 0x40, 0xFF, 0x96,
- 0x00, 0x6F, 0x00, 0xD5, 0xFB, 0x5E, 0x47, 0x50, 0x0D, 0xF2, 0xF8,
- 0x78, 0x04, 0x3F, 0xFD, 0x82, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, 0x01, 0x53, 0xFD,
- 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, 0x76, 0xFC, 0x1F,
- 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, 0xFF, 0x13, 0x00,
- 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xDF,
- 0x06, 0x30, 0xF3, 0x78, 0x21, 0xDB, 0x3C, 0x28, 0xF3, 0x65, 0x05,
- 0xA2, 0xFD, 0xEA, 0x00, 0xBE, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE,
- 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06,
- 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C,
- 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
- 0xD8, 0xFF, 0x3C, 0x00, 0xEE, 0xFF, 0x5A, 0xFF, 0x98, 0x02, 0xBB,
- 0xF7, 0x87, 0x44, 0x8C, 0x14, 0x83, 0xF6, 0x95, 0x05, 0xBA, 0xFC,
- 0xBB, 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
- 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, 0xFD, 0x05, 0x03, 0xE1, 0xFB,
- 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, 0xAA, 0xFD, 0x18, 0x02, 0x72,
- 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00,
- 0x39, 0xFF, 0xD6, 0x01, 0x75, 0xFC, 0x37, 0x06, 0xFF, 0xF4, 0xC7,
- 0x19, 0xCC, 0x41, 0x7F, 0xF5, 0xE2, 0x03, 0x95, 0xFE, 0x5D, 0x00,
- 0x05, 0x00, 0xED, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
- 0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
- 0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
- 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF5, 0xFF, 0xEE, 0xFF,
- 0x8B, 0x00, 0x44, 0xFE, 0x65, 0x04, 0xAA, 0xF4, 0x66, 0x40, 0x23,
- 0x1C, 0x63, 0xF4, 0x74, 0x06, 0x5D, 0xFC, 0xDE, 0x01, 0x37, 0xFF,
- 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA,
- 0xFE, 0xAE, 0x01, 0x70, 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07,
- 0x14, 0xFB, 0x6D, 0x03, 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAC, 0x01,
- 0xDF, 0xFC, 0x43, 0x05, 0x3C, 0xF7, 0x46, 0x12, 0x8D, 0x45, 0xE2,
- 0xF8, 0xF7, 0x01, 0xB8, 0xFF, 0xB9, 0xFF, 0x56, 0x00, 0xCE, 0xFF,
- 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34,
- 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2,
- 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAB, 0xFF, 0x10, 0x01, 0x62, 0xFD,
- 0xC5, 0x05, 0xA5, 0xF2, 0x1F, 0x3B, 0xD6, 0x23, 0xBE, 0xF2, 0x01,
- 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x10, 0x00, 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4,
- 0x00, 0x0C, 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04,
- 0x26, 0xFD, 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6D, 0x01, 0x6E, 0xFD, 0x17, 0x04,
- 0xBC, 0xF9, 0x30, 0x0B, 0xF4, 0x47, 0x4B, 0xFD, 0xB5, 0xFF, 0xFD,
- 0x00, 0x08, 0xFF, 0xAC, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76,
- 0xF3, 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD,
- 0xD4, 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21,
- 0x00, 0x77, 0xFF, 0x77, 0x01, 0xBD, 0xFC, 0xAE, 0x06, 0xA3, 0xF1,
- 0xE3, 0x34, 0x64, 0x2B, 0xBC, 0xF1, 0x2A, 0x07, 0x43, 0xFC, 0xCD,
- 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDD, 0xFF,
- 0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
- 0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
- 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F,
- 0xFF, 0x20, 0x01, 0x16, 0xFE, 0xCA, 0x02, 0x54, 0xFC, 0xB9, 0x04,
- 0xF2, 0x48, 0xA9, 0x02, 0x39, 0xFD, 0x53, 0x02, 0x53, 0xFE, 0x03,
- 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF,
- 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89,
- 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00,
- 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBD,
- 0x01, 0x57, 0xFC, 0x1E, 0x07, 0x90, 0xF1, 0xED, 0x2D, 0x8C, 0x32,
- 0x83, 0xF1, 0xE2, 0x06, 0x92, 0xFC, 0x93, 0x01, 0x68, 0xFF, 0x26,
- 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, 0xA4, 0x00,
- 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, 0x1D, 0x10,
- 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, 0x36, 0x00,
- 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, 0xCA, 0x00, 0xC9, 0xFE, 0x73,
- 0x01, 0xDE, 0xFE, 0x0C, 0xFF, 0x76, 0x48, 0xDE, 0x08, 0xA1, 0xFA,
- 0xA6, 0x03, 0xA6, 0xFD, 0x53, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00,
- 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, 0xFC,
- 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, 0x98,
- 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, 0x00,
- 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x32, 0xFC, 0x1B,
- 0x07, 0x50, 0xF2, 0x7B, 0x26, 0x11, 0x39, 0x2F, 0xF2, 0x23, 0x06,
- 0x22, 0xFD, 0x37, 0x01, 0x97, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, 0x41, 0xFD, 0xF6, 0x05,
- 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, 0xF2, 0x0F, 0x07, 0x31,
- 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00,
- 0xC2, 0xFF, 0x73, 0x00, 0x7D, 0xFF, 0x25, 0x00, 0x38, 0x01, 0x4C,
- 0xFA, 0x89, 0x46, 0xC3, 0x0F, 0x14, 0xF8, 0xE0, 0x04, 0x0D, 0xFD,
- 0x98, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
- 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, 0xDF, 0x03, 0x2E, 0xFA,
- 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, 0xFF, 0x38, 0x01, 0xE9,
- 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE4, 0x01, 0x49, 0xFC, 0xAF, 0x06, 0xC1, 0xF3, 0xCD,
- 0x1E, 0xB1, 0x3E, 0xD9, 0xF3, 0xEC, 0x04, 0xF0, 0xFD, 0xBC, 0x00,
- 0xD5, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F,
- 0xFF, 0x85, 0x01, 0xA6, 0xFC, 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33,
- 0xAB, 0x2C, 0xA3, 0xF1, 0x26, 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D,
- 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE2, 0xFF, 0x20, 0x00,
- 0x26, 0x00, 0xF5, 0xFE, 0x43, 0x03, 0x8D, 0xF6, 0x3C, 0x43, 0x25,
- 0x17, 0xBB, 0xF5, 0xEA, 0x05, 0x95, 0xFC, 0xCA, 0x01, 0x3D, 0xFF,
- 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11,
- 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48,
- 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84,
- 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
- 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A,
- 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00,
- 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1,
- 0xFD, 0x4E, 0x05, 0x4A, 0xF3, 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3,
- 0xD6, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE,
- 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7,
- 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00,
- 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, 0x01, 0x4C, 0xFC, 0x26,
- 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, 0x8F, 0xF1, 0xCA, 0x06,
- 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x16,
- 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF,
- 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A,
- 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF,
- 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, 0x07, 0x84,
- 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, 0x41, 0xFD,
- 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8,
- 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9,
- 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2,
- 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
- 0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
- 0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0x07, 0x00, 0xE8, 0xFF, 0x12,
- 0x00, 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42,
- 0x76, 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B,
- 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF,
- 0xC3, 0x01, 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7,
- 0x43, 0x20, 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00,
- 0xDD, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4,
- 0x00, 0xC8, 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20,
- 0x76, 0xF3, 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01,
- 0x26, 0xFD, 0xAD, 0x04, 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C,
- 0xFB, 0xD4, 0x00, 0x5D, 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF,
- 0x10, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04,
- 0xFD, 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2,
- 0x23, 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD,
- 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x46, 0x01, 0xC3, 0xFD,
- 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, 0xA6, 0x48, 0xF8, 0xFF, 0x70,
- 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, 0x00, 0x9A, 0xFF, 0x19, 0x00,
- 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
- 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
- 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B,
- 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, 0x02, 0xAA, 0xFD,
- 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, 0x05, 0x03, 0xF7,
- 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF,
- 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, 0xDC,
- 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, 0xFC,
- 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xB2,
- 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, 0xFC,
- 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, 0x79,
- 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
- 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
- 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
- 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xD3, 0xFF, 0x47,
- 0x00, 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44,
- 0x8D, 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45,
- 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF,
- 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32,
- 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF,
- 0xF0, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77,
- 0x00, 0x67, 0xFE, 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B,
- 0xA6, 0xF4, 0x5A, 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36,
- 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01,
- 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E,
- 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF,
- 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E,
- 0xFD, 0x9C, 0x05, 0xDC, 0xF2, 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2,
- 0xF3, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x76, 0x01, 0x59, 0xFD,
- 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, 0xB6, 0x47, 0xA4, 0xFC, 0x07,
- 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, 0x00, 0xB1, 0xFF, 0x13, 0x00,
- 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, 0x01, 0xCF, 0xFC, 0x96,
- 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, 0xD4, 0xF1, 0x2B, 0x07,
- 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00,
- 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02,
- 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25,
- 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, 0x00, 0xFD, 0xFF,
- 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, 0x07, 0x85,
- 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, 0x84, 0xFC,
- 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9C,
- 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF,
- 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49,
- 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
- 0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
- 0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
- 0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F,
- 0x00, 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46,
- 0xCD, 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53,
- 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
- 0xE5, 0x01, 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE,
- 0x3D, 0x91, 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF,
- 0x02, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11,
- 0x00, 0x1B, 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16,
- 0x07, 0xF6, 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33,
- 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01,
- 0x88, 0xFC, 0x09, 0x06, 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20,
- 0xF6, 0x83, 0x03, 0xCF, 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF,
- 0x07, 0x00, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10,
- 0xFE, 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3,
- 0x99, 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE,
- 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, 0xFF, 0xA0, 0x01, 0xFB, 0xFC,
- 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, 0x2B, 0x46, 0xBB, 0xF9, 0x83,
- 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, 0x00, 0xC7, 0xFF, 0x0E, 0x00,
- 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
- 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
- 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00,
- 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, 0xFD, 0xD2, 0x03,
- 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, 0x33, 0xFF, 0x45,
- 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, 0x00, 0xFD, 0xFF,
- 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, 0x8C,
- 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, 0xFC,
- 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x86,
- 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, 0x03,
- 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, 0x14,
- 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00,
- 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
- 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
- 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8,
- 0x00, 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48,
- 0x47, 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64,
- 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF,
- 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54,
- 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF,
- 0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2,
- 0xFF, 0xE2, 0xFF, 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11,
- 0x8F, 0xF7, 0x1D, 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F,
- 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01,
- 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55,
- 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF,
- 0x04, 0x00, 0x07, 0x00, 0xE9, 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9,
- 0xFE, 0xA6, 0x03, 0xE4, 0xF5, 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5,
- 0x1A, 0x06, 0x81, 0xFC, 0xD2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE,
- 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC1, 0x01, 0xAB, 0xFC,
- 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, 0x0B, 0x44, 0x42, 0xF7, 0xDC,
- 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, 0x00, 0xDC, 0xFF, 0x09, 0x00,
- 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, 0x00, 0xBF, 0xFD, 0x38,
- 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, 0x66, 0xF3, 0xCE, 0x06,
- 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
- 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04,
- 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A,
- 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
- 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, 0x06, 0xF7,
- 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, 0x34, 0xFC,
- 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24,
- 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB,
- 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3,
- 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00,
- 0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
- 0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
- 0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1,
- 0x00, 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48,
- 0x07, 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78,
- 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF,
- 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46,
- 0x36, 0xC5, 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF,
- 0x1E, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E,
- 0xFF, 0xB6, 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C,
- 0x31, 0xF9, 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A,
- 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01,
- 0x37, 0xFC, 0xEB, 0x06, 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD,
- 0xF2, 0x84, 0x05, 0x8D, 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00,
- 0x01, 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77,
- 0xFF, 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6,
- 0x7C, 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF,
- 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD9, 0x01, 0x6D, 0xFC,
- 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, 0x5F, 0x41, 0x3A, 0xF5, 0x0C,
- 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
- 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
- 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
- 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF,
- 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, 0xFC, 0x5D, 0x05,
- 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, 0x2A, 0x02, 0x9A,
- 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, 0xCC,
- 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, 0xFC,
- 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29,
- 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, 0xF9,
- 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, 0x19,
- 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x20, 0x00,
- 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
- 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
- 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C,
- 0xFF, 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05,
- 0xEA, 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA,
- 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF,
- 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3,
- 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF,
- 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8,
- 0xFE, 0x93, 0x01, 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08,
- 0xE1, 0xFA, 0x86, 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25,
- 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01,
- 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14,
- 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00,
- 0xFF, 0xFF, 0x10, 0x00, 0xBF, 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44,
- 0x00, 0x01, 0x01, 0xB6, 0xFA, 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8,
- 0xC4, 0x04, 0x1B, 0xFD, 0x92, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF,
- 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x44, 0xFC,
- 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, 0x31, 0x3E, 0xA5, 0xF3, 0x0F,
- 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, 0xFF, 0x01, 0x00, 0x02, 0x00,
- 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, 0x00, 0x10, 0xFF, 0x15,
- 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, 0xF1, 0xF5, 0xD3, 0x05,
- 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
- 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06,
- 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9,
- 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0x03, 0x00,
- 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, 0x04, 0x10,
- 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, 0x4E, 0xFC,
- 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E,
- 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7,
- 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E,
- 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x13, 0x00,
- 0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
- 0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
- 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68,
- 0xFF, 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09,
- 0x57, 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2,
- 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF,
- 0x8B, 0x01, 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A,
- 0x2D, 0x9A, 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF,
- 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42,
- 0xFE, 0x74, 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04,
- 0x94, 0xFC, 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F,
- 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01,
- 0x48, 0xFC, 0x28, 0x07, 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97,
- 0xF1, 0xBE, 0x06, 0xB0, 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00,
- 0xFE, 0xFF, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D,
- 0x01, 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9,
- 0xF8, 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00,
- 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC,
- 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, 0x8F, 0x3A, 0x82, 0xF2, 0xE1,
- 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, 0xFF, 0x10, 0x00, 0x00, 0x00,
- 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
- 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
- 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, 0xFC, 0x85, 0x06,
- 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, 0x8C, 0x04, 0x2C,
- 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, 0x00, 0x06, 0x00,
- 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, 0xC7,
- 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, 0xFC,
- 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32,
- 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, 0xF6,
- 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, 0xFE,
- 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x05, 0x00,
- 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
- 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
- 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x56,
- 0xFF, 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D,
- 0x26, 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89,
- 0x00, 0xBA, 0xFF, 0x11, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF,
- 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60,
- 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF,
- 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40,
- 0x01, 0xD0, 0xFD, 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48,
- 0x62, 0x00, 0x3F, 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98,
- 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01,
- 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80,
- 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00,
- 0xFD, 0xFF, 0x1B, 0x00, 0x93, 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD,
- 0x01, 0xDC, 0xFD, 0x3C, 0x01, 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB,
- 0x1F, 0x03, 0xEA, 0xFD, 0x34, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00,
- 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, 0xFF, 0xD6, 0x01, 0x39, 0xFC,
- 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, 0x85, 0x36, 0xCC, 0xF1, 0x7F,
- 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
- 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, 0xFF, 0xA9, 0x00, 0x4D,
- 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, 0x18, 0xF9, 0x66, 0x04,
- 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06,
- 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96,
- 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, 0x00, 0x0B, 0x00,
- 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, 0x02, 0xF0,
- 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, 0xC1, 0xFC,
- 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35,
- 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4,
- 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66,
- 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0x05, 0x00, 0xF4, 0xFF,
- 0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
- 0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
- 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x47,
- 0xFF, 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12,
- 0x5C, 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51,
- 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF,
- 0x09, 0x01, 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64,
- 0x23, 0xD2, 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF,
- 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71,
- 0x01, 0x65, 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47,
- 0x03, 0xFD, 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE,
- 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01,
- 0xC4, 0xFC, 0xA4, 0x06, 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6,
- 0xF1, 0x2A, 0x07, 0x40, 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00,
- 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C,
- 0xFE, 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02,
- 0x5E, 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C,
- 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0xBA, 0x01, 0x5B, 0xFC,
- 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, 0x26, 0x32, 0x80, 0xF1, 0xEA,
- 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
- 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
- 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
- 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD,
- 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, 0xFC, 0x1E, 0x07,
- 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, 0x32, 0x06, 0x18,
- 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
- 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, 0x8B,
- 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, 0xFD,
- 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
- 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, 0xF3,
- 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, 0xC4,
- 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0xE1, 0xFF,
- 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
- 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
- 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D,
- 0xFF, 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17,
- 0x02, 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B,
- 0x00, 0xE4, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF,
- 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B,
- 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF,
- 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C,
- 0x01, 0x05, 0xFD, 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46,
- 0x0D, 0xFA, 0x58, 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4,
- 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01,
- 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61,
- 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00,
- 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D,
- 0xFD, 0xB9, 0x03, 0x7B, 0xFA, 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE,
- 0x03, 0xFF, 0x5F, 0x01, 0xD4, 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16,
- 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, 0xFF, 0x8E, 0x01, 0x99, 0xFC,
- 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, 0x82, 0x2D, 0x96, 0xF1, 0x21,
- 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
- 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, 0xFE, 0x67, 0x02, 0x13,
- 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, 0x7A, 0xFC, 0xB6, 0x02,
- 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD,
- 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07,
- 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5,
- 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x15, 0x00,
- 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, 0xFF, 0x94,
- 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, 0x77, 0xFD,
- 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36,
- 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2,
- 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17,
- 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xCC, 0xFF,
- 0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
- 0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
- 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37,
- 0xFF, 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C,
- 0x1F, 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA,
- 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00,
- 0x54, 0x00, 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56,
- 0x19, 0x1E, 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF,
- 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE,
- 0x01, 0xB4, 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44,
- 0x86, 0xF7, 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9,
- 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00,
- 0xAE, 0xFD, 0x52, 0x05, 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47,
- 0xF3, 0xD8, 0x06, 0x3C, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00,
- 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36,
- 0xFD, 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB,
- 0x91, 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11,
- 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, 0xFF, 0x55, 0x01, 0xF2, 0xFC,
- 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, 0xAA, 0x28, 0x05, 0xF2, 0x27,
- 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
- 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
- 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
- 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFD,
- 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, 0xFC, 0x03, 0x07,
- 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, 0x0A, 0x07, 0x6E,
- 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x1A, 0x00,
- 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, 0x05,
- 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, 0xFD,
- 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33,
- 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, 0xF1,
- 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, 0x5C,
- 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
- 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
- 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
- 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37,
- 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21,
- 0xC0, 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD,
- 0xFF, 0x07, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00,
- 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68,
- 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF,
- 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
- 0x01, 0x73, 0xFC, 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41,
- 0x71, 0xF5, 0xEB, 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED,
- 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00,
- 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C,
- 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00,
- 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD,
- 0xFC, 0x48, 0x05, 0x30, 0xF7, 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8,
- 0x01, 0x02, 0xB2, 0xFF, 0xBD, 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C,
- 0x00, 0x00, 0x00, 0x0E, 0x00, 0xAC, 0xFF, 0x0E, 0x01, 0x66, 0xFD,
- 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, 0xB0, 0x23, 0xC4, 0xF2, 0xFF,
- 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, 0x01, 0x6B, 0xFD, 0x1D,
- 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, 0x33, 0xFD, 0xC1, 0xFF,
- 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, 0xFF, 0x14, 0x00, 0xFE,
- 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06,
- 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42,
- 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00,
- 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, 0x02, 0x47,
- 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, 0x4D, 0x02,
- 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E,
- 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1,
- 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94,
- 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
- 0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
- 0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
- 0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C,
- 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26,
- 0xF2, 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96,
- 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00,
- 0x7A, 0xFF, 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0,
- 0x0F, 0x20, 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF,
- 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
- 0x01, 0x48, 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E,
- 0xCF, 0xF3, 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF,
- 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00,
- 0xFA, 0xFE, 0x3A, 0x03, 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6,
- 0xF5, 0xE6, 0x05, 0x97, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00,
- 0xFE, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93,
- 0xFC, 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6,
- 0x4D, 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08,
- 0x00, 0x03, 0x00, 0xFE, 0xFF, 0xD7, 0xFF, 0xBA, 0x00, 0xF4, 0xFD,
- 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, 0xA7, 0x1E, 0xCA, 0xF3, 0xAC,
- 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
- 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
- 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
- 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0xFF,
- 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, 0xFD, 0x1E, 0x06,
- 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, 0x1A, 0x07, 0x31,
- 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00,
- 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, 0x94,
- 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, 0x01,
- 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26,
- 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, 0xF1,
- 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, 0xBE,
- 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
- 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
- 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
- 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49,
- 0xFF, 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B,
- 0xC3, 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76,
- 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00,
- 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E,
- 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF,
- 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
- 0x01, 0x33, 0xFC, 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B,
- 0x9E, 0xF2, 0xCB, 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E,
- 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF,
- 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48,
- 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00,
- 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C,
- 0xFC, 0x78, 0x06, 0x5A, 0xF4, 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4,
- 0x6D, 0x04, 0x3F, 0xFE, 0x8E, 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04,
- 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x5A, 0x00, 0x9A, 0xFE,
- 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, 0xA1, 0x19, 0x09, 0xF5, 0x33,
- 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
- 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, 0x01, 0xB8, 0xFC, 0x9A,
- 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, 0xA9, 0xF7, 0xA2, 0x02,
- 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, 0xFF, 0x0A, 0x00, 0x01,
- 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05,
- 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B,
- 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00,
- 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, 0x04, 0xE6,
- 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, 0x90, 0x00,
- 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFE, 0xFF, 0x1C,
- 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1,
- 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8,
- 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00,
- 0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
- 0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
- 0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C,
- 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30,
- 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C,
- 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00,
- 0x8E, 0xFE, 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1,
- 0x06, 0x7B, 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF,
- 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8,
- 0x01, 0x37, 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37,
- 0xDC, 0xF1, 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C,
- 0x00, 0xFE, 0xFF, 0x11, 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF,
- 0x90, 0x00, 0x7A, 0x00, 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6,
- 0xF8, 0x7E, 0x04, 0x3C, 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00,
- 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B,
- 0xFC, 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3,
- 0x5F, 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01,
- 0x00, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, 0x00, 0xF1, 0xFF, 0x54, 0xFF,
- 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, 0xB1, 0x14, 0x77, 0xF6, 0x9A,
- 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
- 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
- 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
- 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x04,
- 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, 0xFE, 0x6D, 0x04,
- 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, 0x78, 0x06, 0x5C,
- 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
- 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, 0x48,
- 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, 0xFF,
- 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0E,
- 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, 0xF2,
- 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, 0xE5,
- 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00,
- 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
- 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
- 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76,
- 0xFF, 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34,
- 0x89, 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49,
- 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF,
- 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2,
- 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01,
- 0x8A, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE,
- 0x01, 0x56, 0xFC, 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32,
- 0x84, 0xF1, 0xE0, 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26,
- 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE,
- 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94,
- 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00,
- 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31,
- 0xFC, 0x1A, 0x07, 0x56, 0xF2, 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2,
- 0x1E, 0x06, 0x25, 0xFD, 0x35, 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF,
- 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, 0x00, 0x81, 0xFF, 0x1F, 0x00,
- 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, 0xE7, 0x0F, 0x08, 0xF8, 0xE6,
- 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
- 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x4A, 0xFC, 0xAC,
- 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, 0xE4, 0xF3, 0xE5, 0x04,
- 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0x08,
- 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03,
- 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93,
- 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFE, 0xFF,
- 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, 0x05, 0xC6,
- 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, 0xFA, 0xFE,
- 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFF,
- 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3,
- 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4,
- 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00,
- 0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
- 0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
- 0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96,
- 0xFF, 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38,
- 0xA0, 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C,
- 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF,
- 0x52, 0x01, 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C,
- 0x48, 0x26, 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00,
- 0xA0, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94,
- 0x01, 0x90, 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E,
- 0x8E, 0xF1, 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E,
- 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE,
- 0x4D, 0x02, 0x45, 0xFD, 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47,
- 0xFC, 0xD1, 0x02, 0x12, 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00,
- 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42,
- 0xFC, 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1,
- 0xAB, 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
- 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, 0x00, 0x0C, 0xFF, 0xF7, 0x00,
- 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, 0x51, 0x0B, 0xAF, 0xF9, 0x1D,
- 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00,
- 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
- 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
- 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x0C,
- 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, 0xFF, 0x01, 0x02,
- 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, 0x48, 0x05, 0xDD,
- 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
- 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, 0x6C,
- 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, 0xFE,
- 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xED,
- 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, 0xF5,
- 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, 0xD7,
- 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00,
- 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
- 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
- 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x07, 0x00, 0xBD,
- 0xFF, 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C,
- 0x9E, 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37,
- 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF,
- 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69,
- 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00,
- 0xB6, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C,
- 0x01, 0xE6, 0xFC, 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29,
- 0xF3, 0xF1, 0x29, 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33,
- 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01,
- 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05,
- 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF,
- 0x1A, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E,
- 0xFC, 0x0A, 0x07, 0x7E, 0xF1, 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1,
- 0x03, 0x07, 0x75, 0xFC, 0xA7, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD,
- 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, 0x00, 0x95, 0xFE, 0xD5, 0x01,
- 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, 0x00, 0x07, 0x61, 0xFB, 0x46,
- 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, 0xFF, 0x23, 0x00, 0x00, 0x00,
- 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, 0x01, 0x36, 0xFC, 0x27,
- 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, 0xE4, 0xF1, 0x67, 0x06,
- 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x11,
- 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00,
- 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36,
- 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF,
- 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, 0x06, 0x47,
- 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, 0xAE, 0xFD,
- 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD9,
- 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7,
- 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE,
- 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00,
- 0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
- 0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
- 0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF7, 0xFF, 0xEA,
- 0xFF, 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40,
- 0x94, 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37,
- 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
- 0xA9, 0x01, 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8,
- 0x45, 0x1C, 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00,
- 0xCC, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17,
- 0x01, 0x57, 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24,
- 0xAA, 0xF2, 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01,
- 0x77, 0xFD, 0x04, 0x04, 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94,
- 0xFD, 0x92, 0xFF, 0x10, 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF,
- 0x15, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5,
- 0xFC, 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1,
- 0x29, 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD,
- 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x1B, 0x01, 0x20, 0xFE,
- 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, 0xF4, 0x48, 0xFF, 0x02, 0x13,
- 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, 0x01, 0x88, 0xFF, 0x1D, 0x00,
- 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
- 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
- 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16,
- 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, 0x01, 0x03, 0xFF,
- 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, 0xB9, 0x03, 0x9D,
- 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF,
- 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, 0x61,
- 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, 0xFD,
- 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC4,
- 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, 0xFA,
- 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, 0x9C,
- 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
- 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
- 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE4, 0xFF, 0x1B,
- 0x00, 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43,
- 0x96, 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D,
- 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF,
- 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77,
- 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00,
- 0xE1, 0xFF, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4,
- 0x00, 0xE2, 0xFD, 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F,
- 0xA8, 0xF3, 0xB8, 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
- 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01,
- 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B,
- 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF,
- 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18,
- 0xFD, 0x32, 0x06, 0x1F, 0xF2, 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2,
- 0x1E, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
- 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x4F, 0x01, 0xB0, 0xFD,
- 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, 0x86, 0x48, 0x5A, 0xFF, 0xBA,
- 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, 0x00, 0x9E, 0xFF, 0x17, 0x00,
- 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, 0x01, 0x8C, 0xFC, 0xEA,
- 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, 0x8B, 0xF1, 0x1B, 0x07,
- 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C,
- 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD,
- 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C,
- 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF,
- 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xC6,
- 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, 0xC4, 0xFC,
- 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAE,
- 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD,
- 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71,
- 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
- 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
- 0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
- 0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51,
- 0x00, 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45,
- 0xB2, 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47,
- 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF,
- 0xDD, 0x01, 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB,
- 0x40, 0xD0, 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF,
- 0xF4, 0xFF, 0x05, 0x00, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66,
- 0x00, 0x85, 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A,
- 0xE1, 0xF4, 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35,
- 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01,
- 0xC1, 0xFC, 0x86, 0x05, 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0,
- 0xF7, 0x7B, 0x02, 0x6B, 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF,
- 0x0B, 0x00, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96,
- 0xFD, 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3,
- 0xE6, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x5A, 0xFF, 0x7E, 0x01, 0x48, 0xFD,
- 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, 0x7C, 0x47, 0x19, 0xFC, 0x4D,
- 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, 0x00, 0xB5, 0xFF, 0x12, 0x00,
- 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
- 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
- 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00,
- 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, 0xFD, 0x1F, 0x03,
- 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, 0xDC, 0xFD, 0xFD,
- 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, 0x00, 0xFD, 0xFF,
- 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, 0x80,
- 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, 0xFC,
- 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x98,
- 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, 0x00,
- 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, 0x40,
- 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
- 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
- 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
- 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89,
- 0x00, 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47,
- 0xFC, 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56,
- 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
- 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61,
- 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF,
- 0x05, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE,
- 0xFF, 0x3D, 0xFF, 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15,
- 0x4A, 0xF6, 0xAD, 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32,
- 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01,
- 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7,
- 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF,
- 0x06, 0x00, 0x04, 0x00, 0xF8, 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C,
- 0xFE, 0x8C, 0x04, 0x6D, 0xF4, 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4,
- 0x85, 0x06, 0x57, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
- 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, 0xFF, 0xA7, 0x01, 0xEC, 0xFC,
- 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, 0xD7, 0x45, 0x43, 0xF9, 0xC3,
- 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, 0x00, 0xCB, 0xFF, 0x0D, 0x00,
- 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, 0x01, 0x50, 0xFD, 0xE1,
- 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, 0x9D, 0xF2, 0x09, 0x07,
- 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00,
- 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03,
- 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D,
- 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, 0x00, 0xFE, 0xFF,
- 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, 0x06, 0x97,
- 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, 0x48, 0xFC,
- 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F,
- 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC,
- 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42,
- 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
- 0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
- 0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
- 0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2,
- 0x00, 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48,
- 0x81, 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68,
- 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF,
- 0xE2, 0x01, 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5,
- 0x39, 0x4D, 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF,
- 0x13, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E,
- 0xFF, 0x06, 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10,
- 0xD7, 0xF7, 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E,
- 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01,
- 0x4E, 0xFC, 0xA0, 0x06, 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10,
- 0xF4, 0xC8, 0x04, 0x07, 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF,
- 0x03, 0x00, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9,
- 0xFE, 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5,
- 0x00, 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
- 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, 0x9F, 0xFC,
- 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, 0x9E, 0x43, 0xDD, 0xF6, 0x15,
- 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, 0x00, 0xDF, 0xFF, 0x09, 0x00,
- 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
- 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
- 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
- 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, 0xFD, 0xC4, 0x04,
- 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, 0x01, 0x01, 0x44,
- 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
- 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, 0x14,
- 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, 0xFC,
- 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25,
- 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, 0xFA,
- 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, 0xB8,
- 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00,
- 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
- 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
- 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA,
- 0x00, 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48,
- 0x50, 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C,
- 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF,
- 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86,
- 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF,
- 0x20, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19,
- 0xFF, 0xDD, 0x00, 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B,
- 0x7C, 0xF9, 0x35, 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29,
- 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01,
- 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC,
- 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00,
- 0x00, 0x00, 0x0C, 0x00, 0xD1, 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A,
- 0xFF, 0x2A, 0x02, 0x83, 0xF8, 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7,
- 0x5D, 0x05, 0xD3, 0xFC, 0xB1, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF,
- 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x64, 0xFC,
- 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, 0xD9, 0x40, 0xEA, 0xF4, 0x3E,
- 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, 0xFF, 0xF3, 0xFF, 0x05, 0x00,
- 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x7B, 0xFE, 0x0C,
- 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, 0xCD, 0xF4, 0x4B, 0x06,
- 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF,
- 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05,
- 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77,
- 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0x01, 0x00,
- 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, 0x05, 0xFD,
- 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, 0x37, 0xFC,
- 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A,
- 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9,
- 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E,
- 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
- 0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
- 0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
- 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78,
- 0xFF, 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06,
- 0xDB, 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1,
- 0x00, 0x91, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF,
- 0xB1, 0x01, 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15,
- 0x31, 0x7C, 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF,
- 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3,
- 0xFE, 0xBB, 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07,
- 0x2E, 0xFB, 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24,
- 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01,
- 0x34, 0xFC, 0x25, 0x07, 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7,
- 0xF1, 0x56, 0x06, 0xFE, 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00,
- 0xFF, 0xFF, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A,
- 0x00, 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8,
- 0xA1, 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
- 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3F, 0xFC,
- 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, 0x96, 0x3D, 0x69, 0xF3, 0x38,
- 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, 0xFF, 0x04, 0x00, 0x02, 0x00,
- 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
- 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
- 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
- 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, 0xFC, 0x1A, 0x06,
- 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, 0xA6, 0x03, 0xB9,
- 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0x04, 0x00,
- 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, 0x55,
- 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, 0xFC,
- 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F,
- 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, 0xF7,
- 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, 0xA2,
- 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00,
- 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
- 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
- 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64,
- 0xFF, 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A,
- 0x2C, 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8,
- 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF,
- 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62,
- 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF,
- 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14,
- 0x01, 0x2D, 0xFE, 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48,
- 0x73, 0x03, 0xE0, 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86,
- 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01,
- 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C,
- 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00,
- 0xFD, 0xFF, 0x16, 0x00, 0xA5, 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45,
- 0x01, 0x33, 0xFF, 0x5A, 0xFE, 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA,
- 0xD2, 0x03, 0x90, 0xFD, 0x5E, 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00,
- 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC,
- 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, 0xDF, 0x39, 0x5A, 0xF2, 0x00,
- 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, 0xFF, 0x13, 0x00, 0x00, 0x00,
- 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, 0xFF, 0xFA, 0xFF, 0x83,
- 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, 0xBF, 0xF7, 0x07, 0x05,
- 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
- 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06,
- 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10,
- 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0x07, 0x00,
- 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, 0x03, 0x20,
- 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, 0x88, 0xFC,
- 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33,
- 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6,
- 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11,
- 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
- 0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
- 0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
- 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x53,
- 0xFF, 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E,
- 0xE1, 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F,
- 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF,
- 0x45, 0x01, 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80,
- 0x27, 0x2B, 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF,
- 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49,
- 0x01, 0xBC, 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48,
- 0xC3, 0xFF, 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C,
- 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01,
- 0x84, 0xFC, 0xF3, 0x06, 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85,
- 0xF1, 0x16, 0x07, 0x61, 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00,
- 0xFD, 0xFF, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25,
- 0x02, 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB,
- 0xF8, 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00,
- 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD2, 0x01, 0x3D, 0xFC,
- 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, 0xC6, 0x35, 0xB7, 0xF1, 0x96,
- 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, 0xFF, 0x1F, 0x00, 0xFE, 0xFF,
- 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
- 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
- 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF3, 0x06,
- 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, 0x9C, 0x05, 0x7E,
- 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00,
- 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, 0x5E,
- 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, 0xFC,
- 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36,
- 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, 0xF4,
- 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, 0x77,
- 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF0, 0xFF,
- 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
- 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
- 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x45,
- 0xFF, 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13,
- 0xFD, 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47,
- 0x00, 0xD3, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF,
- 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81,
- 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
- 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79,
- 0x01, 0x53, 0xFD, 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47,
- 0x76, 0xFC, 0x1F, 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2,
- 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01,
- 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC,
- 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00,
- 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7,
- 0xFD, 0x05, 0x03, 0xE1, 0xFB, 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01,
- 0xAA, 0xFD, 0x18, 0x02, 0x72, 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B,
- 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB3, 0x01, 0x64, 0xFC,
- 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, 0x5A, 0x31, 0x7D, 0xF1, 0xF7,
- 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF,
- 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, 0xFE, 0xAE, 0x01, 0x70,
- 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, 0x14, 0xFB, 0x6D, 0x03,
- 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD,
- 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07,
- 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04,
- 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x10, 0x00,
- 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, 0x00, 0x0C,
- 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, 0x26, 0xFD,
- 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
- 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3,
- 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4,
- 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDD, 0xFF,
- 0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
- 0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
- 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3B,
- 0xFF, 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18,
- 0x89, 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12,
- 0x00, 0xE8, 0xFF, 0x07, 0x00, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF,
- 0xA4, 0x00, 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78,
- 0x1D, 0x10, 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF,
- 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2,
- 0x01, 0xF6, 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46,
- 0x93, 0xF9, 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8,
- 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01,
- 0x41, 0xFD, 0xF6, 0x05, 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84,
- 0xF2, 0x0F, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00,
- 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A,
- 0xFD, 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE,
- 0x4B, 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16,
- 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, 0xFF, 0x85, 0x01, 0xA6, 0xFC,
- 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, 0xAB, 0x2C, 0xA3, 0xF1, 0x26,
- 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
- 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
- 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
- 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFD,
- 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07,
- 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71,
- 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x00, 0x00,
- 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7,
- 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02,
- 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x02, 0x00, 0x05,
- 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
- 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
- 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
- 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED,
- 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00,
- 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x84,
- 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
- 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
- 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00,
- 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04,
- 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF,
- 0x27, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, 0xFF, 0x64, 0x00, 0x9B,
- 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, 0x10, 0x46, 0x03, 0x11,
- 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, 0x01, 0x4C, 0xFF, 0x2F,
- 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, 0x42, 0x00,
- 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, 0x18, 0x5C,
- 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00,
- 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8,
- 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3,
- 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD,
- 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23,
- 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF,
- 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
- 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
- 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0xFD,
- 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07,
- 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5,
- 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0xFD, 0xFF,
- 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC,
- 0xF2, 0x81, 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD,
- 0xFB, 0x00, 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35,
- 0x00, 0x38, 0xFF, 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4,
- 0xCE, 0x1A, 0x32, 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71,
- 0x00, 0xFB, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00,
- 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44,
- 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF,
- 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
- 0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
- 0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
- 0x00, 0xB1, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
- 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5,
- 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00,
- 0x8F, 0xFF, 0x1C, 0x00, 0x18, 0x00, 0x9C, 0xFF, 0xD6, 0x00, 0xB1,
- 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, 0x9C, 0x48, 0xFD, 0x07,
- 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, 0x01, 0x6E, 0xFF, 0x24,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, 0x65, 0xFF,
- 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, 0x0E, 0x6A,
- 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, 0x2D, 0x00,
- 0xFF, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B,
- 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6,
- 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF,
- 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE,
- 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99,
- 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
- 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
- 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
- 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD,
- 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06,
- 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E,
- 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
- 0x30, 0x00, 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8,
- 0xF1, 0x62, 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC,
- 0x82, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36,
- 0x00, 0x3A, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2,
- 0xDD, 0x24, 0x54, 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20,
- 0x01, 0xA3, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00,
- 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C,
- 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00,
- 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
- 0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
- 0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
- 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF,
- 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F,
- 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00,
- 0xBB, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x43,
- 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, 0x7E, 0x07, 0xAF, 0x48,
- 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, 0xFE, 0xDD, 0x00, 0x99,
- 0xFF, 0x19, 0x00, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, 0x79, 0xFE,
- 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, 0x06, 0xC7,
- 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, 0x22, 0x00,
- 0x00, 0x00, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6,
- 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9,
- 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00,
- 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF,
- 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C,
- 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF,
- 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
- 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
- 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00,
- 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05,
- 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35,
- 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF,
- 0x20, 0x00, 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1,
- 0xF1, 0x86, 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC,
- 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2D,
- 0x00, 0x54, 0xFF, 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1,
- 0x9F, 0x2E, 0xE3, 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A,
- 0x01, 0x64, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00,
- 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36,
- 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01,
- 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36,
- 0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
- 0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
- 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
- 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB,
- 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00,
- 0xE5, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9E,
- 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, 0x75, 0x10, 0x48, 0x46,
- 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, 0xFF, 0x6B, 0x00, 0xC6,
- 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x5B, 0x01,
- 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, 0x48, 0x8D,
- 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, 0xA4, 0xFF,
- 0x16, 0x00, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74,
- 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC,
- 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00,
- 0x00, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01,
- 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8,
- 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00,
- 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
- 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
- 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x06,
- 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03,
- 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D,
- 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x02, 0x00,
- 0x05, 0x00, 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56,
- 0xF3, 0x61, 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC,
- 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x1A,
- 0x00, 0x8A, 0xFF, 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1,
- 0x82, 0x37, 0x60, 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB,
- 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x29, 0x00,
- 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF,
- 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01,
- 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x43,
- 0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
- 0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
- 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
- 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A,
- 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF,
- 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8,
- 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, 0x38, 0x1A, 0x8C, 0x41,
- 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, 0x00, 0x01, 0x00, 0xEE,
- 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, 0xAF, 0x01,
- 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, 0x45, 0xA9,
- 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, 0xD0, 0xFF,
- 0x0C, 0x00, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65,
- 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD,
- 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14,
- 0x00, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE,
- 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E,
- 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00,
- 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
- 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
- 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x0F,
- 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01,
- 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15,
- 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x08, 0x00,
- 0xE1, 0xFF, 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD,
- 0xF6, 0x77, 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC,
- 0xC8, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFD,
- 0xFF, 0xD9, 0xFF, 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3,
- 0xFC, 0x3E, 0x5B, 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3,
- 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x14, 0x00,
- 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A,
- 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01,
- 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
- 0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
- 0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
- 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
- 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81,
- 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF,
- 0x22, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
- 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, 0x46, 0x24, 0xC8, 0x3A,
- 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, 0x01, 0xA8, 0xFF, 0x0F,
- 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01,
- 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, 0x40, 0x85,
- 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, 0xF7, 0xFF,
- 0x04, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4,
- 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7,
- 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A,
- 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD,
- 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91,
- 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00,
- 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
- 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
- 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0x1A,
- 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD,
- 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4,
- 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x12, 0x00,
- 0xB6, 0xFF, 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB,
- 0xFB, 0x69, 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD,
- 0x81, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD7,
- 0xFF, 0x3E, 0x00, 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7,
- 0x99, 0x44, 0x68, 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA,
- 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF5, 0xFF,
- 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D,
- 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01,
- 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
- 0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
- 0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
- 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF,
- 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40,
- 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF,
- 0x31, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2E, 0x00, 0x52, 0xFF, 0xBC,
- 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, 0x11, 0x2E, 0x6B, 0x32,
- 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, 0x01, 0x67, 0xFF, 0x26,
- 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE0, 0x01,
- 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, 0x38, 0x2A,
- 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, 0x16, 0x00,
- 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48,
- 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3,
- 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03,
- 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC,
- 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D,
- 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00,
- 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
- 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
- 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0x00,
- 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03,
- 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C,
- 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0x1D, 0x00,
- 0x8A, 0xFF, 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6,
- 0x02, 0xF2, 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE,
- 0x1E, 0x01, 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAC,
- 0xFF, 0xAE, 0x00, 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD,
- 0xFD, 0x47, 0x0E, 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C,
- 0x01, 0x61, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF,
- 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B,
- 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01,
- 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
- 0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
- 0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
- 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF,
- 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52,
- 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
- 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1C, 0x00, 0x86, 0xFF, 0x59,
- 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, 0x04, 0x37, 0xF3, 0x28,
- 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x41, 0xFF, 0x33,
- 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01,
- 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E,
- 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00,
- 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37,
- 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1,
- 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE,
- 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC,
- 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F,
- 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00,
- 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
- 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
- 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0xFF,
- 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05,
- 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE,
- 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8,
- 0xF9, 0x0E, 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01,
- 0x05, 0xFF, 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x20,
- 0x00, 0x7F, 0xFF, 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC,
- 0x9B, 0x04, 0xF2, 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50,
- 0xFE, 0x04, 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0x17, 0x00, 0xA1, 0xFF,
- 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70,
- 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01,
- 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
- 0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
- 0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
- 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00,
- 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B,
- 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF,
- 0x34, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xD4, 0xFF, 0xBF,
- 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, 0x98, 0x3E, 0xF3, 0x1E,
- 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36,
- 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, 0x39, 0x01,
- 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, 0x26, 0x4B,
- 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, 0x35, 0x00,
- 0xFD, 0xFF, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90,
- 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1,
- 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD,
- 0xFF, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC,
- 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB,
- 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF,
- 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
- 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
- 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFE,
- 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06,
- 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49,
- 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFF, 0xFF,
- 0x32, 0x00, 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E,
- 0xF6, 0x68, 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF,
- 0xEA, 0xFF, 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x2B,
- 0x00, 0x59, 0xFF, 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8,
- 0x2D, 0x0D, 0x69, 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C,
- 0xFF, 0x93, 0x00, 0xB6, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00,
- 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83,
- 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE,
- 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
- 0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
- 0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
- 0xFF, 0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00,
- 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7,
- 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF,
- 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD9, 0xFF, 0x37, 0x00, 0xF7,
- 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, 0x53, 0x44, 0xFB, 0x14,
- 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, 0x01, 0x42, 0xFF, 0x32,
- 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, 0x00,
- 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, 0x1C, 0x47,
- 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00,
- 0xFE, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57,
- 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2,
- 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD,
- 0xFF, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC,
- 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29,
- 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
- 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
- 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
- 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0xFD,
- 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07,
- 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C,
- 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
- 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB,
- 0xF3, 0x5B, 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD,
- 0xB4, 0x00, 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33,
- 0x00, 0x3E, 0xFF, 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5,
- 0xB6, 0x16, 0x77, 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D,
- 0x00, 0x25, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
- 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59,
- 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF,
- 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x25, 0x00, 0x6C,
- 0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
- 0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
- 0x00, 0x9E, 0xFF, 0x17, 0x00, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00,
- 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13,
- 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF,
- 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAE, 0xFF, 0xA7, 0x00, 0x12,
- 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, 0xDC, 0x47, 0x95, 0x0B,
- 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, 0x01, 0x5F, 0xFF, 0x29,
- 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, 0xC3, 0xFF,
- 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, 0x12, 0x19,
- 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, 0x30, 0x00,
- 0xFF, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85,
- 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4,
- 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE,
- 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD,
- 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6,
- 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
- 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
- 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
- 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0xFD,
- 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07,
- 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78,
- 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
- 0x34, 0x00, 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E,
- 0xF2, 0x60, 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC,
- 0x51, 0x01, 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
- 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3,
- 0xBA, 0x20, 0x61, 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE,
- 0x00, 0xC5, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x35, 0x00,
- 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C,
- 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00,
- 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
- 0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
- 0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
- 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF,
- 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D,
- 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00,
- 0xA9, 0xFF, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x82, 0xFF, 0x18,
- 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, 0x24, 0x04, 0xF5, 0x48,
- 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, 0xFE, 0x0B, 0x01, 0x87,
- 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, 0xDB, 0xFE,
- 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, 0x09, 0x61,
- 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, 0x26, 0x00,
- 0x00, 0x00, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06,
- 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7,
- 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF,
- 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE,
- 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00,
- 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF,
- 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
- 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
- 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
- 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06,
- 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33,
- 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
- 0x28, 0x00, 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E,
- 0xF1, 0xE3, 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC,
- 0xB7, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x32,
- 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1,
- 0xAE, 0x2A, 0x86, 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E,
- 0x01, 0x7B, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
- 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18,
- 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01,
- 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
- 0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
- 0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
- 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF,
- 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC,
- 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00,
- 0xD5, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, 0xFF, 0x7C,
- 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, 0xA4, 0x0C, 0x90, 0x47,
- 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, 0xFF, 0x99, 0x00, 0xB3,
- 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, 0x31, 0x01,
- 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, 0x48, 0x73,
- 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, 0x91, 0xFF,
- 0x1B, 0x00, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB,
- 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB,
- 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00,
- 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1,
- 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF,
- 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
- 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
- 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x04,
- 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04,
- 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55,
- 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00,
- 0x11, 0x00, 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74,
- 0xF2, 0x54, 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC,
- 0xE4, 0x01, 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x23,
- 0x00, 0x71, 0xFF, 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1,
- 0xFD, 0x33, 0x62, 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7,
- 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2F, 0x00,
- 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2,
- 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01,
- 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
- 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
- 0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
- 0xFF, 0x13, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF,
- 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E,
- 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF,
- 0xFB, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC5,
- 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, 0x22, 0x16, 0xC3, 0x43,
- 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, 0x00, 0x2B, 0x00, 0xDE,
- 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x90, 0x01,
- 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, 0x46, 0xE1,
- 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, 0xBE, 0xFF,
- 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC,
- 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF,
- 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18,
- 0x00, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02,
- 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8,
- 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00,
- 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
- 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
- 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x0B,
- 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02,
- 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF,
- 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x05, 0x00,
- 0xF0, 0xFF, 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F,
- 0xF5, 0x32, 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC,
- 0xDA, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
- 0x00, 0xB6, 0xFF, 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2,
- 0x1C, 0x3C, 0x81, 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6,
- 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1E, 0x00,
- 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06,
- 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
- 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
- 0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
- 0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
- 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF,
- 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE,
- 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF,
- 0x19, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6,
- 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, 0x22, 0x20, 0xCA, 0x3D,
- 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, 0x00, 0xCA, 0xFF, 0x03,
- 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01,
- 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, 0x42, 0x02,
- 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, 0xE8, 0xFF,
- 0x07, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6,
- 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9,
- 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E,
- 0x00, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD,
- 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B,
- 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00,
- 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
- 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
- 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00,
- 0x00, 0xF4, 0xFF, 0x1A, 0x00, 0xFF, 0x00, 0x07, 0x03, 0x16, 0x06,
- 0x7C, 0x09, 0x2A, 0x0C, 0x2E, 0x0D, 0x2A, 0x0C, 0x7C, 0x09, 0x16,
- 0x06, 0x07, 0x03, 0xFF, 0x00, 0x1A, 0x00, 0xF4, 0xFF, 0xF2, 0xFF,
- 0xA0, 0xFF, 0x71, 0xFF, 0x71, 0x00, 0x86, 0x03, 0x73, 0x08, 0x88,
- 0x0D, 0x78, 0x10, 0xC9, 0x0F, 0xD5, 0x0B, 0x8B, 0x06, 0x28, 0x02,
- 0xDF, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDC,
- 0xFF, 0x80, 0xFF, 0x9A, 0xFF, 0x46, 0x01, 0x1E, 0x05, 0x5A, 0x0A,
- 0xED, 0x0E, 0xAA, 0x10, 0xAF, 0x0E, 0xFD, 0x09, 0xCB, 0x04, 0x18,
- 0x01, 0x8E, 0xFF, 0x85, 0xFF, 0xE1, 0xFF, 0xFC, 0xFF, 0xBD, 0xFF,
- 0x6D, 0xFF, 0xF6, 0xFF, 0x65, 0x02, 0xE5, 0x06, 0x2B, 0x0C, 0xF3,
- 0x0F, 0x60, 0x10, 0x3B, 0x0D, 0x16, 0x08, 0x3F, 0x03, 0x50, 0x00,
- 0x6E, 0xFF, 0xA7, 0xFF, 0xF5, 0xFF, 0xEF, 0xFF, 0x9A, 0xFF, 0x75,
- 0xFF, 0x91, 0x00, 0xC9, 0x03, 0xC8, 0x08, 0xCC, 0x0D, 0x89, 0x10,
- 0x9F, 0x0F, 0x85, 0x0B, 0x3B, 0x06, 0xF4, 0x01, 0xCD, 0xFF, 0x72,
- 0xFF, 0xC9, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0x7B, 0xFF,
- 0xA5, 0xFF, 0x73, 0x01, 0x6A, 0x05, 0xAD, 0x0A, 0x21, 0x0F, 0xA6,
- 0x10, 0x74, 0x0E, 0xA9, 0x09, 0x83, 0x04, 0xF0, 0x00, 0x85, 0xFF,
- 0x8B, 0xFF, 0xE5, 0xFF, 0xFA, 0xFF, 0xB7, 0xFF, 0x6C, 0xFF, 0x0C,
- 0x00, 0x9D, 0x02, 0x37, 0x07, 0x78, 0x0C, 0x15, 0x10, 0x47, 0x10,
- 0xF3, 0x0C, 0xC2, 0x07, 0x01, 0x03, 0x35, 0x00, 0x6D, 0xFF, 0xAD,
- 0xFF, 0xF7, 0xFF, 0xEB, 0xFF, 0x94, 0xFF, 0x7A, 0xFF, 0xB3, 0x00,
- 0x0D, 0x04, 0x1C, 0x09, 0x0D, 0x0E, 0x97, 0x10, 0x73, 0x0F, 0x35,
- 0x0B, 0xEB, 0x05, 0xC1, 0x01, 0xBD, 0xFF, 0x75, 0xFF, 0xCE, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x77, 0xFF, 0xB3, 0xFF, 0xA1,
- 0x01, 0xB7, 0x05, 0xFF, 0x0A, 0x53, 0x0F, 0x9E, 0x10, 0x37, 0x0E,
- 0x55, 0x09, 0x3B, 0x04, 0xCB, 0x00, 0x7E, 0xFF, 0x90, 0xFF, 0xE9,
- 0xFF, 0xF8, 0xFF, 0xB1, 0xFF, 0x6C, 0xFF, 0x24, 0x00, 0xD8, 0x02,
- 0x8A, 0x07, 0xC2, 0x0C, 0x34, 0x10, 0x2A, 0x10, 0xAA, 0x0C, 0x6F,
- 0x07, 0xC4, 0x02, 0x1C, 0x00, 0x6C, 0xFF, 0xB3, 0xFF, 0xF9, 0xFF,
- 0xE8, 0xFF, 0x8E, 0xFF, 0x80, 0xFF, 0xD7, 0x00, 0x53, 0x04, 0x71,
- 0x09, 0x4C, 0x0E, 0xA1, 0x10, 0x43, 0x0F, 0xE3, 0x0A, 0x9D, 0x05,
- 0x91, 0x01, 0xAE, 0xFF, 0x79, 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF,
- 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC2, 0xFF, 0xD2, 0x01, 0x06, 0x06,
- 0x50, 0x0B, 0x82, 0x0F, 0x93, 0x10, 0xF8, 0x0D, 0x00, 0x09, 0xF6,
- 0x03, 0xA7, 0x00, 0x78, 0xFF, 0x96, 0xFF, 0xEC, 0xFF, 0xF6, 0xFF,
- 0xAB, 0xFF, 0x6D, 0xFF, 0x3E, 0x00, 0x15, 0x03, 0xDE, 0x07, 0x0B,
- 0x0D, 0x50, 0x10, 0x0A, 0x10, 0x5E, 0x0C, 0x1C, 0x07, 0x8A, 0x02,
- 0x04, 0x00, 0x6C, 0xFF, 0xB9, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, 0x89,
- 0xFF, 0x88, 0xFF, 0xFD, 0x00, 0x9B, 0x04, 0xC5, 0x09, 0x88, 0x0E,
- 0xA8, 0x10, 0x10, 0x0F, 0x91, 0x0A, 0x50, 0x05, 0x64, 0x01, 0xA1,
- 0xFF, 0x7D, 0xFF, 0xD9, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF,
- 0x71, 0xFF, 0xD3, 0xFF, 0x05, 0x02, 0x55, 0x06, 0xA0, 0x0B, 0xAD,
- 0x0F, 0x84, 0x10, 0xB6, 0x0D, 0xAC, 0x08, 0xB3, 0x03, 0x86, 0x00,
- 0x74, 0xFF, 0x9C, 0xFF, 0xF0, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, 0x6F,
- 0xFF, 0x5A, 0x00, 0x54, 0x03, 0x32, 0x08, 0x52, 0x0D, 0x68, 0x10,
- 0xE6, 0x0F, 0x11, 0x0C, 0xCA, 0x06, 0x52, 0x02, 0xEF, 0xFF, 0x6E,
- 0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFF, 0x84, 0xFF, 0x91, 0xFF,
- 0x25, 0x01, 0xE4, 0x04, 0x19, 0x0A, 0xC2, 0x0E, 0xAA, 0x10, 0xDA,
- 0x0E, 0x3E, 0x0A, 0x05, 0x05, 0x38, 0x01, 0x96, 0xFF, 0x81, 0xFF,
- 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE6,
- 0xFF, 0x3A, 0x02, 0xA6, 0x06, 0xEF, 0x0B, 0xD6, 0x0F, 0x71, 0x10,
- 0x71, 0x0D, 0x57, 0x08, 0x71, 0x03, 0x67, 0x00, 0x70, 0xFF, 0xA2,
- 0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x78, 0x00,
- 0x95, 0x03, 0x86, 0x08, 0x98, 0x0D, 0x7C, 0x10, 0xC0, 0x0F, 0xC3,
- 0x0B, 0x79, 0x06, 0x1C, 0x02, 0xDB, 0xFF, 0x70, 0xFF, 0xC5, 0xFF,
- 0xFE, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9C, 0xFF, 0x50,
- 0x01, 0x2F, 0x05, 0x6C, 0x0A, 0xF9, 0x0E, 0xA9, 0x10, 0xA2, 0x0E,
- 0xEA, 0x09, 0xBB, 0x04, 0x0F, 0x01, 0x8C, 0xFF, 0x87, 0xFF, 0xE2,
- 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xFA, 0xFF, 0x71, 0x02,
- 0xF7, 0x06, 0x3C, 0x0C, 0xFB, 0x0F, 0x5B, 0x10, 0x2B, 0x0D, 0x03,
- 0x08, 0x31, 0x03, 0x4A, 0x00, 0x6E, 0xFF, 0xA8, 0xFF, 0xF5, 0xFF,
- 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x98, 0x00, 0xD8, 0x03, 0xDB,
- 0x08, 0xDB, 0x0D, 0x8D, 0x10, 0x96, 0x0F, 0x73, 0x0B, 0x29, 0x06,
- 0xE8, 0x01, 0xC9, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, 0x00,
- 0x00, 0xD6, 0xFF, 0x7A, 0xFF, 0xA8, 0xFF, 0x7D, 0x01, 0x7B, 0x05,
- 0xBF, 0x0A, 0x2D, 0x0F, 0xA5, 0x10, 0x67, 0x0E, 0x96, 0x09, 0x73,
- 0x04, 0xE7, 0x00, 0x84, 0xFF, 0x8C, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF,
- 0xB6, 0xFF, 0x6C, 0xFF, 0x11, 0x00, 0xAA, 0x02, 0x4A, 0x07, 0x88,
- 0x0C, 0x1C, 0x10, 0x41, 0x10, 0xE3, 0x0C, 0xAF, 0x07, 0xF3, 0x02,
- 0x2F, 0x00, 0x6C, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEA, 0xFF, 0x93,
- 0xFF, 0x7B, 0xFF, 0xBB, 0x00, 0x1C, 0x04, 0x2F, 0x09, 0x1B, 0x0E,
- 0x9A, 0x10, 0x68, 0x0F, 0x23, 0x0B, 0xDA, 0x05, 0xB7, 0x01, 0xB9,
- 0xFF, 0x76, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, 0xFF,
- 0x76, 0xFF, 0xB6, 0xFF, 0xAC, 0x01, 0xC8, 0x05, 0x11, 0x0B, 0x5E,
- 0x0F, 0x9C, 0x10, 0x29, 0x0E, 0x42, 0x09, 0x2C, 0x04, 0xC2, 0x00,
- 0x7D, 0xFF, 0x92, 0xFF, 0xEA, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, 0x6C,
- 0xFF, 0x29, 0x00, 0xE6, 0x02, 0x9D, 0x07, 0xD3, 0x0C, 0x3B, 0x10,
- 0x23, 0x10, 0x99, 0x0C, 0x5C, 0x07, 0xB7, 0x02, 0x16, 0x00, 0x6C,
- 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8D, 0xFF, 0x82, 0xFF,
- 0xDF, 0x00, 0x63, 0x04, 0x84, 0x09, 0x59, 0x0E, 0xA3, 0x10, 0x38,
- 0x0F, 0xD1, 0x0A, 0x8C, 0x05, 0x87, 0x01, 0xAB, 0xFF, 0x79, 0xFF,
- 0xD5, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC6,
- 0xFF, 0xDD, 0x01, 0x17, 0x06, 0x62, 0x0B, 0x8C, 0x0F, 0x90, 0x10,
- 0xE9, 0x0D, 0xED, 0x08, 0xE7, 0x03, 0xA0, 0x00, 0x77, 0xFF, 0x97,
- 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xA9, 0xFF, 0x6D, 0xFF, 0x44, 0x00,
- 0x23, 0x03, 0xF1, 0x07, 0x1B, 0x0D, 0x55, 0x10, 0x02, 0x10, 0x4D,
- 0x0C, 0x0A, 0x07, 0x7E, 0x02, 0xFF, 0xFF, 0x6D, 0xFF, 0xBA, 0xFF,
- 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x8A, 0xFF, 0x06, 0x01, 0xAB,
- 0x04, 0xD8, 0x09, 0x95, 0x0E, 0xA9, 0x10, 0x05, 0x0F, 0x7F, 0x0A,
- 0x40, 0x05, 0x5A, 0x01, 0x9F, 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00,
- 0x00, 0xFE, 0xFF, 0xC6, 0xFF, 0x70, 0xFF, 0xD7, 0xFF, 0x10, 0x02,
- 0x67, 0x06, 0xB1, 0x0B, 0xB7, 0x0F, 0x80, 0x10, 0xA7, 0x0D, 0x99,
- 0x08, 0xA4, 0x03, 0x7F, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, 0xFF,
- 0xF3, 0xFF, 0xA3, 0xFF, 0x70, 0xFF, 0x60, 0x00, 0x62, 0x03, 0x45,
- 0x08, 0x62, 0x0D, 0x6C, 0x10, 0xDE, 0x0F, 0x00, 0x0C, 0xB8, 0x06,
- 0x46, 0x02, 0xEA, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFD, 0xFF, 0x00,
- 0x00, 0xDE, 0xFF, 0x83, 0xFF, 0x94, 0xFF, 0x2F, 0x01, 0xF4, 0x04,
- 0x2B, 0x0A, 0xCE, 0x0E, 0xAA, 0x10, 0xCE, 0x0E, 0x2B, 0x0A, 0xF4,
- 0x04, 0x2F, 0x01, 0x94, 0xFF, 0x83, 0xFF, 0xDE, 0xFF, 0xFD, 0xFF,
- 0xC0, 0xFF, 0x6E, 0xFF, 0xEA, 0xFF, 0x46, 0x02, 0xB8, 0x06, 0x00,
- 0x0C, 0xDE, 0x0F, 0x6C, 0x10, 0x62, 0x0D, 0x45, 0x08, 0x62, 0x03,
- 0x60, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D,
- 0xFF, 0x73, 0xFF, 0x7F, 0x00, 0xA4, 0x03, 0x99, 0x08, 0xA7, 0x0D,
- 0x80, 0x10, 0xB7, 0x0F, 0xB1, 0x0B, 0x67, 0x06, 0x10, 0x02, 0xD7,
- 0xFF, 0x70, 0xFF, 0xC6, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, 0xFF,
- 0x7E, 0xFF, 0x9F, 0xFF, 0x5A, 0x01, 0x40, 0x05, 0x7F, 0x0A, 0x05,
- 0x0F, 0xA9, 0x10, 0x95, 0x0E, 0xD8, 0x09, 0xAB, 0x04, 0x06, 0x01,
- 0x8A, 0xFF, 0x88, 0xFF, 0xE3, 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D,
- 0xFF, 0xFF, 0xFF, 0x7E, 0x02, 0x0A, 0x07, 0x4D, 0x0C, 0x02, 0x10,
- 0x55, 0x10, 0x1B, 0x0D, 0xF1, 0x07, 0x23, 0x03, 0x44, 0x00, 0x6D,
- 0xFF, 0xA9, 0xFF, 0xF6, 0xFF, 0xED, 0xFF, 0x97, 0xFF, 0x77, 0xFF,
- 0xA0, 0x00, 0xE7, 0x03, 0xED, 0x08, 0xE9, 0x0D, 0x90, 0x10, 0x8C,
- 0x0F, 0x62, 0x0B, 0x17, 0x06, 0xDD, 0x01, 0xC6, 0xFF, 0x73, 0xFF,
- 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x79, 0xFF, 0xAB,
- 0xFF, 0x87, 0x01, 0x8C, 0x05, 0xD1, 0x0A, 0x38, 0x0F, 0xA3, 0x10,
- 0x59, 0x0E, 0x84, 0x09, 0x63, 0x04, 0xDF, 0x00, 0x82, 0xFF, 0x8D,
- 0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xB4, 0xFF, 0x6C, 0xFF, 0x16, 0x00,
- 0xB7, 0x02, 0x5C, 0x07, 0x99, 0x0C, 0x23, 0x10, 0x3B, 0x10, 0xD3,
- 0x0C, 0x9D, 0x07, 0xE6, 0x02, 0x29, 0x00, 0x6C, 0xFF, 0xB0, 0xFF,
- 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7D, 0xFF, 0xC2, 0x00, 0x2C,
- 0x04, 0x42, 0x09, 0x29, 0x0E, 0x9C, 0x10, 0x5E, 0x0F, 0x11, 0x0B,
- 0xC8, 0x05, 0xAC, 0x01, 0xB6, 0xFF, 0x76, 0xFF, 0xD1, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB9, 0xFF, 0xB7, 0x01,
- 0xDA, 0x05, 0x23, 0x0B, 0x68, 0x0F, 0x9A, 0x10, 0x1B, 0x0E, 0x2F,
- 0x09, 0x1C, 0x04, 0xBB, 0x00, 0x7B, 0xFF, 0x93, 0xFF, 0xEA, 0xFF,
- 0xF7, 0xFF, 0xAE, 0xFF, 0x6C, 0xFF, 0x2F, 0x00, 0xF3, 0x02, 0xAF,
- 0x07, 0xE3, 0x0C, 0x41, 0x10, 0x1C, 0x10, 0x88, 0x0C, 0x4A, 0x07,
- 0xAA, 0x02, 0x11, 0x00, 0x6C, 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE6,
- 0xFF, 0x8C, 0xFF, 0x84, 0xFF, 0xE7, 0x00, 0x73, 0x04, 0x96, 0x09,
- 0x67, 0x0E, 0xA5, 0x10, 0x2D, 0x0F, 0xBF, 0x0A, 0x7B, 0x05, 0x7D,
- 0x01, 0xA8, 0xFF, 0x7A, 0xFF, 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
- 0xCA, 0xFF, 0x72, 0xFF, 0xC9, 0xFF, 0xE8, 0x01, 0x29, 0x06, 0x73,
- 0x0B, 0x96, 0x0F, 0x8D, 0x10, 0xDB, 0x0D, 0xDB, 0x08, 0xD8, 0x03,
- 0x98, 0x00, 0x76, 0xFF, 0x99, 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA8,
- 0xFF, 0x6E, 0xFF, 0x4A, 0x00, 0x31, 0x03, 0x03, 0x08, 0x2B, 0x0D,
- 0x5B, 0x10, 0xFB, 0x0F, 0x3C, 0x0C, 0xF7, 0x06, 0x71, 0x02, 0xFA,
- 0xFF, 0x6D, 0xFF, 0xBC, 0xFF, 0xFC, 0xFF, 0xE2, 0xFF, 0x87, 0xFF,
- 0x8C, 0xFF, 0x0F, 0x01, 0xBB, 0x04, 0xEA, 0x09, 0xA2, 0x0E, 0xA9,
- 0x10, 0xF9, 0x0E, 0x6C, 0x0A, 0x2F, 0x05, 0x50, 0x01, 0x9C, 0xFF,
- 0x7F, 0xFF, 0xDB, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, 0x70,
- 0xFF, 0xDB, 0xFF, 0x1C, 0x02, 0x79, 0x06, 0xC3, 0x0B, 0xC0, 0x0F,
- 0x7C, 0x10, 0x98, 0x0D, 0x86, 0x08, 0x95, 0x03, 0x78, 0x00, 0x72,
- 0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA2, 0xFF, 0x70, 0xFF,
- 0x67, 0x00, 0x71, 0x03, 0x57, 0x08, 0x71, 0x0D, 0x71, 0x10, 0xD6,
- 0x0F, 0xEF, 0x0B, 0xA6, 0x06, 0x3A, 0x02, 0xE6, 0xFF, 0x6E, 0xFF,
- 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x96,
- 0xFF, 0x38, 0x01, 0x05, 0x05, 0x3E, 0x0A, 0xDA, 0x0E, 0xAA, 0x10,
- 0xC2, 0x0E, 0x19, 0x0A, 0xE4, 0x04, 0x25, 0x01, 0x91, 0xFF, 0x84,
- 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xBF, 0xFF, 0x6E, 0xFF, 0xEF, 0xFF,
- 0x52, 0x02, 0xCA, 0x06, 0x11, 0x0C, 0xE6, 0x0F, 0x68, 0x10, 0x52,
- 0x0D, 0x32, 0x08, 0x54, 0x03, 0x5A, 0x00, 0x6F, 0xFF, 0xA5, 0xFF,
- 0xF4, 0xFF, 0xF0, 0xFF, 0x9C, 0xFF, 0x74, 0xFF, 0x86, 0x00, 0xB3,
- 0x03, 0xAC, 0x08, 0xB6, 0x0D, 0x84, 0x10, 0xAD, 0x0F, 0xA0, 0x0B,
- 0x55, 0x06, 0x05, 0x02, 0xD3, 0xFF, 0x71, 0xFF, 0xC7, 0xFF, 0xFE,
- 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA1, 0xFF, 0x64, 0x01,
- 0x50, 0x05, 0x91, 0x0A, 0x10, 0x0F, 0xA8, 0x10, 0x88, 0x0E, 0xC5,
- 0x09, 0x9B, 0x04, 0xFD, 0x00, 0x88, 0xFF, 0x89, 0xFF, 0xE4, 0xFF,
- 0xFB, 0xFF, 0xB9, 0xFF, 0x6C, 0xFF, 0x04, 0x00, 0x8A, 0x02, 0x1C,
- 0x07, 0x5E, 0x0C, 0x0A, 0x10, 0x50, 0x10, 0x0B, 0x0D, 0xDE, 0x07,
- 0x15, 0x03, 0x3E, 0x00, 0x6D, 0xFF, 0xAB, 0xFF, 0xF6, 0xFF, 0xEC,
- 0xFF, 0x96, 0xFF, 0x78, 0xFF, 0xA7, 0x00, 0xF6, 0x03, 0x00, 0x09,
- 0xF8, 0x0D, 0x93, 0x10, 0x82, 0x0F, 0x50, 0x0B, 0x06, 0x06, 0xD2,
- 0x01, 0xC2, 0xFF, 0x74, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
- 0xD4, 0xFF, 0x79, 0xFF, 0xAE, 0xFF, 0x91, 0x01, 0x9D, 0x05, 0xE3,
- 0x0A, 0x43, 0x0F, 0xA1, 0x10, 0x4C, 0x0E, 0x71, 0x09, 0x53, 0x04,
- 0xD7, 0x00, 0x80, 0xFF, 0x8E, 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB3,
- 0xFF, 0x6C, 0xFF, 0x1C, 0x00, 0xC4, 0x02, 0x6F, 0x07, 0xAA, 0x0C,
- 0x2A, 0x10, 0x34, 0x10, 0xC2, 0x0C, 0x8A, 0x07, 0xD8, 0x02, 0x24,
- 0x00, 0x6C, 0xFF, 0xB1, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x90, 0xFF,
- 0x7E, 0xFF, 0xCB, 0x00, 0x3B, 0x04, 0x55, 0x09, 0x37, 0x0E, 0x9E,
- 0x10, 0x53, 0x0F, 0xFF, 0x0A, 0xB7, 0x05, 0xA1, 0x01, 0xB3, 0xFF,
- 0x77, 0xFF, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x75,
- 0xFF, 0xBD, 0xFF, 0xC1, 0x01, 0xEB, 0x05, 0x35, 0x0B, 0x73, 0x0F,
- 0x97, 0x10, 0x0D, 0x0E, 0x1C, 0x09, 0x0D, 0x04, 0xB3, 0x00, 0x7A,
- 0xFF, 0x94, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAD, 0xFF, 0x6D, 0xFF,
- 0x35, 0x00, 0x01, 0x03, 0xC2, 0x07, 0xF3, 0x0C, 0x47, 0x10, 0x15,
- 0x10, 0x78, 0x0C, 0x37, 0x07, 0x9D, 0x02, 0x0C, 0x00, 0x6C, 0xFF,
- 0xB7, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, 0xF0,
- 0x00, 0x83, 0x04, 0xA9, 0x09, 0x74, 0x0E, 0xA6, 0x10, 0x21, 0x0F,
- 0xAD, 0x0A, 0x6A, 0x05, 0x73, 0x01, 0xA5, 0xFF, 0x7B, 0xFF, 0xD7,
- 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC9, 0xFF, 0x72, 0xFF, 0xCD, 0xFF,
- 0xF4, 0x01, 0x3B, 0x06, 0x85, 0x0B, 0x9F, 0x0F, 0x89, 0x10, 0xCC,
- 0x0D, 0xC8, 0x08, 0xC9, 0x03, 0x91, 0x00, 0x75, 0xFF, 0x9A, 0xFF,
- 0xEF, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x50, 0x00, 0x3F,
- 0x03, 0x16, 0x08, 0x3B, 0x0D, 0x60, 0x10, 0xF3, 0x0F, 0x2B, 0x0C,
- 0xE5, 0x06, 0x65, 0x02, 0xF6, 0xFF, 0x6D, 0xFF, 0xBD, 0xFF, 0xFC,
- 0xFF, 0xE1, 0xFF, 0x85, 0xFF, 0x8E, 0xFF, 0x18, 0x01, 0xCB, 0x04,
- 0xFD, 0x09, 0xAF, 0x0E, 0xAA, 0x10, 0xED, 0x0E, 0x5A, 0x0A, 0x1E,
- 0x05, 0x46, 0x01, 0x9A, 0xFF, 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00,
- 0xFD, 0xFF, 0xC3, 0xFF, 0x6F, 0xFF, 0xDF, 0xFF, 0x28, 0x02, 0x8B,
- 0x06, 0xD5, 0x0B, 0xC9, 0x0F, 0x78, 0x10, 0x88, 0x0D, 0x73, 0x08,
- 0x86, 0x03, 0x71, 0x00, 0x71, 0xFF, 0xA0, 0xFF, 0xF2, 0xFF, 0xF2,
- 0xFF, 0xA1, 0xFF, 0x71, 0xFF, 0x6E, 0x00, 0x7F, 0x03, 0x6A, 0x08,
- 0x81, 0x0D, 0x76, 0x10, 0xCD, 0x0F, 0xDD, 0x0B, 0x94, 0x06, 0x2E,
- 0x02, 0xE1, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
- 0xDC, 0xFF, 0x80, 0xFF, 0x98, 0xFF, 0x42, 0x01, 0x16, 0x05, 0x50,
- 0x0A, 0xE7, 0x0E, 0xAA, 0x10, 0xB5, 0x0E, 0x06, 0x0A, 0xD3, 0x04,
- 0x1C, 0x01, 0x8F, 0xFF, 0x85, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, 0xBE,
- 0xFF, 0x6D, 0xFF, 0xF3, 0xFF, 0x5E, 0x02, 0xDC, 0x06, 0x23, 0x0C,
- 0xEF, 0x0F, 0x63, 0x10, 0x43, 0x0D, 0x1F, 0x08, 0x46, 0x03, 0x53,
- 0x00, 0x6E, 0xFF, 0xA6, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, 0xFF,
- 0x75, 0xFF, 0x8D, 0x00, 0xC1, 0x03, 0xBE, 0x08, 0xC4, 0x0D, 0x88,
- 0x10, 0xA4, 0x0F, 0x8E, 0x0B, 0x43, 0x06, 0xF9, 0x01, 0xCF, 0xFF,
- 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, 0x7C,
- 0xFF, 0xA4, 0xFF, 0x6E, 0x01, 0x61, 0x05, 0xA3, 0x0A, 0x1C, 0x0F,
- 0xA7, 0x10, 0x7B, 0x0E, 0xB2, 0x09, 0x8B, 0x04, 0xF4, 0x00, 0x86,
- 0xFF, 0x8A, 0xFF, 0xE4, 0xFF, 0xFA, 0xFF, 0xB8, 0xFF, 0x6C, 0xFF,
- 0x09, 0x00, 0x97, 0x02, 0x2E, 0x07, 0x6F, 0x0C, 0x11, 0x10, 0x4A,
- 0x10, 0xFB, 0x0C, 0xCB, 0x07, 0x07, 0x03, 0x38, 0x00, 0x6D, 0xFF,
- 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, 0xAF,
- 0x00, 0x05, 0x04, 0x13, 0x09, 0x06, 0x0E, 0x96, 0x10, 0x78, 0x0F,
- 0x3E, 0x0B, 0xF4, 0x05, 0xC7, 0x01, 0xBF, 0xFF, 0x74, 0xFF, 0xCE,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x78, 0xFF, 0xB1, 0xFF,
- 0x9C, 0x01, 0xAE, 0x05, 0xF6, 0x0A, 0x4E, 0x0F, 0x9F, 0x10, 0x3E,
- 0x0E, 0x5E, 0x09, 0x43, 0x04, 0xCF, 0x00, 0x7F, 0xFF, 0x90, 0xFF,
- 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x21, 0x00, 0xD2,
- 0x02, 0x81, 0x07, 0xBA, 0x0C, 0x31, 0x10, 0x2E, 0x10, 0xB2, 0x0C,
- 0x78, 0x07, 0xCB, 0x02, 0x1E, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, 0xF9,
- 0xFF, 0xE8, 0xFF, 0x8F, 0xFF, 0x80, 0xFF, 0xD3, 0x00, 0x4B, 0x04,
- 0x67, 0x09, 0x45, 0x0E, 0xA0, 0x10, 0x48, 0x0F, 0xEC, 0x0A, 0xA6,
- 0x05, 0x97, 0x01, 0xB0, 0xFF, 0x78, 0xFF, 0xD3, 0xFF, 0x00, 0x00,
- 0xFF, 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC0, 0xFF, 0xCC, 0x01, 0xFD,
- 0x05, 0x47, 0x0B, 0x7D, 0x0F, 0x94, 0x10, 0xFF, 0x0D, 0x0A, 0x09,
- 0xFE, 0x03, 0xAB, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, 0xF7,
- 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x3B, 0x00, 0x0E, 0x03, 0xD5, 0x07,
- 0x03, 0x0D, 0x4D, 0x10, 0x0E, 0x10, 0x67, 0x0C, 0x25, 0x07, 0x91,
- 0x02, 0x07, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF,
- 0x89, 0xFF, 0x87, 0xFF, 0xF9, 0x00, 0x93, 0x04, 0xBC, 0x09, 0x82,
- 0x0E, 0xA7, 0x10, 0x16, 0x0F, 0x9A, 0x0A, 0x59, 0x05, 0x69, 0x01,
- 0xA3, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC8,
- 0xFF, 0x71, 0xFF, 0xD1, 0xFF, 0xFF, 0x01, 0x4C, 0x06, 0x97, 0x0B,
- 0xA9, 0x0F, 0x86, 0x10, 0xBD, 0x0D, 0xB5, 0x08, 0xBA, 0x03, 0x8A,
- 0x00, 0x74, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF,
- 0x6F, 0xFF, 0x57, 0x00, 0x4D, 0x03, 0x29, 0x08, 0x4B, 0x0D, 0x65,
- 0x10, 0xEB, 0x0F, 0x1A, 0x0C, 0xD3, 0x06, 0x58, 0x02, 0xF1, 0xFF,
- 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x84, 0xFF, 0x90,
- 0xFF, 0x21, 0x01, 0xDC, 0x04, 0x10, 0x0A, 0xBB, 0x0E, 0xAA, 0x10,
- 0xE1, 0x0E, 0x47, 0x0A, 0x0D, 0x05, 0x3D, 0x01, 0x97, 0xFF, 0x81,
- 0xFF, 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC2, 0xFF, 0x6F, 0xFF,
- 0xE4, 0xFF, 0x34, 0x02, 0x9D, 0x06, 0xE6, 0x0B, 0xD1, 0x0F, 0x73,
- 0x10, 0x79, 0x0D, 0x61, 0x08, 0x78, 0x03, 0x6A, 0x00, 0x70, 0xFF,
- 0xA1, 0xFF, 0xF2, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x74,
- 0x00, 0x8E, 0x03, 0x7D, 0x08, 0x90, 0x0D, 0x7A, 0x10, 0xC4, 0x0F,
- 0xCC, 0x0B, 0x82, 0x06, 0x22, 0x02, 0xDD, 0xFF, 0x6F, 0xFF, 0xC4,
- 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9B, 0xFF,
- 0x4B, 0x01, 0x26, 0x05, 0x63, 0x0A, 0xF3, 0x0E, 0xAA, 0x10, 0xA8,
- 0x0E, 0xF4, 0x09, 0xC3, 0x04, 0x13, 0x01, 0x8D, 0xFF, 0x86, 0xFF,
- 0xE1, 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xF8, 0xFF, 0x6B,
- 0x02, 0xEE, 0x06, 0x34, 0x0C, 0xF7, 0x0F, 0x5D, 0x10, 0x33, 0x0D,
- 0x0D, 0x08, 0x38, 0x03, 0x4D, 0x00, 0x6E, 0xFF, 0xA7, 0xFF, 0xF5,
- 0xFF, 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x94, 0x00, 0xD0, 0x03,
- 0xD1, 0x08, 0xD3, 0x0D, 0x8B, 0x10, 0x9A, 0x0F, 0x7C, 0x0B, 0x32,
- 0x06, 0xEE, 0x01, 0xCB, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF,
- 0x00, 0x00, 0xD6, 0xFF, 0x7B, 0xFF, 0xA7, 0xFF, 0x78, 0x01, 0x72,
- 0x05, 0xB6, 0x0A, 0x27, 0x0F, 0xA5, 0x10, 0x6E, 0x0E, 0xA0, 0x09,
- 0x7B, 0x04, 0xEC, 0x00, 0x85, 0xFF, 0x8B, 0xFF, 0xE5, 0xFF, 0xFA,
- 0xFF, 0xB6, 0xFF, 0x6C, 0xFF, 0x0E, 0x00, 0xA4, 0x02, 0x41, 0x07,
- 0x80, 0x0C, 0x19, 0x10, 0x44, 0x10, 0xEB, 0x0C, 0xB9, 0x07, 0xFA,
- 0x02, 0x32, 0x00, 0x6D, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEB, 0xFF,
- 0x93, 0xFF, 0x7B, 0xFF, 0xB7, 0x00, 0x15, 0x04, 0x26, 0x09, 0x14,
- 0x0E, 0x98, 0x10, 0x6D, 0x0F, 0x2C, 0x0B, 0xE3, 0x05, 0xBC, 0x01,
- 0xBB, 0xFF, 0x75, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1,
- 0xFF, 0x77, 0xFF, 0xB5, 0xFF, 0xA6, 0x01, 0xC0, 0x05, 0x08, 0x0B,
- 0x58, 0x0F, 0x9D, 0x10, 0x30, 0x0E, 0x4B, 0x09, 0x34, 0x04, 0xC6,
- 0x00, 0x7D, 0xFF, 0x91, 0xFF, 0xE9, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF,
- 0x6C, 0xFF, 0x27, 0x00, 0xDF, 0x02, 0x94, 0x07, 0xCA, 0x0C, 0x37,
- 0x10, 0x27, 0x10, 0xA1, 0x0C, 0x65, 0x07, 0xBE, 0x02, 0x19, 0x00,
- 0x6C, 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8E, 0xFF, 0x81,
- 0xFF, 0xDB, 0x00, 0x5B, 0x04, 0x7A, 0x09, 0x53, 0x0E, 0xA2, 0x10,
- 0x3D, 0x0F, 0xDA, 0x0A, 0x95, 0x05, 0x8C, 0x01, 0xAD, 0xFF, 0x79,
- 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xFF, 0x73, 0xFF,
- 0xC4, 0xFF, 0xD7, 0x01, 0x0E, 0x06, 0x59, 0x0B, 0x87, 0x0F, 0x91,
- 0x10, 0xF0, 0x0D, 0xF7, 0x08, 0xEF, 0x03, 0xA3, 0x00, 0x78, 0xFF,
- 0x97, 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xAA, 0xFF, 0x6D, 0xFF, 0x41,
- 0x00, 0x1C, 0x03, 0xE7, 0x07, 0x13, 0x0D, 0x52, 0x10, 0x06, 0x10,
- 0x56, 0x0C, 0x13, 0x07, 0x84, 0x02, 0x02, 0x00, 0x6D, 0xFF, 0xBA,
- 0xFF, 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 0x01, 0x01,
- 0xA3, 0x04, 0xCE, 0x09, 0x8F, 0x0E, 0xA8, 0x10, 0x0A, 0x0F, 0x88,
- 0x0A, 0x48, 0x05, 0x5F, 0x01, 0xA0, 0xFF, 0x7D, 0xFF, 0xD9, 0xFF,
- 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, 0x70, 0xFF, 0xD5, 0xFF, 0x0B,
- 0x02, 0x5E, 0x06, 0xA9, 0x0B, 0xB2, 0x0F, 0x82, 0x10, 0xAE, 0x0D,
- 0xA2, 0x08, 0xAB, 0x03, 0x82, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0,
- 0xFF, 0xF3, 0xFF, 0xA4, 0xFF, 0x6F, 0xFF, 0x5D, 0x00, 0x5B, 0x03,
- 0x3B, 0x08, 0x5A, 0x0D, 0x6A, 0x10, 0xE2, 0x0F, 0x09, 0x0C, 0xC1,
- 0x06, 0x4C, 0x02, 0xEC, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFC, 0xFF,
- 0xDF, 0xFF, 0x83, 0xFF, 0x93, 0xFF, 0x2A, 0x01, 0xEC, 0x04, 0x22,
- 0x0A, 0xC8, 0x0E, 0xAB, 0x10, 0xD4, 0x0E, 0x35, 0x0A, 0xFD, 0x04,
- 0x33, 0x01, 0x95, 0xFF, 0x82, 0xFF, 0xDE, 0xFF, 0x00, 0x00, 0xFD,
- 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE8, 0xFF, 0x40, 0x02, 0xAF, 0x06,
- 0xF7, 0x0B, 0xDA, 0x0F, 0x6F, 0x10, 0x6A, 0x0D, 0x4E, 0x08, 0x6A,
- 0x03, 0x64, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF,
- 0x9E, 0xFF, 0x72, 0xFF, 0x7B, 0x00, 0x9C, 0x03, 0x90, 0x08, 0x9F,
- 0x0D, 0x7E, 0x10, 0xBB, 0x0F, 0xBA, 0x0B, 0x70, 0x06, 0x16, 0x02,
- 0xD9, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA,
- 0xFF, 0x7E, 0xFF, 0x9D, 0xFF, 0x55, 0x01, 0x37, 0x05, 0x75, 0x0A,
- 0xFF, 0x0E, 0xA9, 0x10, 0x9C, 0x0E, 0xE1, 0x09, 0xB3, 0x04, 0x0A,
- 0x01, 0x8B, 0xFF, 0x87, 0xFF, 0xE2, 0xFF, 0xFB, 0xFF, 0xBB, 0xFF,
- 0x6D, 0xFF, 0xFD, 0xFF, 0x77, 0x02, 0x01, 0x07, 0x45, 0x0C, 0xFF,
- 0x0F, 0x58, 0x10, 0x23, 0x0D, 0xFA, 0x07, 0x2A, 0x03, 0x47, 0x00,
- 0x6E, 0xFF, 0xA9, 0xFF, 0xF5, 0xFF, 0xED, 0xFF, 0x98, 0xFF, 0x77,
- 0xFF, 0x9C, 0x00, 0xDF, 0x03, 0xE4, 0x08, 0xE2, 0x0D, 0x8E, 0x10,
- 0x91, 0x0F, 0x6B, 0x0B, 0x20, 0x06, 0xE3, 0x01, 0xC8, 0xFF, 0x73,
- 0xFF, 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x7A, 0xFF,
- 0xAA, 0xFF, 0x82, 0x01, 0x83, 0x05, 0xC8, 0x0A, 0x32, 0x0F, 0xA4,
- 0x10, 0x60, 0x0E, 0x8D, 0x09, 0x6B, 0x04, 0xE3, 0x00, 0x83, 0xFF,
- 0x8D, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, 0xB5, 0xFF, 0x6C, 0xFF, 0x14,
- 0x00, 0xB1, 0x02, 0x53, 0x07, 0x91, 0x0C, 0x20, 0x10, 0x3E, 0x10,
- 0xDB, 0x0C, 0xA6, 0x07, 0xEC, 0x02, 0x2C, 0x00, 0x6C, 0xFF, 0xAF,
- 0xFF, 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7C, 0xFF, 0xBE, 0x00,
- 0x24, 0x04, 0x38, 0x09, 0x22, 0x0E, 0x9B, 0x10, 0x63, 0x0F, 0x1A,
- 0x0B, 0xD1, 0x05, 0xB1, 0x01, 0xB8, 0xFF, 0x76, 0xFF, 0xD0, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB8, 0xFF, 0xB1,
- 0x01, 0xD1, 0x05, 0x1A, 0x0B, 0x63, 0x0F, 0x9B, 0x10, 0x22, 0x0E,
- 0x38, 0x09, 0x24, 0x04, 0xBE, 0x00, 0x7C, 0xFF, 0x92, 0xFF, 0xEA,
- 0xFF, 0xF8, 0xFF, 0xAF, 0xFF, 0x6C, 0xFF, 0x2C, 0x00, 0xEC, 0x02,
- 0xA6, 0x07, 0xDB, 0x0C, 0x3E, 0x10, 0x20, 0x10, 0x91, 0x0C, 0x53,
- 0x07, 0xB1, 0x02, 0x14, 0x00, 0x6C, 0xFF, 0xB5, 0xFF, 0xFA, 0xFF,
- 0xE6, 0xFF, 0x8D, 0xFF, 0x83, 0xFF, 0xE3, 0x00, 0x6B, 0x04, 0x8D,
- 0x09, 0x60, 0x0E, 0xA4, 0x10, 0x32, 0x0F, 0xC8, 0x0A, 0x83, 0x05,
- 0x82, 0x01, 0xAA, 0xFF, 0x7A, 0xFF, 0xD5, 0xFF, 0x00, 0x00, 0xFF,
- 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC8, 0xFF, 0xE3, 0x01, 0x20, 0x06,
- 0x6B, 0x0B, 0x91, 0x0F, 0x8E, 0x10, 0xE2, 0x0D, 0xE4, 0x08, 0xDF,
- 0x03, 0x9C, 0x00, 0x77, 0xFF, 0x98, 0xFF, 0xED, 0xFF, 0xF5, 0xFF,
- 0xA9, 0xFF, 0x6E, 0xFF, 0x47, 0x00, 0x2A, 0x03, 0xFA, 0x07, 0x23,
- 0x0D, 0x58, 0x10, 0xFF, 0x0F, 0x45, 0x0C, 0x01, 0x07, 0x77, 0x02,
- 0xFD, 0xFF, 0x6D, 0xFF, 0xBB, 0xFF, 0xFB, 0xFF, 0xE2, 0xFF, 0x87,
- 0xFF, 0x8B, 0xFF, 0x0A, 0x01, 0xB3, 0x04, 0xE1, 0x09, 0x9C, 0x0E,
- 0xA9, 0x10, 0xFF, 0x0E, 0x75, 0x0A, 0x37, 0x05, 0x55, 0x01, 0x9D,
- 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF,
- 0x70, 0xFF, 0xD9, 0xFF, 0x16, 0x02, 0x70, 0x06, 0xBA, 0x0B, 0xBB,
- 0x0F, 0x7E, 0x10, 0x9F, 0x0D, 0x90, 0x08, 0x9C, 0x03, 0x7B, 0x00,
- 0x72, 0xFF, 0x9E, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA3, 0xFF, 0x70,
- 0xFF, 0x64, 0x00, 0x6A, 0x03, 0x4E, 0x08, 0x6A, 0x0D, 0x6F, 0x10,
- 0xDA, 0x0F, 0xF7, 0x0B, 0xAF, 0x06, 0x40, 0x02, 0xE8, 0xFF, 0x6E,
- 0xFF, 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDE, 0xFF, 0x82, 0xFF,
- 0x95, 0xFF, 0x33, 0x01, 0xFD, 0x04, 0x35, 0x0A, 0xD4, 0x0E, 0xAB,
- 0x10, 0xC8, 0x0E, 0x22, 0x0A, 0xEC, 0x04, 0x2A, 0x01, 0x93, 0xFF,
- 0x83, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xC0, 0xFF, 0x6E, 0xFF, 0xEC,
- 0xFF, 0x4C, 0x02, 0xC1, 0x06, 0x09, 0x0C, 0xE2, 0x0F, 0x6A, 0x10,
- 0x5A, 0x0D, 0x3B, 0x08, 0x5B, 0x03, 0x5D, 0x00, 0x6F, 0xFF, 0xA4,
- 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, 0xFF, 0x73, 0xFF, 0x82, 0x00,
- 0xAB, 0x03, 0xA2, 0x08, 0xAE, 0x0D, 0x82, 0x10, 0xB2, 0x0F, 0xA9,
- 0x0B, 0x5E, 0x06, 0x0B, 0x02, 0xD5, 0xFF, 0x70, 0xFF, 0xC7, 0xFF,
- 0xFE, 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA0, 0xFF, 0x5F,
- 0x01, 0x48, 0x05, 0x88, 0x0A, 0x0A, 0x0F, 0xA8, 0x10, 0x8F, 0x0E,
- 0xCE, 0x09, 0xA3, 0x04, 0x01, 0x01, 0x89, 0xFF, 0x88, 0xFF, 0xE3,
- 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, 0xFF, 0x02, 0x00, 0x84, 0x02,
- 0x13, 0x07, 0x56, 0x0C, 0x06, 0x10, 0x52, 0x10, 0x13, 0x0D, 0xE7,
- 0x07, 0x1C, 0x03, 0x41, 0x00, 0x6D, 0xFF, 0xAA, 0xFF, 0xF6, 0xFF,
- 0xED, 0xFF, 0x97, 0xFF, 0x78, 0xFF, 0xA3, 0x00, 0xEF, 0x03, 0xF7,
- 0x08, 0xF0, 0x0D, 0x91, 0x10, 0x87, 0x0F, 0x59, 0x0B, 0x0E, 0x06,
- 0xD7, 0x01, 0xC4, 0xFF, 0x73, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0x00,
- 0x00, 0xD4, 0xFF, 0x79, 0xFF, 0xAD, 0xFF, 0x8C, 0x01, 0x95, 0x05,
- 0xDA, 0x0A, 0x3D, 0x0F, 0xA2, 0x10, 0x53, 0x0E, 0x7A, 0x09, 0x5B,
- 0x04, 0xDB, 0x00, 0x81, 0xFF, 0x8E, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF,
- 0xB4, 0xFF, 0x6C, 0xFF, 0x19, 0x00, 0xBE, 0x02, 0x65, 0x07, 0xA1,
- 0x0C, 0x27, 0x10, 0x37, 0x10, 0xCA, 0x0C, 0x94, 0x07, 0xDF, 0x02,
- 0x27, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x91,
- 0xFF, 0x7D, 0xFF, 0xC6, 0x00, 0x34, 0x04, 0x4B, 0x09, 0x30, 0x0E,
- 0x9D, 0x10, 0x58, 0x0F, 0x08, 0x0B, 0xC0, 0x05, 0xA6, 0x01, 0xB5,
- 0xFF, 0x77, 0xFF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF,
- 0x75, 0xFF, 0xBB, 0xFF, 0xBC, 0x01, 0xE3, 0x05, 0x2C, 0x0B, 0x6D,
- 0x0F, 0x98, 0x10, 0x14, 0x0E, 0x26, 0x09, 0x15, 0x04, 0xB7, 0x00,
- 0x7B, 0xFF, 0x93, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAE, 0xFF, 0x6D,
- 0xFF, 0x32, 0x00, 0xFA, 0x02, 0xB9, 0x07, 0xEB, 0x0C, 0x44, 0x10,
- 0x19, 0x10, 0x80, 0x0C, 0x41, 0x07, 0xA4, 0x02, 0x0E, 0x00, 0x6C,
- 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF,
- 0xEC, 0x00, 0x7B, 0x04, 0xA0, 0x09, 0x6E, 0x0E, 0xA5, 0x10, 0x27,
- 0x0F, 0xB6, 0x0A, 0x72, 0x05, 0x78, 0x01, 0xA7, 0xFF, 0x7B, 0xFF,
- 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xCA, 0xFF, 0x72, 0xFF, 0xCB,
- 0xFF, 0xEE, 0x01, 0x32, 0x06, 0x7C, 0x0B, 0x9A, 0x0F, 0x8B, 0x10,
- 0xD3, 0x0D, 0xD1, 0x08, 0xD0, 0x03, 0x94, 0x00, 0x76, 0xFF, 0x99,
- 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x4D, 0x00,
- 0x38, 0x03, 0x0D, 0x08, 0x33, 0x0D, 0x5D, 0x10, 0xF7, 0x0F, 0x34,
- 0x0C, 0xEE, 0x06, 0x6B, 0x02, 0xF8, 0xFF, 0x6D, 0xFF, 0xBC, 0xFF,
- 0xFC, 0xFF, 0xE1, 0xFF, 0x86, 0xFF, 0x8D, 0xFF, 0x13, 0x01, 0xC3,
- 0x04, 0xF4, 0x09, 0xA8, 0x0E, 0xAA, 0x10, 0xF3, 0x0E, 0x63, 0x0A,
- 0x26, 0x05, 0x4B, 0x01, 0x9B, 0xFF, 0x7F, 0xFF, 0xDB, 0xFF, 0x00,
- 0x00, 0xFD, 0xFF, 0xC4, 0xFF, 0x6F, 0xFF, 0xDD, 0xFF, 0x22, 0x02,
- 0x82, 0x06, 0xCC, 0x0B, 0xC4, 0x0F, 0x7A, 0x10, 0x90, 0x0D, 0x7D,
- 0x08, 0x8E, 0x03, 0x74, 0x00, 0x72, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF,
- 0xF2, 0xFF, 0xA1, 0xFF, 0x70, 0xFF, 0x6A, 0x00, 0x78, 0x03, 0x61,
- 0x08, 0x79, 0x0D, 0x73, 0x10, 0xD1, 0x0F, 0xE6, 0x0B, 0x9D, 0x06,
- 0x34, 0x02, 0xE4, 0xFF, 0x6F, 0xFF, 0xC2, 0xFF, 0xFD, 0xFF, 0x00,
- 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x97, 0xFF, 0x3D, 0x01, 0x0D, 0x05,
- 0x47, 0x0A, 0xE1, 0x0E, 0xAA, 0x10, 0xBB, 0x0E, 0x10, 0x0A, 0xDC,
- 0x04, 0x21, 0x01, 0x90, 0xFF, 0x84, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF,
- 0xBE, 0xFF, 0x6D, 0xFF, 0xF1, 0xFF, 0x58, 0x02, 0xD3, 0x06, 0x1A,
- 0x0C, 0xEB, 0x0F, 0x65, 0x10, 0x4B, 0x0D, 0x29, 0x08, 0x4D, 0x03,
- 0x57, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B,
- 0xFF, 0x74, 0xFF, 0x8A, 0x00, 0xBA, 0x03, 0xB5, 0x08, 0xBD, 0x0D,
- 0x86, 0x10, 0xA9, 0x0F, 0x97, 0x0B, 0x4C, 0x06, 0xFF, 0x01, 0xD1,
- 0xFF, 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF,
- 0x7C, 0xFF, 0xA3, 0xFF, 0x69, 0x01, 0x59, 0x05, 0x9A, 0x0A, 0x16,
- 0x0F, 0xA7, 0x10, 0x82, 0x0E, 0xBC, 0x09, 0x93, 0x04, 0xF9, 0x00,
- 0x87, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, 0xFB, 0xFF, 0xB8, 0xFF, 0x6C,
- 0xFF, 0x07, 0x00, 0x91, 0x02, 0x25, 0x07, 0x67, 0x0C, 0x0E, 0x10,
- 0x4D, 0x10, 0x03, 0x0D, 0xD5, 0x07, 0x0E, 0x03, 0x3B, 0x00, 0x6D,
- 0xFF, 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF,
- 0xAB, 0x00, 0xFE, 0x03, 0x0A, 0x09, 0xFF, 0x0D, 0x94, 0x10, 0x7D,
- 0x0F, 0x47, 0x0B, 0xFD, 0x05, 0xCC, 0x01, 0xC0, 0xFF, 0x74, 0xFF,
- 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD3, 0xFF, 0x78, 0xFF, 0xB0,
- 0xFF, 0x97, 0x01, 0xA6, 0x05, 0xEC, 0x0A, 0x48, 0x0F, 0xA0, 0x10,
- 0x45, 0x0E, 0x67, 0x09, 0x4B, 0x04, 0xD3, 0x00, 0x80, 0xFF, 0x8F,
- 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x1E, 0x00,
- 0xCB, 0x02, 0x78, 0x07, 0xB2, 0x0C, 0x2E, 0x10, 0x31, 0x10, 0xBA,
- 0x0C, 0x81, 0x07, 0xD2, 0x02, 0x21, 0x00, 0x6C, 0xFF, 0xB2, 0xFF,
- 0xF9, 0xFF, 0xE8, 0xFF, 0x90, 0xFF, 0x7F, 0xFF, 0xCF, 0x00, 0x43,
- 0x04, 0x5E, 0x09, 0x3E, 0x0E, 0x9F, 0x10, 0x4E, 0x0F, 0xF6, 0x0A,
- 0xAE, 0x05, 0x9C, 0x01, 0xB1, 0xFF, 0x78, 0xFF, 0xD2, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x74, 0xFF, 0xBF, 0xFF, 0xC7, 0x01,
- 0xF4, 0x05, 0x3E, 0x0B, 0x78, 0x0F, 0x96, 0x10, 0x06, 0x0E, 0x13,
- 0x09, 0x05, 0x04, 0xAF, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF,
- 0xF7, 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x38, 0x00, 0x07, 0x03, 0xCB,
- 0x07, 0xFB, 0x0C, 0x4A, 0x10, 0x11, 0x10, 0x6F, 0x0C, 0x2E, 0x07,
- 0x97, 0x02, 0x09, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFA, 0xFF, 0xE4,
- 0xFF, 0x8A, 0xFF, 0x86, 0xFF, 0xF4, 0x00, 0x8B, 0x04, 0xB2, 0x09,
- 0x7B, 0x0E, 0xA7, 0x10, 0x1C, 0x0F, 0xA3, 0x0A, 0x61, 0x05, 0x6E,
- 0x01, 0xA4, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
- 0xC8, 0xFF, 0x71, 0xFF, 0xCF, 0xFF, 0xF9, 0x01, 0x43, 0x06, 0x8E,
- 0x0B, 0xA4, 0x0F, 0x88, 0x10, 0xC4, 0x0D, 0xBE, 0x08, 0xC1, 0x03,
- 0x8D, 0x00, 0x75, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA6,
- 0xFF, 0x6E, 0xFF, 0x53, 0x00, 0x46, 0x03, 0x1F, 0x08, 0x43, 0x0D,
- 0x63, 0x10, 0xEF, 0x0F, 0x23, 0x0C, 0xDC, 0x06, 0x5E, 0x02, 0xF3,
- 0xFF, 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x85, 0xFF,
- 0x8F, 0xFF, 0x1C, 0x01, 0xD3, 0x04, 0x06, 0x0A, 0xB5, 0x0E, 0xAA,
- 0x10, 0xE7, 0x0E, 0x50, 0x0A, 0x16, 0x05, 0x42, 0x01, 0x98, 0xFF,
- 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC3, 0xFF, 0x6F,
- 0xFF, 0xE1, 0xFF, 0x2E, 0x02, 0x94, 0x06, 0xDD, 0x0B, 0xCD, 0x0F,
- 0x76, 0x10, 0x81, 0x0D, 0x6A, 0x08, 0x7F, 0x03, 0x6E, 0x00, 0x71,
- 0xFF, 0xA1, 0xFF, 0xF2, 0xFF, 0x00, 0x00, 0x15, 0x00, 0xD1, 0xFF,
- 0x8B, 0xFE, 0xBC, 0xFD, 0xE1, 0x00, 0x84, 0x09, 0xB0, 0x13, 0x47,
- 0x18, 0xB0, 0x13, 0x84, 0x09, 0xE1, 0x00, 0xBC, 0xFD, 0x8B, 0xFE,
- 0xD1, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xDA, 0x00, 0x30,
- 0x00, 0x5D, 0xFC, 0xB3, 0xFC, 0x35, 0x0A, 0xC2, 0x1C, 0x24, 0x20,
- 0x48, 0x10, 0x5D, 0xFF, 0x74, 0xFB, 0x3A, 0xFF, 0xFB, 0x00, 0x42,
- 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2C, 0x00, 0xF3, 0x00, 0xAD, 0xFF,
- 0xC5, 0xFB, 0x11, 0xFE, 0xAF, 0x0D, 0xEF, 0x1E, 0x68, 0x1E, 0xBC,
- 0x0C, 0xA7, 0xFD, 0xEA, 0xFB, 0xD3, 0xFF, 0xEE, 0x00, 0x24, 0x00,
- 0xFA, 0xFF, 0xF7, 0xFF, 0x4C, 0x00, 0xFB, 0x00, 0x0C, 0xFF, 0x5F,
- 0xFB, 0xE8, 0xFF, 0x3D, 0x11, 0x7E, 0x20, 0x13, 0x1C, 0x4C, 0x09,
- 0x6A, 0xFC, 0x8C, 0xFC, 0x4E, 0x00, 0xD1, 0x00, 0x0E, 0x00, 0xFD,
- 0xFF, 0xF7, 0xFF, 0x72, 0x00, 0xEC, 0x00, 0x55, 0xFE, 0x3D, 0xFB,
- 0x37, 0x02, 0xBE, 0x14, 0x5D, 0x21, 0x40, 0x19, 0x18, 0x06, 0xA2,
- 0xFB, 0x47, 0xFD, 0xA7, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xFC, 0xFF, 0x9B, 0x00, 0xC0, 0x00, 0x92, 0xFD, 0x73,
- 0xFB, 0xF2, 0x04, 0x0E, 0x18, 0x81, 0x21, 0x0C, 0x16, 0x37, 0x03,
- 0x47, 0xFB, 0x0B, 0xFE, 0xDF, 0x00, 0x82, 0x00, 0xF9, 0xFF, 0xFE,
- 0xFF, 0x08, 0x00, 0xC3, 0x00, 0x74, 0x00, 0xD2, 0xFC, 0x10, 0xFC,
- 0x08, 0x08, 0x0A, 0x1B, 0xE9, 0x20, 0x9A, 0x12, 0xBE, 0x00, 0x49,
- 0xFB, 0xC8, 0xFE, 0xF9, 0x00, 0x5A, 0x00, 0xF7, 0xFF, 0xFC, 0xFF,
- 0x1B, 0x00, 0xE4, 0x00, 0x06, 0x00, 0x24, 0xFC, 0x1E, 0xFD, 0x65,
- 0x0B, 0x94, 0x1D, 0x9D, 0x1F, 0x0D, 0x0F, 0xB8, 0xFE, 0x96, 0xFB,
- 0x72, 0xFF, 0xF9, 0x00, 0x37, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x36,
- 0x00, 0xF8, 0x00, 0x78, 0xFF, 0x9B, 0xFB, 0xA6, 0xFE, 0xE9, 0x0E,
- 0x8D, 0x1F, 0xAA, 0x1D, 0x87, 0x0B, 0x2B, 0xFD, 0x1E, 0xFC, 0x02,
- 0x00, 0xE5, 0x00, 0x1C, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x58, 0x00,
- 0xF9, 0x00, 0xCF, 0xFE, 0x4A, 0xFB, 0xA7, 0x00, 0x77, 0x12, 0xE0,
- 0x20, 0x26, 0x1B, 0x28, 0x08, 0x18, 0xFC, 0xCB, 0xFC, 0x71, 0x00,
- 0xC5, 0x00, 0x08, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x80, 0x00, 0xE1,
- 0x00, 0x13, 0xFE, 0x45, 0xFB, 0x1D, 0x03, 0xEB, 0x15, 0x7F, 0x21,
- 0x2D, 0x18, 0x0E, 0x05, 0x77, 0xFB, 0x8B, 0xFD, 0xBE, 0x00, 0x9D,
- 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA9, 0x00,
- 0xAA, 0x00, 0x4F, 0xFD, 0x9D, 0xFB, 0xFA, 0x05, 0x22, 0x19, 0x62,
- 0x21, 0xE0, 0x14, 0x50, 0x02, 0x3E, 0xFB, 0x4E, 0xFE, 0xEB, 0x00,
- 0x73, 0x00, 0xF7, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xD0, 0x00, 0x52,
- 0x00, 0x93, 0xFC, 0x60, 0xFC, 0x2C, 0x09, 0xFA, 0x1B, 0x8A, 0x20,
- 0x60, 0x11, 0xFD, 0xFF, 0x5C, 0xFB, 0x06, 0xFF, 0xFB, 0x00, 0x4D,
- 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x23, 0x00, 0xED, 0x00, 0xD9, 0xFF,
- 0xEF, 0xFB, 0x98, 0xFD, 0x99, 0x0C, 0x54, 0x1E, 0x02, 0x1F, 0xD2,
- 0x0D, 0x20, 0xFE, 0xC0, 0xFB, 0xA7, 0xFF, 0xF4, 0x00, 0x2D, 0x00,
- 0xF9, 0xFF, 0xF8, 0xFF, 0x41, 0x00, 0xFB, 0x00, 0x41, 0xFF, 0x78,
- 0xFB, 0x4A, 0xFF, 0x25, 0x10, 0x16, 0x20, 0xDA, 0x1C, 0x56, 0x0A,
- 0xBE, 0xFC, 0x56, 0xFC, 0x2C, 0x00, 0xDB, 0x00, 0x14, 0x00, 0xFD,
- 0xFF, 0xF7, 0xFF, 0x66, 0x00, 0xF4, 0x00, 0x8F, 0xFE, 0x3F, 0xFB,
- 0x75, 0x01, 0xAE, 0x13, 0x2C, 0x21, 0x2A, 0x1A, 0x0D, 0x07, 0xD4,
- 0xFB, 0x0C, 0xFD, 0x8F, 0x00, 0xB7, 0x00, 0x03, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0xFA, 0xFF, 0x8E, 0x00, 0xD1, 0x00, 0xCF, 0xFD, 0x58,
- 0xFB, 0x10, 0x04, 0x10, 0x17, 0x8A, 0x21, 0x10, 0x17, 0x10, 0x04,
- 0x58, 0xFB, 0xCF, 0xFD, 0xD1, 0x00, 0x8E, 0x00, 0xFA, 0xFF, 0xFF,
- 0xFF, 0x03, 0x00, 0xB7, 0x00, 0x8F, 0x00, 0x0C, 0xFD, 0xD4, 0xFB,
- 0x0D, 0x07, 0x2A, 0x1A, 0x2C, 0x21, 0xAE, 0x13, 0x75, 0x01, 0x3F,
- 0xFB, 0x8F, 0xFE, 0xF4, 0x00, 0x66, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
- 0x14, 0x00, 0xDB, 0x00, 0x2C, 0x00, 0x56, 0xFC, 0xBE, 0xFC, 0x56,
- 0x0A, 0xDA, 0x1C, 0x16, 0x20, 0x25, 0x10, 0x4A, 0xFF, 0x78, 0xFB,
- 0x41, 0xFF, 0xFB, 0x00, 0x41, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2D,
- 0x00, 0xF4, 0x00, 0xA7, 0xFF, 0xC0, 0xFB, 0x20, 0xFE, 0xD2, 0x0D,
- 0x02, 0x1F, 0x54, 0x1E, 0x99, 0x0C, 0x98, 0xFD, 0xEF, 0xFB, 0xD9,
- 0xFF, 0xED, 0x00, 0x23, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4D, 0x00,
- 0xFB, 0x00, 0x06, 0xFF, 0x5C, 0xFB, 0xFD, 0xFF, 0x60, 0x11, 0x8A,
- 0x20, 0xFA, 0x1B, 0x2C, 0x09, 0x60, 0xFC, 0x93, 0xFC, 0x52, 0x00,
- 0xD0, 0x00, 0x0D, 0x00, 0xFE, 0xFF, 0xF7, 0xFF, 0x73, 0x00, 0xEB,
- 0x00, 0x4E, 0xFE, 0x3E, 0xFB, 0x50, 0x02, 0xE0, 0x14, 0x62, 0x21,
- 0x22, 0x19, 0xFA, 0x05, 0x9D, 0xFB, 0x4F, 0xFD, 0xAA, 0x00, 0xA9,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x9D, 0x00,
- 0xBE, 0x00, 0x8B, 0xFD, 0x77, 0xFB, 0x0E, 0x05, 0x2D, 0x18, 0x7F,
- 0x21, 0xEB, 0x15, 0x1D, 0x03, 0x45, 0xFB, 0x13, 0xFE, 0xE1, 0x00,
- 0x80, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x08, 0x00, 0xC5, 0x00, 0x71,
- 0x00, 0xCB, 0xFC, 0x18, 0xFC, 0x28, 0x08, 0x26, 0x1B, 0xE0, 0x20,
- 0x77, 0x12, 0xA7, 0x00, 0x4A, 0xFB, 0xCF, 0xFE, 0xF9, 0x00, 0x58,
- 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1C, 0x00, 0xE5, 0x00, 0x02, 0x00,
- 0x1E, 0xFC, 0x2B, 0xFD, 0x87, 0x0B, 0xAA, 0x1D, 0x8D, 0x1F, 0xE9,
- 0x0E, 0xA6, 0xFE, 0x9B, 0xFB, 0x78, 0xFF, 0xF8, 0x00, 0x36, 0x00,
- 0xF9, 0xFF, 0xF8, 0xFF, 0x37, 0x00, 0xF9, 0x00, 0x72, 0xFF, 0x96,
- 0xFB, 0xB8, 0xFE, 0x0D, 0x0F, 0x9D, 0x1F, 0x94, 0x1D, 0x65, 0x0B,
- 0x1E, 0xFD, 0x24, 0xFC, 0x06, 0x00, 0xE4, 0x00, 0x1B, 0x00, 0xFC,
- 0xFF, 0xF7, 0xFF, 0x5A, 0x00, 0xF9, 0x00, 0xC8, 0xFE, 0x49, 0xFB,
- 0xBE, 0x00, 0x9A, 0x12, 0xE9, 0x20, 0x0A, 0x1B, 0x08, 0x08, 0x10,
- 0xFC, 0xD2, 0xFC, 0x74, 0x00, 0xC3, 0x00, 0x08, 0x00, 0xFE, 0xFF,
- 0xF9, 0xFF, 0x82, 0x00, 0xDF, 0x00, 0x0B, 0xFE, 0x47, 0xFB, 0x37,
- 0x03, 0x0C, 0x16, 0x81, 0x21, 0x0E, 0x18, 0xF2, 0x04, 0x73, 0xFB,
- 0x92, 0xFD, 0xC0, 0x00, 0x9B, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xAB, 0x00, 0xA7, 0x00, 0x47, 0xFD, 0xA2, 0xFB,
- 0x18, 0x06, 0x40, 0x19, 0x5D, 0x21, 0xBE, 0x14, 0x37, 0x02, 0x3D,
- 0xFB, 0x55, 0xFE, 0xEC, 0x00, 0x72, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
- 0x0E, 0x00, 0xD1, 0x00, 0x4E, 0x00, 0x8C, 0xFC, 0x6A, 0xFC, 0x4C,
- 0x09, 0x13, 0x1C, 0x7E, 0x20, 0x3D, 0x11, 0xE8, 0xFF, 0x5F, 0xFB,
- 0x0C, 0xFF, 0xFB, 0x00, 0x4C, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x24,
- 0x00, 0xEE, 0x00, 0xD3, 0xFF, 0xEA, 0xFB, 0xA7, 0xFD, 0xBC, 0x0C,
- 0x68, 0x1E, 0xEF, 0x1E, 0xAF, 0x0D, 0x11, 0xFE, 0xC5, 0xFB, 0xAD,
- 0xFF, 0xF3, 0x00, 0x2C, 0x00, 0xFA, 0xFF, 0xF8, 0xFF, 0x42, 0x00,
- 0xFB, 0x00, 0x3A, 0xFF, 0x74, 0xFB, 0x5D, 0xFF, 0x48, 0x10, 0x24,
- 0x20, 0xC2, 0x1C, 0x35, 0x0A, 0xB3, 0xFC, 0x5D, 0xFC, 0x30, 0x00,
- 0xDA, 0x00, 0x13, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x67, 0x00, 0xF3,
- 0x00, 0x88, 0xFE, 0x3E, 0xFB, 0x8C, 0x01, 0xD0, 0x13, 0x33, 0x21,
- 0x0D, 0x1A, 0xEE, 0x06, 0xCD, 0xFB, 0x13, 0xFD, 0x92, 0x00, 0xB6,
- 0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFA, 0xFF, 0x90, 0x00,
- 0xCF, 0x00, 0xC7, 0xFD, 0x5B, 0xFB, 0x2B, 0x04, 0x31, 0x17, 0x8A,
- 0x21, 0xF0, 0x16, 0xF4, 0x03, 0x56, 0xFB, 0xD6, 0xFD, 0xD3, 0x00,
- 0x8D, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0xB9, 0x00, 0x8C,
- 0x00, 0x05, 0xFD, 0xDB, 0xFB, 0x2C, 0x07, 0x47, 0x1A, 0x25, 0x21,
- 0x8B, 0x13, 0x5D, 0x01, 0x40, 0xFB, 0x97, 0xFE, 0xF5, 0x00, 0x64,
- 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x15, 0x00, 0xDC, 0x00, 0x27, 0x00,
- 0x50, 0xFC, 0xCA, 0xFC, 0x78, 0x0A, 0xF2, 0x1C, 0x07, 0x20, 0x02,
- 0x10, 0x37, 0xFF, 0x7B, 0xFB, 0x47, 0xFF, 0xFB, 0x00, 0x40, 0x00,
- 0xF8, 0xFF, 0xF9, 0xFF, 0x2E, 0x00, 0xF5, 0x00, 0xA2, 0xFF, 0xBB,
- 0xFB, 0x31, 0xFE, 0xF5, 0x0D, 0x14, 0x1F, 0x3F, 0x1E, 0x77, 0x0C,
- 0x8A, 0xFD, 0xF5, 0xFB, 0xDE, 0xFF, 0xEC, 0x00, 0x22, 0x00, 0xFB,
- 0xFF, 0xF7, 0xFF, 0x4E, 0x00, 0xFB, 0x00, 0xFF, 0xFE, 0x59, 0xFB,
- 0x11, 0x00, 0x83, 0x11, 0x96, 0x20, 0xE0, 0x1B, 0x0B, 0x09, 0x56,
- 0xFC, 0x99, 0xFC, 0x56, 0x00, 0xCE, 0x00, 0x0D, 0x00, 0xFE, 0xFF,
- 0xF8, 0xFF, 0x75, 0x00, 0xEA, 0x00, 0x47, 0xFE, 0x3E, 0xFB, 0x69,
- 0x02, 0x02, 0x15, 0x66, 0x21, 0x04, 0x19, 0xDC, 0x05, 0x98, 0xFB,
- 0x56, 0xFD, 0xAD, 0x00, 0xA8, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
- 0x00, 0xFD, 0xFF, 0x9E, 0x00, 0xBC, 0x00, 0x83, 0xFD, 0x7B, 0xFB,
- 0x2B, 0x05, 0x4C, 0x18, 0x7C, 0x21, 0xCA, 0x15, 0x03, 0x03, 0x44,
- 0xFB, 0x1A, 0xFE, 0xE2, 0x00, 0x7E, 0x00, 0xF8, 0xFF, 0xFE, 0xFF,
- 0x09, 0x00, 0xC6, 0x00, 0x6D, 0x00, 0xC3, 0xFC, 0x20, 0xFC, 0x49,
- 0x08, 0x41, 0x1B, 0xD6, 0x20, 0x54, 0x12, 0x92, 0x00, 0x4C, 0xFB,
- 0xD6, 0xFE, 0xFA, 0x00, 0x57, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1D,
- 0x00, 0xE6, 0x00, 0xFD, 0xFF, 0x18, 0xFC, 0x38, 0xFD, 0xA9, 0x0B,
- 0xC0, 0x1D, 0x7C, 0x1F, 0xC6, 0x0E, 0x95, 0xFE, 0x9F, 0xFB, 0x7E,
- 0xFF, 0xF8, 0x00, 0x35, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x38, 0x00,
- 0xF9, 0x00, 0x6C, 0xFF, 0x92, 0xFB, 0xC9, 0xFE, 0x2F, 0x0F, 0xAD,
- 0x1F, 0x7D, 0x1D, 0x42, 0x0B, 0x12, 0xFD, 0x2A, 0xFC, 0x0B, 0x00,
- 0xE3, 0x00, 0x1A, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5B, 0x00, 0xF8,
- 0x00, 0xC1, 0xFE, 0x47, 0xFB, 0xD4, 0x00, 0xBC, 0x12, 0xF3, 0x20,
- 0xEF, 0x1A, 0xE9, 0x07, 0x08, 0xFC, 0xD9, 0xFC, 0x78, 0x00, 0xC2,
- 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x83, 0x00, 0xDD, 0x00,
- 0x04, 0xFE, 0x49, 0xFB, 0x52, 0x03, 0x2D, 0x16, 0x83, 0x21, 0xEF,
- 0x17, 0xD5, 0x04, 0x6F, 0xFB, 0x9A, 0xFD, 0xC3, 0x00, 0x9A, 0x00,
- 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xAD, 0x00, 0xA4,
- 0x00, 0x40, 0xFD, 0xA8, 0xFB, 0x36, 0x06, 0x5E, 0x19, 0x58, 0x21,
- 0x9C, 0x14, 0x1E, 0x02, 0x3D, 0xFB, 0x5D, 0xFE, 0xED, 0x00, 0x70,
- 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, 0x00, 0xD2, 0x00, 0x4A, 0x00,
- 0x85, 0xFC, 0x74, 0xFC, 0x6D, 0x09, 0x2D, 0x1C, 0x72, 0x20, 0x1A,
- 0x11, 0xD4, 0xFF, 0x61, 0xFB, 0x13, 0xFF, 0xFC, 0x00, 0x4A, 0x00,
- 0xF7, 0xFF, 0xFA, 0xFF, 0x25, 0x00, 0xEF, 0x00, 0xCE, 0xFF, 0xE4,
- 0xFB, 0xB5, 0xFD, 0xDE, 0x0C, 0x7C, 0x1E, 0xDD, 0x1E, 0x8C, 0x0D,
- 0x01, 0xFE, 0xCA, 0xFB, 0xB3, 0xFF, 0xF3, 0x00, 0x2B, 0x00, 0xFA,
- 0xFF, 0xF8, 0xFF, 0x44, 0x00, 0xFB, 0x00, 0x34, 0xFF, 0x71, 0xFB,
- 0x71, 0xFF, 0x6B, 0x10, 0x32, 0x20, 0xA9, 0x1C, 0x13, 0x0A, 0xA8,
- 0xFC, 0x63, 0xFC, 0x35, 0x00, 0xD9, 0x00, 0x12, 0x00, 0xFD, 0xFF,
- 0xF7, 0xFF, 0x69, 0x00, 0xF2, 0x00, 0x81, 0xFE, 0x3E, 0xFB, 0xA4,
- 0x01, 0xF2, 0x13, 0x3A, 0x21, 0xF0, 0x19, 0xCF, 0x06, 0xC7, 0xFB,
- 0x1B, 0xFD, 0x96, 0x00, 0xB4, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00,
- 0x00, 0xFB, 0xFF, 0x92, 0x00, 0xCD, 0x00, 0xC0, 0xFD, 0x5E, 0xFB,
- 0x47, 0x04, 0x51, 0x17, 0x8A, 0x21, 0xD0, 0x16, 0xD9, 0x03, 0x53,
- 0xFB, 0xDE, 0xFD, 0xD5, 0x00, 0x8B, 0x00, 0xFA, 0xFF, 0xFF, 0xFF,
- 0x04, 0x00, 0xBA, 0x00, 0x89, 0x00, 0xFD, 0xFC, 0xE2, 0xFB, 0x4B,
- 0x07, 0x63, 0x1A, 0x1D, 0x21, 0x69, 0x13, 0x46, 0x01, 0x41, 0xFB,
- 0x9E, 0xFE, 0xF5, 0x00, 0x63, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x16,
- 0x00, 0xDD, 0x00, 0x23, 0x00, 0x49, 0xFC, 0xD5, 0xFC, 0x99, 0x0A,
- 0x09, 0x1D, 0xF9, 0x1F, 0xDF, 0x0F, 0x24, 0xFF, 0x7F, 0xFB, 0x4D,
- 0xFF, 0xFB, 0x00, 0x3F, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2F, 0x00,
- 0xF5, 0x00, 0x9C, 0xFF, 0xB6, 0xFB, 0x41, 0xFE, 0x17, 0x0E, 0x26,
- 0x1F, 0x2B, 0x1E, 0x54, 0x0C, 0x7C, 0xFD, 0xFA, 0xFB, 0xE3, 0xFF,
- 0xEB, 0x00, 0x21, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x50, 0x00, 0xFB,
- 0x00, 0xF8, 0xFE, 0x57, 0xFB, 0x26, 0x00, 0xA6, 0x11, 0xA1, 0x20,
- 0xC6, 0x1B, 0xEA, 0x08, 0x4D, 0xFC, 0xA0, 0xFC, 0x5A, 0x00, 0xCD,
- 0x00, 0x0C, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0xE9, 0x00,
- 0x3F, 0xFE, 0x3F, 0xFB, 0x82, 0x02, 0x23, 0x15, 0x6B, 0x21, 0xE5,
- 0x18, 0xBE, 0x05, 0x93, 0xFB, 0x5E, 0xFD, 0xAF, 0x00, 0xA6, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xA0, 0x00, 0xB9,
- 0x00, 0x7C, 0xFD, 0x80, 0xFB, 0x48, 0x05, 0x6B, 0x18, 0x79, 0x21,
- 0xA9, 0x15, 0xE9, 0x02, 0x43, 0xFB, 0x21, 0xFE, 0xE3, 0x00, 0x7D,
- 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x09, 0x00, 0xC7, 0x00, 0x69, 0x00,
- 0xBC, 0xFC, 0x29, 0xFC, 0x69, 0x08, 0x5C, 0x1B, 0xCC, 0x20, 0x32,
- 0x12, 0x7C, 0x00, 0x4E, 0xFB, 0xDD, 0xFE, 0xFA, 0x00, 0x56, 0x00,
- 0xF7, 0xFF, 0xFB, 0xFF, 0x1D, 0x00, 0xE7, 0x00, 0xF8, 0xFF, 0x12,
- 0xFC, 0x45, 0xFD, 0xCB, 0x0B, 0xD6, 0x1D, 0x6C, 0x1F, 0xA3, 0x0E,
- 0x84, 0xFE, 0xA4, 0xFB, 0x84, 0xFF, 0xF7, 0x00, 0x34, 0x00, 0xF9,
- 0xFF, 0xF8, 0xFF, 0x3A, 0x00, 0xFA, 0x00, 0x66, 0xFF, 0x8E, 0xFB,
- 0xDB, 0xFE, 0x53, 0x0F, 0xBD, 0x1F, 0x66, 0x1D, 0x21, 0x0B, 0x05,
- 0xFD, 0x30, 0xFC, 0x10, 0x00, 0xE2, 0x00, 0x19, 0x00, 0xFC, 0xFF,
- 0xF7, 0xFF, 0x5D, 0x00, 0xF8, 0x00, 0xBA, 0xFE, 0x46, 0xFB, 0xEA,
- 0x00, 0xDF, 0x12, 0xFC, 0x20, 0xD3, 0x1A, 0xC9, 0x07, 0x00, 0xFC,
- 0xE0, 0xFC, 0x7B, 0x00, 0xC0, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9,
- 0xFF, 0x85, 0x00, 0xDC, 0x00, 0xFC, 0xFD, 0x4A, 0xFB, 0x6C, 0x03,
- 0x4E, 0x16, 0x85, 0x21, 0xCF, 0x17, 0xB8, 0x04, 0x6C, 0xFB, 0xA2,
- 0xFD, 0xC5, 0x00, 0x98, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
- 0x01, 0x00, 0xAE, 0x00, 0xA1, 0x00, 0x38, 0xFD, 0xAE, 0xFB, 0x54,
- 0x06, 0x7C, 0x19, 0x53, 0x21, 0x7B, 0x14, 0x05, 0x02, 0x3D, 0xFB,
- 0x64, 0xFE, 0xEE, 0x00, 0x6F, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F,
- 0x00, 0xD4, 0x00, 0x46, 0x00, 0x7E, 0xFC, 0x7E, 0xFC, 0x8E, 0x09,
- 0x46, 0x1C, 0x66, 0x20, 0xF7, 0x10, 0xC0, 0xFF, 0x64, 0xFB, 0x1A,
- 0xFF, 0xFC, 0x00, 0x49, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x26, 0x00,
- 0xF0, 0x00, 0xC9, 0xFF, 0xDF, 0xFB, 0xC4, 0xFD, 0x01, 0x0D, 0x90,
- 0x1E, 0xCA, 0x1E, 0x69, 0x0D, 0xF1, 0xFD, 0xCF, 0xFB, 0xB8, 0xFF,
- 0xF2, 0x00, 0x29, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x45, 0x00, 0xFC,
- 0x00, 0x2D, 0xFF, 0x6D, 0xFB, 0x84, 0xFF, 0x8E, 0x10, 0x3F, 0x20,
- 0x91, 0x1C, 0xF2, 0x09, 0x9D, 0xFC, 0x6A, 0xFC, 0x39, 0x00, 0xD7,
- 0x00, 0x12, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6A, 0x00, 0xF1, 0x00,
- 0x7A, 0xFE, 0x3D, 0xFB, 0xBC, 0x01, 0x14, 0x14, 0x41, 0x21, 0xD4,
- 0x19, 0xB0, 0x06, 0xC0, 0xFB, 0x22, 0xFD, 0x99, 0x00, 0xB3, 0x00,
- 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x93, 0x00, 0xCB,
- 0x00, 0xB8, 0xFD, 0x61, 0xFB, 0x63, 0x04, 0x71, 0x17, 0x89, 0x21,
- 0xB0, 0x16, 0xBD, 0x03, 0x51, 0xFB, 0xE6, 0xFD, 0xD7, 0x00, 0x8A,
- 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0xBC, 0x00, 0x86, 0x00,
- 0xF6, 0xFC, 0xE9, 0xFB, 0x6A, 0x07, 0x80, 0x1A, 0x15, 0x21, 0x47,
- 0x13, 0x2F, 0x01, 0x42, 0xFB, 0xA5, 0xFE, 0xF6, 0x00, 0x61, 0x00,
- 0xF7, 0xFF, 0xFC, 0xFF, 0x16, 0x00, 0xDF, 0x00, 0x1E, 0x00, 0x43,
- 0xFC, 0xE1, 0xFC, 0xBB, 0x0A, 0x21, 0x1D, 0xEA, 0x1F, 0xBC, 0x0F,
- 0x12, 0xFF, 0x82, 0xFB, 0x54, 0xFF, 0xFA, 0x00, 0x3D, 0x00, 0xF8,
- 0xFF, 0xF9, 0xFF, 0x30, 0x00, 0xF6, 0x00, 0x96, 0xFF, 0xB1, 0xFB,
- 0x51, 0xFE, 0x3A, 0x0E, 0x38, 0x1F, 0x16, 0x1E, 0x32, 0x0C, 0x6E,
- 0xFD, 0x00, 0xFC, 0xE8, 0xFF, 0xEA, 0x00, 0x20, 0x00, 0xFB, 0xFF,
- 0xF7, 0xFF, 0x51, 0x00, 0xFB, 0x00, 0xF1, 0xFE, 0x54, 0xFB, 0x3B,
- 0x00, 0xC9, 0x11, 0xAD, 0x20, 0xAC, 0x1B, 0xCA, 0x08, 0x44, 0xFC,
- 0xA7, 0xFC, 0x5E, 0x00, 0xCC, 0x00, 0x0B, 0x00, 0xFE, 0xFF, 0xF8,
- 0xFF, 0x78, 0x00, 0xE7, 0x00, 0x38, 0xFE, 0x40, 0xFB, 0x9B, 0x02,
- 0x45, 0x15, 0x6F, 0x21, 0xC7, 0x18, 0xA1, 0x05, 0x8E, 0xFB, 0x65,
- 0xFD, 0xB2, 0x00, 0xA5, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFE, 0xFF, 0xA2, 0x00, 0xB7, 0x00, 0x74, 0xFD, 0x84, 0xFB, 0x66,
- 0x05, 0x8A, 0x18, 0x76, 0x21, 0x87, 0x15, 0xCF, 0x02, 0x41, 0xFB,
- 0x29, 0xFE, 0xE5, 0x00, 0x7B, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0A,
- 0x00, 0xC9, 0x00, 0x66, 0x00, 0xB5, 0xFC, 0x32, 0xFC, 0x89, 0x08,
- 0x77, 0x1B, 0xC2, 0x20, 0x0F, 0x12, 0x66, 0x00, 0x50, 0xFB, 0xE4,
- 0xFE, 0xFA, 0x00, 0x54, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1E, 0x00,
- 0xE8, 0x00, 0xF3, 0xFF, 0x0C, 0xFC, 0x53, 0xFD, 0xED, 0x0B, 0xEB,
- 0x1D, 0x5A, 0x1F, 0x80, 0x0E, 0x73, 0xFE, 0xA8, 0xFB, 0x8A, 0xFF,
- 0xF7, 0x00, 0x32, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3B, 0x00, 0xFA,
- 0x00, 0x60, 0xFF, 0x8A, 0xFB, 0xED, 0xFE, 0x76, 0x0F, 0xCC, 0x1F,
- 0x4F, 0x1D, 0xFF, 0x0A, 0xF9, 0xFC, 0x36, 0xFC, 0x15, 0x00, 0xE1,
- 0x00, 0x18, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5E, 0x00, 0xF7, 0x00,
- 0xB3, 0xFE, 0x44, 0xFB, 0x01, 0x01, 0x02, 0x13, 0x04, 0x21, 0xB8,
- 0x1A, 0xA9, 0x07, 0xF8, 0xFB, 0xE7, 0xFC, 0x7F, 0x00, 0xBF, 0x00,
- 0x06, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x86, 0x00, 0xDA, 0x00, 0xF5,
- 0xFD, 0x4C, 0xFB, 0x87, 0x03, 0x6E, 0x16, 0x86, 0x21, 0xB0, 0x17,
- 0x9C, 0x04, 0x68, 0xFB, 0xA9, 0xFD, 0xC7, 0x00, 0x96, 0x00, 0xFB,
- 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xB0, 0x00, 0x9F, 0x00,
- 0x31, 0xFD, 0xB4, 0xFB, 0x73, 0x06, 0x99, 0x19, 0x4D, 0x21, 0x59,
- 0x14, 0xED, 0x01, 0x3D, 0xFB, 0x6B, 0xFE, 0xEF, 0x00, 0x6D, 0x00,
- 0xF7, 0xFF, 0xFD, 0xFF, 0x10, 0x00, 0xD5, 0x00, 0x42, 0x00, 0x77,
- 0xFC, 0x88, 0xFC, 0xAF, 0x09, 0x5F, 0x1C, 0x59, 0x20, 0xD4, 0x10,
- 0xAC, 0xFF, 0x67, 0xFB, 0x20, 0xFF, 0xFC, 0x00, 0x48, 0x00, 0xF7,
- 0xFF, 0xFA, 0xFF, 0x27, 0x00, 0xF0, 0x00, 0xC3, 0xFF, 0xD9, 0xFB,
- 0xD3, 0xFD, 0x24, 0x0D, 0xA3, 0x1E, 0xB7, 0x1E, 0x46, 0x0D, 0xE2,
- 0xFD, 0xD4, 0xFB, 0xBE, 0xFF, 0xF1, 0x00, 0x28, 0x00, 0xFA, 0xFF,
- 0xF7, 0xFF, 0x46, 0x00, 0xFC, 0x00, 0x27, 0xFF, 0x6A, 0xFB, 0x98,
- 0xFF, 0xB1, 0x10, 0x4C, 0x20, 0x78, 0x1C, 0xD1, 0x09, 0x93, 0xFC,
- 0x71, 0xFC, 0x3D, 0x00, 0xD6, 0x00, 0x11, 0x00, 0xFD, 0xFF, 0xF7,
- 0xFF, 0x6C, 0x00, 0xF0, 0x00, 0x72, 0xFE, 0x3D, 0xFB, 0xD4, 0x01,
- 0x36, 0x14, 0x47, 0x21, 0xB6, 0x19, 0x91, 0x06, 0xBA, 0xFB, 0x29,
- 0xFD, 0x9C, 0x00, 0xB1, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00,
- 0xFB, 0xFF, 0x95, 0x00, 0xC9, 0x00, 0xB1, 0xFD, 0x65, 0xFB, 0x80,
- 0x04, 0x90, 0x17, 0x88, 0x21, 0x8F, 0x16, 0xA2, 0x03, 0x4E, 0xFB,
- 0xED, 0xFD, 0xD9, 0x00, 0x88, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x05,
- 0x00, 0xBD, 0x00, 0x82, 0x00, 0xEF, 0xFC, 0xF0, 0xFB, 0x8A, 0x07,
- 0x9C, 0x1A, 0x0D, 0x21, 0x24, 0x13, 0x18, 0x01, 0x43, 0xFB, 0xAC,
- 0xFE, 0xF7, 0x00, 0x60, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x17, 0x00,
- 0xE0, 0x00, 0x1A, 0x00, 0x3D, 0xFC, 0xED, 0xFC, 0xDD, 0x0A, 0x38,
- 0x1D, 0xDB, 0x1F, 0x99, 0x0F, 0xFF, 0xFE, 0x86, 0xFB, 0x5A, 0xFF,
- 0xFA, 0x00, 0x3C, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x31, 0x00, 0xF6,
- 0x00, 0x90, 0xFF, 0xAD, 0xFB, 0x62, 0xFE, 0x5D, 0x0E, 0x49, 0x1F,
- 0x01, 0x1E, 0x10, 0x0C, 0x60, 0xFD, 0x06, 0xFC, 0xEE, 0xFF, 0xE9,
- 0x00, 0x1F, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x53, 0x00, 0xFB, 0x00,
- 0xEB, 0xFE, 0x52, 0xFB, 0x51, 0x00, 0xEC, 0x11, 0xB7, 0x20, 0x91,
- 0x1B, 0xA9, 0x08, 0x3B, 0xFC, 0xAE, 0xFC, 0x62, 0x00, 0xCA, 0x00,
- 0x0B, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7A, 0x00, 0xE6, 0x00, 0x30,
- 0xFE, 0x40, 0xFB, 0xB5, 0x02, 0x66, 0x15, 0x73, 0x21, 0xA9, 0x18,
- 0x83, 0x05, 0x89, 0xFB, 0x6D, 0xFD, 0xB4, 0x00, 0xA3, 0x00, 0xFE,
- 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xA3, 0x00, 0xB4, 0x00,
- 0x6D, 0xFD, 0x89, 0xFB, 0x83, 0x05, 0xA9, 0x18, 0x73, 0x21, 0x66,
- 0x15, 0xB5, 0x02, 0x40, 0xFB, 0x30, 0xFE, 0xE6, 0x00, 0x7A, 0x00,
- 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, 0xCA, 0x00, 0x62, 0x00, 0xAE,
- 0xFC, 0x3B, 0xFC, 0xA9, 0x08, 0x91, 0x1B, 0xB7, 0x20, 0xEC, 0x11,
- 0x51, 0x00, 0x52, 0xFB, 0xEB, 0xFE, 0xFB, 0x00, 0x53, 0x00, 0xF7,
- 0xFF, 0xFB, 0xFF, 0x1F, 0x00, 0xE9, 0x00, 0xEE, 0xFF, 0x06, 0xFC,
- 0x60, 0xFD, 0x10, 0x0C, 0x01, 0x1E, 0x49, 0x1F, 0x5D, 0x0E, 0x62,
- 0xFE, 0xAD, 0xFB, 0x90, 0xFF, 0xF6, 0x00, 0x31, 0x00, 0xF9, 0xFF,
- 0xF8, 0xFF, 0x3C, 0x00, 0xFA, 0x00, 0x5A, 0xFF, 0x86, 0xFB, 0xFF,
- 0xFE, 0x99, 0x0F, 0xDB, 0x1F, 0x38, 0x1D, 0xDD, 0x0A, 0xED, 0xFC,
- 0x3D, 0xFC, 0x1A, 0x00, 0xE0, 0x00, 0x17, 0x00, 0xFC, 0xFF, 0xF7,
- 0xFF, 0x60, 0x00, 0xF7, 0x00, 0xAC, 0xFE, 0x43, 0xFB, 0x18, 0x01,
- 0x24, 0x13, 0x0D, 0x21, 0x9C, 0x1A, 0x8A, 0x07, 0xF0, 0xFB, 0xEF,
- 0xFC, 0x82, 0x00, 0xBD, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xF9, 0xFF,
- 0x88, 0x00, 0xD9, 0x00, 0xED, 0xFD, 0x4E, 0xFB, 0xA2, 0x03, 0x8F,
- 0x16, 0x88, 0x21, 0x90, 0x17, 0x80, 0x04, 0x65, 0xFB, 0xB1, 0xFD,
- 0xC9, 0x00, 0x95, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02,
- 0x00, 0xB1, 0x00, 0x9C, 0x00, 0x29, 0xFD, 0xBA, 0xFB, 0x91, 0x06,
- 0xB6, 0x19, 0x47, 0x21, 0x36, 0x14, 0xD4, 0x01, 0x3D, 0xFB, 0x72,
- 0xFE, 0xF0, 0x00, 0x6C, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x11, 0x00,
- 0xD6, 0x00, 0x3D, 0x00, 0x71, 0xFC, 0x93, 0xFC, 0xD1, 0x09, 0x78,
- 0x1C, 0x4C, 0x20, 0xB1, 0x10, 0x98, 0xFF, 0x6A, 0xFB, 0x27, 0xFF,
- 0xFC, 0x00, 0x46, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x28, 0x00, 0xF1,
- 0x00, 0xBE, 0xFF, 0xD4, 0xFB, 0xE2, 0xFD, 0x46, 0x0D, 0xB7, 0x1E,
- 0xA3, 0x1E, 0x24, 0x0D, 0xD3, 0xFD, 0xD9, 0xFB, 0xC3, 0xFF, 0xF0,
- 0x00, 0x27, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x48, 0x00, 0xFC, 0x00,
- 0x20, 0xFF, 0x67, 0xFB, 0xAC, 0xFF, 0xD4, 0x10, 0x59, 0x20, 0x5F,
- 0x1C, 0xAF, 0x09, 0x88, 0xFC, 0x77, 0xFC, 0x42, 0x00, 0xD5, 0x00,
- 0x10, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6D, 0x00, 0xEF, 0x00, 0x6B,
- 0xFE, 0x3D, 0xFB, 0xED, 0x01, 0x59, 0x14, 0x4D, 0x21, 0x99, 0x19,
- 0x73, 0x06, 0xB4, 0xFB, 0x31, 0xFD, 0x9F, 0x00, 0xB0, 0x00, 0x01,
- 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x96, 0x00, 0xC7, 0x00,
- 0xA9, 0xFD, 0x68, 0xFB, 0x9C, 0x04, 0xB0, 0x17, 0x86, 0x21, 0x6E,
- 0x16, 0x87, 0x03, 0x4C, 0xFB, 0xF5, 0xFD, 0xDA, 0x00, 0x86, 0x00,
- 0xF9, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0xBF, 0x00, 0x7F, 0x00, 0xE7,
- 0xFC, 0xF8, 0xFB, 0xA9, 0x07, 0xB8, 0x1A, 0x04, 0x21, 0x02, 0x13,
- 0x01, 0x01, 0x44, 0xFB, 0xB3, 0xFE, 0xF7, 0x00, 0x5E, 0x00, 0xF7,
- 0xFF, 0xFC, 0xFF, 0x18, 0x00, 0xE1, 0x00, 0x15, 0x00, 0x36, 0xFC,
- 0xF9, 0xFC, 0xFF, 0x0A, 0x4F, 0x1D, 0xCC, 0x1F, 0x76, 0x0F, 0xED,
- 0xFE, 0x8A, 0xFB, 0x60, 0xFF, 0xFA, 0x00, 0x3B, 0x00, 0xF8, 0xFF,
- 0xF9, 0xFF, 0x32, 0x00, 0xF7, 0x00, 0x8A, 0xFF, 0xA8, 0xFB, 0x73,
- 0xFE, 0x80, 0x0E, 0x5A, 0x1F, 0xEB, 0x1D, 0xED, 0x0B, 0x53, 0xFD,
- 0x0C, 0xFC, 0xF3, 0xFF, 0xE8, 0x00, 0x1E, 0x00, 0xFB, 0xFF, 0xF7,
- 0xFF, 0x54, 0x00, 0xFA, 0x00, 0xE4, 0xFE, 0x50, 0xFB, 0x66, 0x00,
- 0x0F, 0x12, 0xC2, 0x20, 0x77, 0x1B, 0x89, 0x08, 0x32, 0xFC, 0xB5,
- 0xFC, 0x66, 0x00, 0xC9, 0x00, 0x0A, 0x00, 0xFE, 0xFF, 0xF8, 0xFF,
- 0x7B, 0x00, 0xE5, 0x00, 0x29, 0xFE, 0x41, 0xFB, 0xCF, 0x02, 0x87,
- 0x15, 0x76, 0x21, 0x8A, 0x18, 0x66, 0x05, 0x84, 0xFB, 0x74, 0xFD,
- 0xB7, 0x00, 0xA2, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE,
- 0xFF, 0xA5, 0x00, 0xB2, 0x00, 0x65, 0xFD, 0x8E, 0xFB, 0xA1, 0x05,
- 0xC7, 0x18, 0x6F, 0x21, 0x45, 0x15, 0x9B, 0x02, 0x40, 0xFB, 0x38,
- 0xFE, 0xE7, 0x00, 0x78, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00,
- 0xCC, 0x00, 0x5E, 0x00, 0xA7, 0xFC, 0x44, 0xFC, 0xCA, 0x08, 0xAC,
- 0x1B, 0xAD, 0x20, 0xC9, 0x11, 0x3B, 0x00, 0x54, 0xFB, 0xF1, 0xFE,
- 0xFB, 0x00, 0x51, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x20, 0x00, 0xEA,
- 0x00, 0xE8, 0xFF, 0x00, 0xFC, 0x6E, 0xFD, 0x32, 0x0C, 0x16, 0x1E,
- 0x38, 0x1F, 0x3A, 0x0E, 0x51, 0xFE, 0xB1, 0xFB, 0x96, 0xFF, 0xF6,
- 0x00, 0x30, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3D, 0x00, 0xFA, 0x00,
- 0x54, 0xFF, 0x82, 0xFB, 0x12, 0xFF, 0xBC, 0x0F, 0xEA, 0x1F, 0x21,
- 0x1D, 0xBB, 0x0A, 0xE1, 0xFC, 0x43, 0xFC, 0x1E, 0x00, 0xDF, 0x00,
- 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x61, 0x00, 0xF6, 0x00, 0xA5,
- 0xFE, 0x42, 0xFB, 0x2F, 0x01, 0x47, 0x13, 0x15, 0x21, 0x80, 0x1A,
- 0x6A, 0x07, 0xE9, 0xFB, 0xF6, 0xFC, 0x86, 0x00, 0xBC, 0x00, 0x05,
- 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8A, 0x00, 0xD7, 0x00, 0xE6, 0xFD,
- 0x51, 0xFB, 0xBD, 0x03, 0xB0, 0x16, 0x89, 0x21, 0x71, 0x17, 0x63,
- 0x04, 0x61, 0xFB, 0xB8, 0xFD, 0xCB, 0x00, 0x93, 0x00, 0xFB, 0xFF,
- 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0xB3, 0x00, 0x99, 0x00, 0x22,
- 0xFD, 0xC0, 0xFB, 0xB0, 0x06, 0xD4, 0x19, 0x41, 0x21, 0x14, 0x14,
- 0xBC, 0x01, 0x3D, 0xFB, 0x7A, 0xFE, 0xF1, 0x00, 0x6A, 0x00, 0xF7,
- 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD7, 0x00, 0x39, 0x00, 0x6A, 0xFC,
- 0x9D, 0xFC, 0xF2, 0x09, 0x91, 0x1C, 0x3F, 0x20, 0x8E, 0x10, 0x84,
- 0xFF, 0x6D, 0xFB, 0x2D, 0xFF, 0xFC, 0x00, 0x45, 0x00, 0xF7, 0xFF,
- 0xFA, 0xFF, 0x29, 0x00, 0xF2, 0x00, 0xB8, 0xFF, 0xCF, 0xFB, 0xF1,
- 0xFD, 0x69, 0x0D, 0xCA, 0x1E, 0x90, 0x1E, 0x01, 0x0D, 0xC4, 0xFD,
- 0xDF, 0xFB, 0xC9, 0xFF, 0xF0, 0x00, 0x26, 0x00, 0xFA, 0xFF, 0xF7,
- 0xFF, 0x49, 0x00, 0xFC, 0x00, 0x1A, 0xFF, 0x64, 0xFB, 0xC0, 0xFF,
- 0xF7, 0x10, 0x66, 0x20, 0x46, 0x1C, 0x8E, 0x09, 0x7E, 0xFC, 0x7E,
- 0xFC, 0x46, 0x00, 0xD4, 0x00, 0x0F, 0x00, 0xFD, 0xFF, 0xF7, 0xFF,
- 0x6F, 0x00, 0xEE, 0x00, 0x64, 0xFE, 0x3D, 0xFB, 0x05, 0x02, 0x7B,
- 0x14, 0x53, 0x21, 0x7C, 0x19, 0x54, 0x06, 0xAE, 0xFB, 0x38, 0xFD,
- 0xA1, 0x00, 0xAE, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFC,
- 0xFF, 0x98, 0x00, 0xC5, 0x00, 0xA2, 0xFD, 0x6C, 0xFB, 0xB8, 0x04,
- 0xCF, 0x17, 0x85, 0x21, 0x4E, 0x16, 0x6C, 0x03, 0x4A, 0xFB, 0xFC,
- 0xFD, 0xDC, 0x00, 0x85, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
- 0xC0, 0x00, 0x7B, 0x00, 0xE0, 0xFC, 0x00, 0xFC, 0xC9, 0x07, 0xD3,
- 0x1A, 0xFC, 0x20, 0xDF, 0x12, 0xEA, 0x00, 0x46, 0xFB, 0xBA, 0xFE,
- 0xF8, 0x00, 0x5D, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x19, 0x00, 0xE2,
- 0x00, 0x10, 0x00, 0x30, 0xFC, 0x05, 0xFD, 0x21, 0x0B, 0x66, 0x1D,
- 0xBD, 0x1F, 0x53, 0x0F, 0xDB, 0xFE, 0x8E, 0xFB, 0x66, 0xFF, 0xFA,
- 0x00, 0x3A, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x34, 0x00, 0xF7, 0x00,
- 0x84, 0xFF, 0xA4, 0xFB, 0x84, 0xFE, 0xA3, 0x0E, 0x6C, 0x1F, 0xD6,
- 0x1D, 0xCB, 0x0B, 0x45, 0xFD, 0x12, 0xFC, 0xF8, 0xFF, 0xE7, 0x00,
- 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x56, 0x00, 0xFA, 0x00, 0xDD,
- 0xFE, 0x4E, 0xFB, 0x7C, 0x00, 0x32, 0x12, 0xCC, 0x20, 0x5C, 0x1B,
- 0x69, 0x08, 0x29, 0xFC, 0xBC, 0xFC, 0x69, 0x00, 0xC7, 0x00, 0x09,
- 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7D, 0x00, 0xE3, 0x00, 0x21, 0xFE,
- 0x43, 0xFB, 0xE9, 0x02, 0xA9, 0x15, 0x79, 0x21, 0x6B, 0x18, 0x48,
- 0x05, 0x80, 0xFB, 0x7C, 0xFD, 0xB9, 0x00, 0xA0, 0x00, 0xFD, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x00, 0xAF, 0x00, 0x5E,
- 0xFD, 0x93, 0xFB, 0xBE, 0x05, 0xE5, 0x18, 0x6B, 0x21, 0x23, 0x15,
- 0x82, 0x02, 0x3F, 0xFB, 0x3F, 0xFE, 0xE9, 0x00, 0x77, 0x00, 0xF8,
- 0xFF, 0xFE, 0xFF, 0x0C, 0x00, 0xCD, 0x00, 0x5A, 0x00, 0xA0, 0xFC,
- 0x4D, 0xFC, 0xEA, 0x08, 0xC6, 0x1B, 0xA1, 0x20, 0xA6, 0x11, 0x26,
- 0x00, 0x57, 0xFB, 0xF8, 0xFE, 0xFB, 0x00, 0x50, 0x00, 0xF7, 0xFF,
- 0xFB, 0xFF, 0x21, 0x00, 0xEB, 0x00, 0xE3, 0xFF, 0xFA, 0xFB, 0x7C,
- 0xFD, 0x54, 0x0C, 0x2B, 0x1E, 0x26, 0x1F, 0x17, 0x0E, 0x41, 0xFE,
- 0xB6, 0xFB, 0x9C, 0xFF, 0xF5, 0x00, 0x2F, 0x00, 0xF9, 0xFF, 0xF8,
- 0xFF, 0x3F, 0x00, 0xFB, 0x00, 0x4D, 0xFF, 0x7F, 0xFB, 0x24, 0xFF,
- 0xDF, 0x0F, 0xF9, 0x1F, 0x09, 0x1D, 0x99, 0x0A, 0xD5, 0xFC, 0x49,
- 0xFC, 0x23, 0x00, 0xDD, 0x00, 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF,
- 0x63, 0x00, 0xF5, 0x00, 0x9E, 0xFE, 0x41, 0xFB, 0x46, 0x01, 0x69,
- 0x13, 0x1D, 0x21, 0x63, 0x1A, 0x4B, 0x07, 0xE2, 0xFB, 0xFD, 0xFC,
- 0x89, 0x00, 0xBA, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8B,
- 0x00, 0xD5, 0x00, 0xDE, 0xFD, 0x53, 0xFB, 0xD9, 0x03, 0xD0, 0x16,
- 0x8A, 0x21, 0x51, 0x17, 0x47, 0x04, 0x5E, 0xFB, 0xC0, 0xFD, 0xCD,
- 0x00, 0x92, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00,
- 0xB4, 0x00, 0x96, 0x00, 0x1B, 0xFD, 0xC7, 0xFB, 0xCF, 0x06, 0xF0,
- 0x19, 0x3A, 0x21, 0xF2, 0x13, 0xA4, 0x01, 0x3E, 0xFB, 0x81, 0xFE,
- 0xF2, 0x00, 0x69, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD9,
- 0x00, 0x35, 0x00, 0x63, 0xFC, 0xA8, 0xFC, 0x13, 0x0A, 0xA9, 0x1C,
- 0x32, 0x20, 0x6B, 0x10, 0x71, 0xFF, 0x71, 0xFB, 0x34, 0xFF, 0xFB,
- 0x00, 0x44, 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2B, 0x00, 0xF3, 0x00,
- 0xB3, 0xFF, 0xCA, 0xFB, 0x01, 0xFE, 0x8C, 0x0D, 0xDD, 0x1E, 0x7C,
- 0x1E, 0xDE, 0x0C, 0xB5, 0xFD, 0xE4, 0xFB, 0xCE, 0xFF, 0xEF, 0x00,
- 0x25, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4A, 0x00, 0xFC, 0x00, 0x13,
- 0xFF, 0x61, 0xFB, 0xD4, 0xFF, 0x1A, 0x11, 0x72, 0x20, 0x2D, 0x1C,
- 0x6D, 0x09, 0x74, 0xFC, 0x85, 0xFC, 0x4A, 0x00, 0xD2, 0x00, 0x0F,
- 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x70, 0x00, 0xED, 0x00, 0x5D, 0xFE,
- 0x3D, 0xFB, 0x1E, 0x02, 0x9C, 0x14, 0x58, 0x21, 0x5E, 0x19, 0x36,
- 0x06, 0xA8, 0xFB, 0x40, 0xFD, 0xA4, 0x00, 0xAD, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x9A, 0x00, 0xC3, 0x00, 0x9A,
- 0xFD, 0x6F, 0xFB, 0xD5, 0x04, 0xEF, 0x17, 0x83, 0x21, 0x2D, 0x16,
- 0x52, 0x03, 0x49, 0xFB, 0x04, 0xFE, 0xDD, 0x00, 0x83, 0x00, 0xF9,
- 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC2, 0x00, 0x78, 0x00, 0xD9, 0xFC,
- 0x08, 0xFC, 0xE9, 0x07, 0xEF, 0x1A, 0xF3, 0x20, 0xBC, 0x12, 0xD4,
- 0x00, 0x47, 0xFB, 0xC1, 0xFE, 0xF8, 0x00, 0x5B, 0x00, 0xF7, 0xFF,
- 0xFC, 0xFF, 0x1A, 0x00, 0xE3, 0x00, 0x0B, 0x00, 0x2A, 0xFC, 0x12,
- 0xFD, 0x42, 0x0B, 0x7D, 0x1D, 0xAD, 0x1F, 0x2F, 0x0F, 0xC9, 0xFE,
- 0x92, 0xFB, 0x6C, 0xFF, 0xF9, 0x00, 0x38, 0x00, 0xF8, 0xFF, 0xF9,
- 0xFF, 0x35, 0x00, 0xF8, 0x00, 0x7E, 0xFF, 0x9F, 0xFB, 0x95, 0xFE,
- 0xC6, 0x0E, 0x7C, 0x1F, 0xC0, 0x1D, 0xA9, 0x0B, 0x38, 0xFD, 0x18,
- 0xFC, 0xFD, 0xFF, 0xE6, 0x00, 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF,
- 0x57, 0x00, 0xFA, 0x00, 0xD6, 0xFE, 0x4C, 0xFB, 0x92, 0x00, 0x54,
- 0x12, 0xD6, 0x20, 0x41, 0x1B, 0x49, 0x08, 0x20, 0xFC, 0xC3, 0xFC,
- 0x6D, 0x00, 0xC6, 0x00, 0x09, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7E,
- 0x00, 0xE2, 0x00, 0x1A, 0xFE, 0x44, 0xFB, 0x03, 0x03, 0xCA, 0x15,
- 0x7C, 0x21, 0x4C, 0x18, 0x2B, 0x05, 0x7B, 0xFB, 0x83, 0xFD, 0xBC,
- 0x00, 0x9E, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
- 0xA8, 0x00, 0xAD, 0x00, 0x56, 0xFD, 0x98, 0xFB, 0xDC, 0x05, 0x04,
- 0x19, 0x66, 0x21, 0x02, 0x15, 0x69, 0x02, 0x3E, 0xFB, 0x47, 0xFE,
- 0xEA, 0x00, 0x75, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xCE,
- 0x00, 0x56, 0x00, 0x99, 0xFC, 0x56, 0xFC, 0x0B, 0x09, 0xE0, 0x1B,
- 0x96, 0x20, 0x83, 0x11, 0x11, 0x00, 0x59, 0xFB, 0xFF, 0xFE, 0xFB,
- 0x00, 0x4E, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x22, 0x00, 0xEC, 0x00,
- 0xDE, 0xFF, 0xF5, 0xFB, 0x8A, 0xFD, 0x77, 0x0C, 0x3F, 0x1E, 0x14,
- 0x1F, 0xF5, 0x0D, 0x31, 0xFE, 0xBB, 0xFB, 0xA2, 0xFF, 0xF5, 0x00,
- 0x2E, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x40, 0x00, 0xFB, 0x00, 0x47,
- 0xFF, 0x7B, 0xFB, 0x37, 0xFF, 0x02, 0x10, 0x07, 0x20, 0xF2, 0x1C,
- 0x78, 0x0A, 0xCA, 0xFC, 0x50, 0xFC, 0x27, 0x00, 0xDC, 0x00, 0x15,
- 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x64, 0x00, 0xF5, 0x00, 0x97, 0xFE,
- 0x40, 0xFB, 0x5D, 0x01, 0x8B, 0x13, 0x25, 0x21, 0x47, 0x1A, 0x2C,
- 0x07, 0xDB, 0xFB, 0x05, 0xFD, 0x8C, 0x00, 0xB9, 0x00, 0x04, 0x00,
- 0xFF, 0xFF, 0xFA, 0xFF, 0x8D, 0x00, 0xD3, 0x00, 0xD6, 0xFD, 0x56,
- 0xFB, 0xF4, 0x03, 0xF0, 0x16, 0x8A, 0x21, 0x31, 0x17, 0x2B, 0x04,
- 0x5B, 0xFB, 0xC7, 0xFD, 0xCF, 0x00, 0x90, 0x00, 0xFA, 0xFF, 0x00,
- 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xB6, 0x00, 0x92, 0x00, 0x13, 0xFD,
- 0xCD, 0xFB, 0xEE, 0x06, 0x0D, 0x1A, 0x33, 0x21, 0xD0, 0x13, 0x8C,
- 0x01, 0x3E, 0xFB, 0x88, 0xFE, 0xF3, 0x00, 0x67, 0x00, 0xF7, 0xFF,
- 0x06, 0x00, 0x1D, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0xA1, 0x02, 0xA6,
- 0xF8, 0x56, 0x02, 0xA5, 0x28, 0xA5, 0x28, 0x56, 0x02, 0xA6, 0xF8,
- 0xA1, 0x02, 0xFE, 0x00, 0x03, 0xFF, 0x1D, 0x00, 0x06, 0x00, 0x00,
- 0x00, 0x21, 0x00, 0xA6, 0xFF, 0x3F, 0xFF, 0x0B, 0x03, 0x42, 0xFE,
- 0x3E, 0xF8, 0x7F, 0x15, 0xAC, 0x30, 0x7F, 0x15, 0x3E, 0xF8, 0x42,
- 0xFE, 0x0B, 0x03, 0x3F, 0xFF, 0xA6, 0xFF, 0x21, 0x00, 0x00, 0x00,
- 0xFA, 0xFF, 0xCE, 0xFF, 0x14, 0x01, 0x00, 0xFD, 0x35, 0x06, 0xD5,
- 0xF4, 0xDA, 0x15, 0x92, 0x40, 0xAE, 0xFE, 0xF3, 0xFC, 0x68, 0x03,
- 0x86, 0xFD, 0x51, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEC,
- 0xFF, 0xF9, 0xFF, 0xC6, 0x00, 0x55, 0xFD, 0x35, 0x06, 0x90, 0xF3,
- 0xE5, 0x1C, 0x6B, 0x3D, 0x71, 0xFA, 0x34, 0xFF, 0x46, 0x02, 0xFF,
- 0xFD, 0x2D, 0x01, 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDB, 0xFF,
- 0x2D, 0x00, 0x60, 0x00, 0xE1, 0xFD, 0xCE, 0x05, 0xED, 0xF2, 0xF3,
- 0x23, 0x20, 0x39, 0x22, 0xF7, 0x44, 0x01, 0x1F, 0x01, 0x89, 0xFE,
- 0xFB, 0x00, 0x9C, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC9, 0xFF, 0x68,
- 0x00, 0xE5, 0xFF, 0xA0, 0xFE, 0xFB, 0x04, 0x0C, 0xF3, 0xC5, 0x2A,
- 0xD8, 0x33, 0xC9, 0xF4, 0x0B, 0x03, 0x05, 0x00, 0x1A, 0xFF, 0xC1,
- 0x00, 0xAD, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB5, 0xFF, 0xA5, 0x00,
- 0x5C, 0xFF, 0x8C, 0xFF, 0xBF, 0x03, 0x06, 0xF4, 0x22, 0x31, 0xC8,
- 0x2D, 0x63, 0xF3, 0x76, 0x04, 0x08, 0xFF, 0xA7, 0xFF, 0x84, 0x00,
- 0xC0, 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA4, 0xFF, 0xE1, 0x00, 0xCB,
- 0xFE, 0x9B, 0x00, 0x21, 0x02, 0xEE, 0xF5, 0xCD, 0x36, 0x24, 0x27,
- 0xE1, 0xF2, 0x7A, 0x05, 0x33, 0xFE, 0x2A, 0x00, 0x47, 0x00, 0xD3,
- 0xFF, 0x04, 0x00, 0x0F, 0x00, 0x95, 0xFF, 0x17, 0x01, 0x3D, 0xFE,
- 0xBD, 0x01, 0x30, 0x00, 0xCC, 0xF8, 0x92, 0x3B, 0x2A, 0x20, 0x2E,
- 0xF3, 0x12, 0x06, 0x8F, 0xFD, 0x9A, 0x00, 0x10, 0x00, 0xE5, 0xFF,
- 0x02, 0x00, 0x10, 0x00, 0x8C, 0xFF, 0x42, 0x01, 0xBB, 0xFD, 0xE4,
- 0x02, 0x01, 0xFE, 0x9C, 0xFC, 0x45, 0x3F, 0x16, 0x19, 0x2D, 0xF4,
- 0x41, 0x06, 0x21, 0xFD, 0xF3, 0x00, 0xE0, 0xFF, 0xF4, 0xFF, 0x01,
- 0x00, 0x10, 0x00, 0x8B, 0xFF, 0x5D, 0x01, 0x4F, 0xFD, 0xFB, 0x03,
- 0xB2, 0xFB, 0x53, 0x01, 0xC2, 0x41, 0x24, 0x12, 0xBA, 0xF5, 0x0F,
- 0x06, 0xE9, 0xFC, 0x33, 0x01, 0xBB, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x0D, 0x00, 0x93, 0xFF, 0x63, 0x01, 0x04, 0xFD, 0xEF, 0x04, 0x62,
- 0xF9, 0xD7, 0x06, 0xF2, 0x42, 0x8D, 0x0B, 0xB0, 0xF7, 0x87, 0x05,
- 0xE6, 0xFC, 0x58, 0x01, 0xA0, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x07, 0x00, 0xA5, 0xFF, 0x52, 0x01, 0xE2, 0xFC, 0xAD, 0x05,
- 0x35, 0xF7, 0x08, 0x0D, 0xCB, 0x42, 0x81, 0x05, 0xE8, 0xF9, 0xBB,
- 0x04, 0x12, 0xFD, 0x64, 0x01, 0x90, 0xFF, 0x0E, 0x00, 0x00, 0x00,
- 0xFE, 0xFF, 0xC2, 0xFF, 0x27, 0x01, 0xF1, 0xFC, 0x22, 0x06, 0x54,
- 0xF5, 0xB8, 0x13, 0x4A, 0x41, 0x29, 0x00, 0x3C, 0xFC, 0xBD, 0x03,
- 0x66, 0xFD, 0x58, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF1,
- 0xFF, 0xEB, 0xFF, 0xE1, 0x00, 0x35, 0xFD, 0x40, 0x06, 0xE4, 0xF3,
- 0xB7, 0x1A, 0x85, 0x3E, 0xA6, 0xFB, 0x86, 0xFE, 0xA0, 0x02, 0xD7,
- 0xFD, 0x39, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xE1, 0xFF,
- 0x1C, 0x00, 0x82, 0x00, 0xB0, 0xFD, 0xF9, 0x05, 0x0C, 0xF3, 0xCB,
- 0x21, 0x8F, 0x3A, 0x0D, 0xF8, 0xA9, 0x00, 0x79, 0x01, 0x5D, 0xFE,
- 0x0B, 0x01, 0x98, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCE, 0xFF, 0x55,
- 0x00, 0x0D, 0x00, 0x60, 0xFE, 0x48, 0x05, 0xEC, 0xF2, 0xB6, 0x28,
- 0x91, 0x35, 0x68, 0xF5, 0x88, 0x02, 0x5A, 0x00, 0xED, 0xFE, 0xD4,
- 0x00, 0xA8, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0x92, 0x00,
- 0x87, 0xFF, 0x3F, 0xFF, 0x2B, 0x04, 0xA1, 0xF3, 0x3D, 0x2F, 0xB8,
- 0x2F, 0xB8, 0xF3, 0x11, 0x04, 0x52, 0xFF, 0x7C, 0xFF, 0x97, 0x00,
- 0xBA, 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA9, 0xFF, 0xCF, 0x00, 0xF8,
- 0xFE, 0x44, 0x00, 0xAA, 0x02, 0x3E, 0xF5, 0x24, 0x35, 0x3B, 0x29,
- 0xF2, 0xF2, 0x35, 0x05, 0x70, 0xFE, 0x03, 0x00, 0x5A, 0x00, 0xCD,
- 0xFF, 0x05, 0x00, 0x0E, 0x00, 0x99, 0xFF, 0x07, 0x01, 0x68, 0xFE,
- 0x63, 0x01, 0xD0, 0x00, 0xD0, 0xF7, 0x35, 0x3A, 0x55, 0x22, 0x02,
- 0xF3, 0xEF, 0x05, 0xBC, 0xFD, 0x7A, 0x00, 0x20, 0x00, 0xDF, 0xFF,
- 0x03, 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x36, 0x01, 0xE1, 0xFD, 0x8A,
- 0x02, 0xB2, 0xFE, 0x56, 0xFB, 0x40, 0x3E, 0x42, 0x1B, 0xCE, 0xF3,
- 0x3E, 0x06, 0x3D, 0xFD, 0xDB, 0x00, 0xEE, 0xFF, 0xF0, 0xFF, 0x01,
- 0x00, 0x11, 0x00, 0x8A, 0xFF, 0x57, 0x01, 0x6D, 0xFD, 0xA8, 0x03,
- 0x69, 0xFC, 0xC8, 0xFF, 0x20, 0x41, 0x40, 0x14, 0x33, 0xF5, 0x28,
- 0x06, 0xF5, 0xFC, 0x22, 0x01, 0xC5, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
- 0x0F, 0x00, 0x8F, 0xFF, 0x64, 0x01, 0x17, 0xFD, 0xA9, 0x04, 0x16,
- 0xFA, 0x10, 0x05, 0xB8, 0x42, 0x87, 0x0D, 0x0D, 0xF7, 0xB9, 0x05,
- 0xE2, 0xFC, 0x50, 0x01, 0xA7, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0A, 0x00, 0x9E, 0xFF, 0x5A, 0x01, 0xE8, 0xFC, 0x7A, 0x05,
- 0xDA, 0xF7, 0x10, 0x0B, 0xFB, 0x42, 0x4B, 0x07, 0x35, 0xF9, 0x00,
- 0x05, 0x00, 0xFD, 0x63, 0x01, 0x94, 0xFF, 0x0D, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0xB8, 0xFF, 0x37, 0x01, 0xE7, 0xFC, 0x07, 0x06, 0xDE,
- 0xF5, 0x9F, 0x11, 0xE4, 0x41, 0xB8, 0x01, 0x84, 0xFB, 0x0F, 0x04,
- 0x48, 0xFD, 0x5E, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF5,
- 0xFF, 0xDD, 0xFF, 0xF9, 0x00, 0x1B, 0xFD, 0x41, 0x06, 0x47, 0xF4,
- 0x8B, 0x18, 0x81, 0x3F, 0xF1, 0xFC, 0xD5, 0xFD, 0xFA, 0x02, 0xB2,
- 0xFD, 0x45, 0x01, 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE6, 0xFF,
- 0x0C, 0x00, 0xA2, 0x00, 0x85, 0xFD, 0x1A, 0x06, 0x3C, 0xF3, 0x9F,
- 0x1F, 0xE6, 0x3B, 0x0E, 0xF9, 0x07, 0x00, 0xD4, 0x01, 0x33, 0xFE,
- 0x1B, 0x01, 0x94, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x43,
- 0x00, 0x33, 0x00, 0x25, 0xFE, 0x89, 0x05, 0xE0, 0xF2, 0x9C, 0x26,
- 0x33, 0x37, 0x1E, 0xF6, 0xFD, 0x01, 0xB0, 0x00, 0xC0, 0xFE, 0xE6,
- 0x00, 0xA2, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC1, 0xFF, 0x7F, 0x00,
- 0xB2, 0xFF, 0xF6, 0xFE, 0x8E, 0x04, 0x51, 0xF3, 0x49, 0x2D, 0x98,
- 0x31, 0x23, 0xF4, 0xA2, 0x03, 0xA0, 0xFF, 0x51, 0xFF, 0xAA, 0x00,
- 0xB4, 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAE, 0xFF, 0xBD, 0x00, 0x25,
- 0xFF, 0xF1, 0xFF, 0x2B, 0x03, 0xA5, 0xF4, 0x68, 0x33, 0x48, 0x2B,
- 0x17, 0xF3, 0xE7, 0x04, 0xB1, 0xFE, 0xDB, 0xFF, 0x6C, 0x00, 0xC7,
- 0xFF, 0x06, 0x00, 0x0D, 0x00, 0x9E, 0xFF, 0xF7, 0x00, 0x94, 0xFE,
- 0x09, 0x01, 0x6A, 0x01, 0xEB, 0xF6, 0xC1, 0x38, 0x7D, 0x24, 0xE8,
- 0xF2, 0xC1, 0x05, 0xEE, 0xFD, 0x57, 0x00, 0x31, 0x00, 0xDA, 0xFF,
- 0x03, 0x00, 0x10, 0x00, 0x91, 0xFF, 0x29, 0x01, 0x09, 0xFE, 0x2F,
- 0x02, 0x5F, 0xFF, 0x27, 0xFA, 0x20, 0x3D, 0x70, 0x1D, 0x7D, 0xF3,
- 0x31, 0x06, 0x5E, 0xFD, 0xBF, 0x00, 0xFD, 0xFF, 0xEB, 0xFF, 0x02,
- 0x00, 0x11, 0x00, 0x8B, 0xFF, 0x4E, 0x01, 0x8E, 0xFD, 0x52, 0x03,
- 0x20, 0xFD, 0x52, 0xFE, 0x60, 0x40, 0x63, 0x16, 0xB7, 0xF4, 0x39,
- 0x06, 0x05, 0xFD, 0x0F, 0x01, 0xD1, 0xFF, 0xF9, 0xFF, 0x00, 0x00,
- 0x10, 0x00, 0x8D, 0xFF, 0x62, 0x01, 0x2E, 0xFD, 0x5E, 0x04, 0xCC,
- 0xFA, 0x5B, 0x03, 0x5E, 0x42, 0x8E, 0x0F, 0x71, 0xF6, 0xE4, 0x05,
- 0xE2, 0xFC, 0x45, 0x01, 0xAF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0B, 0x00, 0x99, 0xFF, 0x60, 0x01, 0xF2, 0xFC, 0x40, 0x05,
- 0x85, 0xF8, 0x26, 0x09, 0x0C, 0x43, 0x26, 0x09, 0x85, 0xF8, 0x40,
- 0x05, 0xF2, 0xFC, 0x60, 0x01, 0x99, 0xFF, 0x0B, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0xAF, 0xFF, 0x45, 0x01, 0xE2, 0xFC, 0xE4, 0x05, 0x71,
- 0xF6, 0x8E, 0x0F, 0x5E, 0x42, 0x5B, 0x03, 0xCC, 0xFA, 0x5E, 0x04,
- 0x2E, 0xFD, 0x62, 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xF9,
- 0xFF, 0xD1, 0xFF, 0x0F, 0x01, 0x05, 0xFD, 0x39, 0x06, 0xB7, 0xF4,
- 0x63, 0x16, 0x60, 0x40, 0x52, 0xFE, 0x20, 0xFD, 0x52, 0x03, 0x8E,
- 0xFD, 0x4E, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEB, 0xFF,
- 0xFD, 0xFF, 0xBF, 0x00, 0x5E, 0xFD, 0x31, 0x06, 0x7D, 0xF3, 0x70,
- 0x1D, 0x20, 0x3D, 0x27, 0xFA, 0x5F, 0xFF, 0x2F, 0x02, 0x09, 0xFE,
- 0x29, 0x01, 0x91, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDA, 0xFF, 0x31,
- 0x00, 0x57, 0x00, 0xEE, 0xFD, 0xC1, 0x05, 0xE8, 0xF2, 0x7D, 0x24,
- 0xC1, 0x38, 0xEB, 0xF6, 0x6A, 0x01, 0x09, 0x01, 0x94, 0xFE, 0xF7,
- 0x00, 0x9E, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC7, 0xFF, 0x6C, 0x00,
- 0xDB, 0xFF, 0xB1, 0xFE, 0xE7, 0x04, 0x17, 0xF3, 0x48, 0x2B, 0x68,
- 0x33, 0xA5, 0xF4, 0x2B, 0x03, 0xF1, 0xFF, 0x25, 0xFF, 0xBD, 0x00,
- 0xAE, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB4, 0xFF, 0xAA, 0x00, 0x51,
- 0xFF, 0xA0, 0xFF, 0xA2, 0x03, 0x23, 0xF4, 0x98, 0x31, 0x49, 0x2D,
- 0x51, 0xF3, 0x8E, 0x04, 0xF6, 0xFE, 0xB2, 0xFF, 0x7F, 0x00, 0xC1,
- 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA2, 0xFF, 0xE6, 0x00, 0xC0, 0xFE,
- 0xB0, 0x00, 0xFD, 0x01, 0x1E, 0xF6, 0x33, 0x37, 0x9C, 0x26, 0xE0,
- 0xF2, 0x89, 0x05, 0x25, 0xFE, 0x33, 0x00, 0x43, 0x00, 0xD4, 0xFF,
- 0x04, 0x00, 0x0F, 0x00, 0x94, 0xFF, 0x1B, 0x01, 0x33, 0xFE, 0xD4,
- 0x01, 0x07, 0x00, 0x0E, 0xF9, 0xE6, 0x3B, 0x9F, 0x1F, 0x3C, 0xF3,
- 0x1A, 0x06, 0x85, 0xFD, 0xA2, 0x00, 0x0C, 0x00, 0xE6, 0xFF, 0x02,
- 0x00, 0x11, 0x00, 0x8C, 0xFF, 0x45, 0x01, 0xB2, 0xFD, 0xFA, 0x02,
- 0xD5, 0xFD, 0xF1, 0xFC, 0x81, 0x3F, 0x8B, 0x18, 0x47, 0xF4, 0x41,
- 0x06, 0x1B, 0xFD, 0xF9, 0x00, 0xDD, 0xFF, 0xF5, 0xFF, 0x01, 0x00,
- 0x10, 0x00, 0x8B, 0xFF, 0x5E, 0x01, 0x48, 0xFD, 0x0F, 0x04, 0x84,
- 0xFB, 0xB8, 0x01, 0xE4, 0x41, 0x9F, 0x11, 0xDE, 0xF5, 0x07, 0x06,
- 0xE7, 0xFC, 0x37, 0x01, 0xB8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x0D,
- 0x00, 0x94, 0xFF, 0x63, 0x01, 0x00, 0xFD, 0x00, 0x05, 0x35, 0xF9,
- 0x4B, 0x07, 0xFB, 0x42, 0x10, 0x0B, 0xDA, 0xF7, 0x7A, 0x05, 0xE8,
- 0xFC, 0x5A, 0x01, 0x9E, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0xA7, 0xFF, 0x50, 0x01, 0xE2, 0xFC, 0xB9, 0x05, 0x0D,
- 0xF7, 0x87, 0x0D, 0xB8, 0x42, 0x10, 0x05, 0x16, 0xFA, 0xA9, 0x04,
- 0x17, 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFD,
- 0xFF, 0xC5, 0xFF, 0x22, 0x01, 0xF5, 0xFC, 0x28, 0x06, 0x33, 0xF5,
- 0x40, 0x14, 0x20, 0x41, 0xC8, 0xFF, 0x69, 0xFC, 0xA8, 0x03, 0x6D,
- 0xFD, 0x57, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF0, 0xFF,
- 0xEE, 0xFF, 0xDB, 0x00, 0x3D, 0xFD, 0x3E, 0x06, 0xCE, 0xF3, 0x42,
- 0x1B, 0x40, 0x3E, 0x56, 0xFB, 0xB2, 0xFE, 0x8A, 0x02, 0xE1, 0xFD,
- 0x36, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDF, 0xFF, 0x20,
- 0x00, 0x7A, 0x00, 0xBC, 0xFD, 0xEF, 0x05, 0x02, 0xF3, 0x55, 0x22,
- 0x35, 0x3A, 0xD0, 0xF7, 0xD0, 0x00, 0x63, 0x01, 0x68, 0xFE, 0x07,
- 0x01, 0x99, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCD, 0xFF, 0x5A, 0x00,
- 0x03, 0x00, 0x70, 0xFE, 0x35, 0x05, 0xF2, 0xF2, 0x3B, 0x29, 0x24,
- 0x35, 0x3E, 0xF5, 0xAA, 0x02, 0x44, 0x00, 0xF8, 0xFE, 0xCF, 0x00,
- 0xA9, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBA, 0xFF, 0x97, 0x00, 0x7C,
- 0xFF, 0x52, 0xFF, 0x11, 0x04, 0xB8, 0xF3, 0xB8, 0x2F, 0x3D, 0x2F,
- 0xA1, 0xF3, 0x2B, 0x04, 0x3F, 0xFF, 0x87, 0xFF, 0x92, 0x00, 0xBB,
- 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA8, 0xFF, 0xD4, 0x00, 0xED, 0xFE,
- 0x5A, 0x00, 0x88, 0x02, 0x68, 0xF5, 0x91, 0x35, 0xB6, 0x28, 0xEC,
- 0xF2, 0x48, 0x05, 0x60, 0xFE, 0x0D, 0x00, 0x55, 0x00, 0xCE, 0xFF,
- 0x05, 0x00, 0x0E, 0x00, 0x98, 0xFF, 0x0B, 0x01, 0x5D, 0xFE, 0x79,
- 0x01, 0xA9, 0x00, 0x0D, 0xF8, 0x8F, 0x3A, 0xCB, 0x21, 0x0C, 0xF3,
- 0xF9, 0x05, 0xB0, 0xFD, 0x82, 0x00, 0x1C, 0x00, 0xE1, 0xFF, 0x03,
- 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x39, 0x01, 0xD7, 0xFD, 0xA0, 0x02,
- 0x86, 0xFE, 0xA6, 0xFB, 0x85, 0x3E, 0xB7, 0x1A, 0xE4, 0xF3, 0x40,
- 0x06, 0x35, 0xFD, 0xE1, 0x00, 0xEB, 0xFF, 0xF1, 0xFF, 0x01, 0x00,
- 0x11, 0x00, 0x8A, 0xFF, 0x58, 0x01, 0x66, 0xFD, 0xBD, 0x03, 0x3C,
- 0xFC, 0x29, 0x00, 0x4A, 0x41, 0xB8, 0x13, 0x54, 0xF5, 0x22, 0x06,
- 0xF1, 0xFC, 0x27, 0x01, 0xC2, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x0E,
- 0x00, 0x90, 0xFF, 0x64, 0x01, 0x12, 0xFD, 0xBB, 0x04, 0xE8, 0xF9,
- 0x81, 0x05, 0xCB, 0x42, 0x08, 0x0D, 0x35, 0xF7, 0xAD, 0x05, 0xE2,
- 0xFC, 0x52, 0x01, 0xA5, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0xA0, 0xFF, 0x58, 0x01, 0xE6, 0xFC, 0x87, 0x05, 0xB0,
- 0xF7, 0x8D, 0x0B, 0xF2, 0x42, 0xD7, 0x06, 0x62, 0xF9, 0xEF, 0x04,
- 0x04, 0xFD, 0x63, 0x01, 0x93, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xBB, 0xFF, 0x33, 0x01, 0xE9, 0xFC, 0x0F, 0x06, 0xBA, 0xF5,
- 0x24, 0x12, 0xC2, 0x41, 0x53, 0x01, 0xB2, 0xFB, 0xFB, 0x03, 0x4F,
- 0xFD, 0x5D, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF4, 0xFF,
- 0xE0, 0xFF, 0xF3, 0x00, 0x21, 0xFD, 0x41, 0x06, 0x2D, 0xF4, 0x16,
- 0x19, 0x45, 0x3F, 0x9C, 0xFC, 0x01, 0xFE, 0xE4, 0x02, 0xBB, 0xFD,
- 0x42, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE5, 0xFF, 0x10,
- 0x00, 0x9A, 0x00, 0x8F, 0xFD, 0x12, 0x06, 0x2E, 0xF3, 0x2A, 0x20,
- 0x92, 0x3B, 0xCC, 0xF8, 0x30, 0x00, 0xBD, 0x01, 0x3D, 0xFE, 0x17,
- 0x01, 0x95, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x47, 0x00,
- 0x2A, 0x00, 0x33, 0xFE, 0x7A, 0x05, 0xE1, 0xF2, 0x24, 0x27, 0xCD,
- 0x36, 0xEE, 0xF5, 0x21, 0x02, 0x9B, 0x00, 0xCB, 0xFE, 0xE1, 0x00,
- 0xA4, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0x84, 0x00, 0xA7,
- 0xFF, 0x08, 0xFF, 0x76, 0x04, 0x63, 0xF3, 0xC8, 0x2D, 0x22, 0x31,
- 0x06, 0xF4, 0xBF, 0x03, 0x8C, 0xFF, 0x5C, 0xFF, 0xA5, 0x00, 0xB5,
- 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAD, 0xFF, 0xC1, 0x00, 0x1A, 0xFF,
- 0x05, 0x00, 0x0B, 0x03, 0xC9, 0xF4, 0xD8, 0x33, 0xC5, 0x2A, 0x0C,
- 0xF3, 0xFB, 0x04, 0xA0, 0xFE, 0xE5, 0xFF, 0x68, 0x00, 0xC9, 0xFF,
- 0x06, 0x00, 0x0D, 0x00, 0x9C, 0xFF, 0xFB, 0x00, 0x89, 0xFE, 0x1F,
- 0x01, 0x44, 0x01, 0x22, 0xF7, 0x20, 0x39, 0xF3, 0x23, 0xED, 0xF2,
- 0xCE, 0x05, 0xE1, 0xFD, 0x60, 0x00, 0x2D, 0x00, 0xDB, 0xFF, 0x03,
- 0x00, 0x10, 0x00, 0x90, 0xFF, 0x2D, 0x01, 0xFF, 0xFD, 0x46, 0x02,
- 0x34, 0xFF, 0x71, 0xFA, 0x6B, 0x3D, 0xE5, 0x1C, 0x90, 0xF3, 0x35,
- 0x06, 0x55, 0xFD, 0xC6, 0x00, 0xF9, 0xFF, 0xEC, 0xFF, 0x01, 0x00,
- 0x11, 0x00, 0x8B, 0xFF, 0x51, 0x01, 0x86, 0xFD, 0x68, 0x03, 0xF3,
- 0xFC, 0xAE, 0xFE, 0x92, 0x40, 0xDA, 0x15, 0xD5, 0xF4, 0x35, 0x06,
- 0x00, 0xFD, 0x14, 0x01, 0xCE, 0xFF, 0xFA, 0xFF, 0x00, 0x00, 0x0F,
- 0x00, 0x8D, 0xFF, 0x63, 0x01, 0x28, 0xFD, 0x71, 0x04, 0x9E, 0xFA,
- 0xC7, 0x03, 0x79, 0x42, 0x0B, 0x0F, 0x97, 0xF6, 0xDA, 0x05, 0xE2,
- 0xFC, 0x48, 0x01, 0xAD, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x9A, 0xFF, 0x5F, 0x01, 0xEF, 0xFC, 0x4F, 0x05, 0x5A,
- 0xF8, 0x9F, 0x09, 0x0A, 0x43, 0xAE, 0x08, 0xB1, 0xF8, 0x30, 0x05,
- 0xF5, 0xFC, 0x61, 0x01, 0x97, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0xB1, 0xFF, 0x41, 0x01, 0xE3, 0xFC, 0xED, 0x05, 0x4C, 0xF6,
- 0x11, 0x10, 0x42, 0x42, 0xF1, 0x02, 0xFA, 0xFA, 0x4B, 0x04, 0x34,
- 0xFD, 0x61, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF8, 0xFF,
- 0xD4, 0xFF, 0x0A, 0x01, 0x0A, 0xFD, 0x3C, 0x06, 0x9A, 0xF4, 0xED,
- 0x16, 0x2A, 0x40, 0xF8, 0xFD, 0x4D, 0xFD, 0x3C, 0x03, 0x97, 0xFD,
- 0x4C, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEA, 0xFF, 0x00,
- 0x00, 0xB8, 0x00, 0x67, 0xFD, 0x2C, 0x06, 0x6B, 0xF3, 0xFC, 0x1D,
- 0xD3, 0x3C, 0xDF, 0xF9, 0x89, 0xFF, 0x18, 0x02, 0x13, 0xFE, 0x26,
- 0x01, 0x92, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD9, 0xFF, 0x36, 0x00,
- 0x4E, 0x00, 0xFB, 0xFD, 0xB4, 0x05, 0xE4, 0xF2, 0x04, 0x25, 0x5F,
- 0x38, 0xB6, 0xF6, 0x90, 0x01, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00,
- 0x9F, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC6, 0xFF, 0x71, 0x00, 0xD1,
- 0xFF, 0xC2, 0xFE, 0xD1, 0x04, 0x23, 0xF3, 0xC9, 0x2B, 0xF5, 0x32,
- 0x83, 0xF4, 0x49, 0x03, 0xDC, 0xFF, 0x30, 0xFF, 0xB8, 0x00, 0xB0,
- 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB3, 0xFF, 0xAE, 0x00, 0x46, 0xFF,
- 0xB4, 0xFF, 0x85, 0x03, 0x42, 0xF4, 0x0E, 0x32, 0xCA, 0x2C, 0x41,
- 0xF3, 0xA5, 0x04, 0xE4, 0xFE, 0xBC, 0xFF, 0x7A, 0x00, 0xC3, 0xFF,
- 0x07, 0x00, 0x0D, 0x00, 0xA1, 0xFF, 0xEA, 0x00, 0xB5, 0xFE, 0xC6,
- 0x00, 0xD9, 0x01, 0x4F, 0xF6, 0x99, 0x37, 0x16, 0x26, 0xE0, 0xF2,
- 0x98, 0x05, 0x16, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0xD6, 0xFF, 0x04,
- 0x00, 0x0F, 0x00, 0x93, 0xFF, 0x1F, 0x01, 0x28, 0xFE, 0xEB, 0x01,
- 0xDD, 0xFF, 0x52, 0xF9, 0x36, 0x3C, 0x13, 0x1F, 0x4B, 0xF3, 0x20,
- 0x06, 0x7B, 0xFD, 0xA9, 0x00, 0x08, 0x00, 0xE7, 0xFF, 0x02, 0x00,
- 0x11, 0x00, 0x8C, 0xFF, 0x47, 0x01, 0xA9, 0xFD, 0x10, 0x03, 0xA8,
- 0xFD, 0x47, 0xFD, 0xBB, 0x3F, 0x01, 0x18, 0x62, 0xF4, 0x40, 0x06,
- 0x15, 0xFD, 0xFF, 0x00, 0xDA, 0xFF, 0xF6, 0xFF, 0x01, 0x00, 0x10,
- 0x00, 0x8B, 0xFF, 0x5F, 0x01, 0x41, 0xFD, 0x23, 0x04, 0x56, 0xFB,
- 0x1F, 0x02, 0x06, 0x42, 0x19, 0x11, 0x02, 0xF6, 0xFF, 0x05, 0xE5,
- 0xFC, 0x3B, 0x01, 0xB6, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00,
- 0x95, 0xFF, 0x62, 0x01, 0xFC, 0xFC, 0x10, 0x05, 0x09, 0xF9, 0xC1,
- 0x07, 0x03, 0x43, 0x94, 0x0A, 0x05, 0xF8, 0x6C, 0x05, 0xEA, 0xFC,
- 0x5C, 0x01, 0x9D, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0x00, 0xA9, 0xFF, 0x4D, 0x01, 0xE1, 0xFC, 0xC4, 0x05, 0xE6, 0xF6,
- 0x08, 0x0E, 0xA5, 0x42, 0xA1, 0x04, 0x43, 0xFA, 0x97, 0x04, 0x1D,
- 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFC, 0xFF,
- 0xC8, 0xFF, 0x1E, 0x01, 0xF8, 0xFC, 0x2D, 0x06, 0x13, 0xF5, 0xC8,
- 0x14, 0xF2, 0x40, 0x69, 0xFF, 0x97, 0xFC, 0x92, 0x03, 0x75, 0xFD,
- 0x55, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEF, 0xFF, 0xF2,
- 0xFF, 0xD4, 0x00, 0x45, 0xFD, 0x3B, 0x06, 0xB8, 0xF3, 0xCE, 0x1B,
- 0xFB, 0x3D, 0x08, 0xFB, 0xDE, 0xFE, 0x73, 0x02, 0xEB, 0xFD, 0x33,
- 0x01, 0x8F, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDE, 0xFF, 0x25, 0x00,
- 0x71, 0x00, 0xC8, 0xFD, 0xE5, 0x05, 0xFA, 0xF2, 0xDF, 0x22, 0xDB,
- 0x39, 0x94, 0xF7, 0xF7, 0x00, 0x4C, 0x01, 0x73, 0xFE, 0x03, 0x01,
- 0x9A, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCC, 0xFF, 0x5E, 0x00, 0xF9,
- 0xFF, 0x80, 0xFE, 0x23, 0x05, 0xF9, 0xF2, 0xC0, 0x29, 0xB8, 0x34,
- 0x16, 0xF5, 0xCB, 0x02, 0x2F, 0x00, 0x03, 0xFF, 0xCA, 0x00, 0xAA,
- 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xB8, 0xFF, 0x9B, 0x00, 0x72, 0xFF,
- 0x65, 0xFF, 0xF6, 0x03, 0xD1, 0xF3, 0x31, 0x30, 0xC1, 0x2E, 0x8B,
- 0xF3, 0x45, 0x04, 0x2D, 0xFF, 0x92, 0xFF, 0x8D, 0x00, 0xBD, 0xFF,
- 0x08, 0x00, 0x0C, 0x00, 0xA6, 0xFF, 0xD8, 0x00, 0xE2, 0xFE, 0x6F,
- 0x00, 0x66, 0x02, 0x93, 0xF5, 0xFB, 0x35, 0x31, 0x28, 0xE7, 0xF2,
- 0x59, 0x05, 0x51, 0xFE, 0x17, 0x00, 0x50, 0x00, 0xD0, 0xFF, 0x05,
- 0x00, 0x0E, 0x00, 0x97, 0xFF, 0x0F, 0x01, 0x53, 0xFE, 0x90, 0x01,
- 0x81, 0x00, 0x4B, 0xF8, 0xE6, 0x3A, 0x3F, 0x21, 0x16, 0xF3, 0x02,
- 0x06, 0xA5, 0xFD, 0x8A, 0x00, 0x18, 0x00, 0xE2, 0xFF, 0x02, 0x00,
- 0x10, 0x00, 0x8D, 0xFF, 0x3C, 0x01, 0xCE, 0xFD, 0xB7, 0x02, 0x5A,
- 0xFE, 0xF7, 0xFB, 0xC6, 0x3E, 0x2C, 0x1A, 0xFC, 0xF3, 0x41, 0x06,
- 0x2E, 0xFD, 0xE7, 0x00, 0xE7, 0xFF, 0xF2, 0xFF, 0x01, 0x00, 0x10,
- 0x00, 0x8B, 0xFF, 0x5A, 0x01, 0x5E, 0xFD, 0xD2, 0x03, 0x0E, 0xFC,
- 0x8B, 0x00, 0x75, 0x41, 0x32, 0x13, 0x75, 0xF5, 0x1C, 0x06, 0xEE,
- 0xFC, 0x2B, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00,
- 0x91, 0xFF, 0x64, 0x01, 0x0D, 0xFD, 0xCD, 0x04, 0xBB, 0xF9, 0xF2,
- 0x05, 0xD9, 0x42, 0x88, 0x0C, 0x5E, 0xF7, 0xA1, 0x05, 0xE3, 0xFC,
- 0x54, 0x01, 0xA3, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
- 0x00, 0xA2, 0xFF, 0x56, 0x01, 0xE5, 0xFC, 0x94, 0x05, 0x87, 0xF7,
- 0x0A, 0x0C, 0xE6, 0x42, 0x64, 0x06, 0x8E, 0xF9, 0xDE, 0x04, 0x09,
- 0xFD, 0x64, 0x01, 0x92, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xBD, 0xFF, 0x2F, 0x01, 0xEC, 0xFC, 0x16, 0x06, 0x98, 0xF5, 0xAB,
- 0x12, 0x9C, 0x41, 0xEE, 0x00, 0xE0, 0xFB, 0xE6, 0x03, 0x57, 0xFD,
- 0x5B, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF3, 0xFF, 0xE4,
- 0xFF, 0xED, 0x00, 0x27, 0xFD, 0x41, 0x06, 0x14, 0xF4, 0xA1, 0x19,
- 0x06, 0x3F, 0x49, 0xFC, 0x2E, 0xFE, 0xCD, 0x02, 0xC4, 0xFD, 0x3F,
- 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE3, 0xFF, 0x14, 0x00,
- 0x92, 0x00, 0x9A, 0xFD, 0x0A, 0x06, 0x22, 0xF3, 0xB4, 0x20, 0x3C,
- 0x3B, 0x8B, 0xF8, 0x58, 0x00, 0xA7, 0x01, 0x48, 0xFE, 0x13, 0x01,
- 0x96, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x4C, 0x00, 0x20,
- 0x00, 0x42, 0xFE, 0x6A, 0x05, 0xE3, 0xF2, 0xAB, 0x27, 0x66, 0x36,
- 0xC0, 0xF5, 0x44, 0x02, 0x85, 0x00, 0xD7, 0xFE, 0xDD, 0x00, 0xA5,
- 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xBE, 0xFF, 0x89, 0x00, 0x9D, 0xFF,
- 0x1A, 0xFF, 0x5E, 0x04, 0x76, 0xF3, 0x45, 0x2E, 0xAA, 0x30, 0xEB,
- 0xF3, 0xDB, 0x03, 0x79, 0xFF, 0x67, 0xFF, 0xA0, 0x00, 0xB7, 0xFF,
- 0x09, 0x00, 0x0B, 0x00, 0xAC, 0xFF, 0xC6, 0x00, 0x0E, 0xFF, 0x1A,
- 0x00, 0xEB, 0x02, 0xEF, 0xF4, 0x49, 0x34, 0x43, 0x2A, 0x02, 0xF3,
- 0x0F, 0x05, 0x90, 0xFE, 0xEF, 0xFF, 0x63, 0x00, 0xCA, 0xFF, 0x06,
- 0x00, 0x0E, 0x00, 0x9B, 0xFF, 0xFF, 0x00, 0x7E, 0xFE, 0x36, 0x01,
- 0x1E, 0x01, 0x5B, 0xF7, 0x7E, 0x39, 0x69, 0x23, 0xF3, 0xF2, 0xD9,
- 0x05, 0xD4, 0xFD, 0x69, 0x00, 0x29, 0x00, 0xDD, 0xFF, 0x03, 0x00,
- 0x10, 0x00, 0x90, 0xFF, 0x30, 0x01, 0xF5, 0xFD, 0x5C, 0x02, 0x09,
- 0xFF, 0xBC, 0xFA, 0xB5, 0x3D, 0x5A, 0x1C, 0xA3, 0xF3, 0x38, 0x06,
- 0x4D, 0xFD, 0xCD, 0x00, 0xF5, 0xFF, 0xED, 0xFF, 0x01, 0x00, 0x11,
- 0x00, 0x8B, 0xFF, 0x53, 0x01, 0x7E, 0xFD, 0x7D, 0x03, 0xC5, 0xFC,
- 0x0B, 0xFF, 0xC3, 0x40, 0x51, 0x15, 0xF4, 0xF4, 0x31, 0x06, 0xFC,
- 0xFC, 0x19, 0x01, 0xCB, 0xFF, 0xFB, 0xFF, 0x00, 0x00, 0x0F, 0x00,
- 0x8E, 0xFF, 0x63, 0x01, 0x22, 0xFD, 0x84, 0x04, 0x71, 0xFA, 0x34,
- 0x04, 0x90, 0x42, 0x89, 0x0E, 0xBE, 0xF6, 0xCF, 0x05, 0xE1, 0xFC,
- 0x4A, 0x01, 0xAB, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
- 0x00, 0x9B, 0xFF, 0x5D, 0x01, 0xEC, 0xFC, 0x5D, 0x05, 0x2F, 0xF8,
- 0x19, 0x0A, 0x07, 0x43, 0x37, 0x08, 0xDD, 0xF8, 0x21, 0x05, 0xF8,
- 0xFC, 0x62, 0x01, 0x96, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00,
- 0xB4, 0xFF, 0x3E, 0x01, 0xE4, 0xFC, 0xF6, 0x05, 0x26, 0xF6, 0x95,
- 0x10, 0x26, 0x42, 0x87, 0x02, 0x28, 0xFB, 0x37, 0x04, 0x3B, 0xFD,
- 0x60, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF7, 0xFF, 0xD7,
- 0xFF, 0x04, 0x01, 0x0F, 0xFD, 0x3E, 0x06, 0x7D, 0xF4, 0x76, 0x17,
- 0xF4, 0x3F, 0x9F, 0xFD, 0x7B, 0xFD, 0x26, 0x03, 0xA0, 0xFD, 0x4A,
- 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE9, 0xFF, 0x04, 0x00,
- 0xB1, 0x00, 0x71, 0xFD, 0x26, 0x06, 0x5A, 0xF3, 0x88, 0x1E, 0x87,
- 0x3C, 0x98, 0xF9, 0xB3, 0xFF, 0x02, 0x02, 0x1E, 0xFE, 0x22, 0x01,
- 0x93, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD7, 0xFF, 0x3A, 0x00, 0x45,
- 0x00, 0x09, 0xFE, 0xA7, 0x05, 0xE1, 0xF2, 0x8D, 0x25, 0xFD, 0x37,
- 0x82, 0xF6, 0xB5, 0x01, 0xDC, 0x00, 0xAA, 0xFE, 0xEE, 0x00, 0xA0,
- 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC4, 0xFF, 0x76, 0x00, 0xC7, 0xFF,
- 0xD3, 0xFE, 0xBC, 0x04, 0x31, 0xF3, 0x4A, 0x2C, 0x83, 0x32, 0x61,
- 0xF4, 0x68, 0x03, 0xC8, 0xFF, 0x3B, 0xFF, 0xB3, 0x00, 0xB1, 0xFF,
- 0x0A, 0x00, 0x0A, 0x00, 0xB1, 0xFF, 0xB3, 0x00, 0x3B, 0xFF, 0xC8,
- 0xFF, 0x68, 0x03, 0x61, 0xF4, 0x83, 0x32, 0x4A, 0x2C, 0x31, 0xF3,
- 0xBC, 0x04, 0xD3, 0xFE, 0xC7, 0xFF, 0x76, 0x00, 0xC4, 0xFF, 0x06,
- 0x00, 0x0D, 0x00, 0xA0, 0xFF, 0xEE, 0x00, 0xAA, 0xFE, 0xDC, 0x00,
- 0xB5, 0x01, 0x82, 0xF6, 0xFD, 0x37, 0x8D, 0x25, 0xE1, 0xF2, 0xA7,
- 0x05, 0x09, 0xFE, 0x45, 0x00, 0x3A, 0x00, 0xD7, 0xFF, 0x04, 0x00,
- 0x0F, 0x00, 0x93, 0xFF, 0x22, 0x01, 0x1E, 0xFE, 0x02, 0x02, 0xB3,
- 0xFF, 0x98, 0xF9, 0x87, 0x3C, 0x88, 0x1E, 0x5A, 0xF3, 0x26, 0x06,
- 0x71, 0xFD, 0xB1, 0x00, 0x04, 0x00, 0xE9, 0xFF, 0x02, 0x00, 0x11,
- 0x00, 0x8B, 0xFF, 0x4A, 0x01, 0xA0, 0xFD, 0x26, 0x03, 0x7B, 0xFD,
- 0x9F, 0xFD, 0xF4, 0x3F, 0x76, 0x17, 0x7D, 0xF4, 0x3E, 0x06, 0x0F,
- 0xFD, 0x04, 0x01, 0xD7, 0xFF, 0xF7, 0xFF, 0x01, 0x00, 0x10, 0x00,
- 0x8C, 0xFF, 0x60, 0x01, 0x3B, 0xFD, 0x37, 0x04, 0x28, 0xFB, 0x87,
- 0x02, 0x26, 0x42, 0x95, 0x10, 0x26, 0xF6, 0xF6, 0x05, 0xE4, 0xFC,
- 0x3E, 0x01, 0xB4, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x96,
- 0xFF, 0x62, 0x01, 0xF8, 0xFC, 0x21, 0x05, 0xDD, 0xF8, 0x37, 0x08,
- 0x07, 0x43, 0x19, 0x0A, 0x2F, 0xF8, 0x5D, 0x05, 0xEC, 0xFC, 0x5D,
- 0x01, 0x9B, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
- 0xAB, 0xFF, 0x4A, 0x01, 0xE1, 0xFC, 0xCF, 0x05, 0xBE, 0xF6, 0x89,
- 0x0E, 0x90, 0x42, 0x34, 0x04, 0x71, 0xFA, 0x84, 0x04, 0x22, 0xFD,
- 0x63, 0x01, 0x8E, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xCB,
- 0xFF, 0x19, 0x01, 0xFC, 0xFC, 0x31, 0x06, 0xF4, 0xF4, 0x51, 0x15,
- 0xC3, 0x40, 0x0B, 0xFF, 0xC5, 0xFC, 0x7D, 0x03, 0x7E, 0xFD, 0x53,
- 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xED, 0xFF, 0xF5, 0xFF,
- 0xCD, 0x00, 0x4D, 0xFD, 0x38, 0x06, 0xA3, 0xF3, 0x5A, 0x1C, 0xB5,
- 0x3D, 0xBC, 0xFA, 0x09, 0xFF, 0x5C, 0x02, 0xF5, 0xFD, 0x30, 0x01,
- 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDD, 0xFF, 0x29, 0x00, 0x69,
- 0x00, 0xD4, 0xFD, 0xD9, 0x05, 0xF3, 0xF2, 0x69, 0x23, 0x7E, 0x39,
- 0x5B, 0xF7, 0x1E, 0x01, 0x36, 0x01, 0x7E, 0xFE, 0xFF, 0x00, 0x9B,
- 0xFF, 0x0E, 0x00, 0x06, 0x00, 0xCA, 0xFF, 0x63, 0x00, 0xEF, 0xFF,
- 0x90, 0xFE, 0x0F, 0x05, 0x02, 0xF3, 0x43, 0x2A, 0x49, 0x34, 0xEF,
- 0xF4, 0xEB, 0x02, 0x1A, 0x00, 0x0E, 0xFF, 0xC6, 0x00, 0xAC, 0xFF,
- 0x0B, 0x00, 0x09, 0x00, 0xB7, 0xFF, 0xA0, 0x00, 0x67, 0xFF, 0x79,
- 0xFF, 0xDB, 0x03, 0xEB, 0xF3, 0xAA, 0x30, 0x45, 0x2E, 0x76, 0xF3,
- 0x5E, 0x04, 0x1A, 0xFF, 0x9D, 0xFF, 0x89, 0x00, 0xBE, 0xFF, 0x07,
- 0x00, 0x0C, 0x00, 0xA5, 0xFF, 0xDD, 0x00, 0xD7, 0xFE, 0x85, 0x00,
- 0x44, 0x02, 0xC0, 0xF5, 0x66, 0x36, 0xAB, 0x27, 0xE3, 0xF2, 0x6A,
- 0x05, 0x42, 0xFE, 0x20, 0x00, 0x4C, 0x00, 0xD1, 0xFF, 0x04, 0x00,
- 0x0F, 0x00, 0x96, 0xFF, 0x13, 0x01, 0x48, 0xFE, 0xA7, 0x01, 0x58,
- 0x00, 0x8B, 0xF8, 0x3C, 0x3B, 0xB4, 0x20, 0x22, 0xF3, 0x0A, 0x06,
- 0x9A, 0xFD, 0x92, 0x00, 0x14, 0x00, 0xE3, 0xFF, 0x02, 0x00, 0x10,
- 0x00, 0x8D, 0xFF, 0x3F, 0x01, 0xC4, 0xFD, 0xCD, 0x02, 0x2E, 0xFE,
- 0x49, 0xFC, 0x06, 0x3F, 0xA1, 0x19, 0x14, 0xF4, 0x41, 0x06, 0x27,
- 0xFD, 0xED, 0x00, 0xE4, 0xFF, 0xF3, 0xFF, 0x01, 0x00, 0x10, 0x00,
- 0x8B, 0xFF, 0x5B, 0x01, 0x57, 0xFD, 0xE6, 0x03, 0xE0, 0xFB, 0xEE,
- 0x00, 0x9C, 0x41, 0xAB, 0x12, 0x98, 0xF5, 0x16, 0x06, 0xEC, 0xFC,
- 0x2F, 0x01, 0xBD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x92,
- 0xFF, 0x64, 0x01, 0x09, 0xFD, 0xDE, 0x04, 0x8E, 0xF9, 0x64, 0x06,
- 0xE6, 0x42, 0x0A, 0x0C, 0x87, 0xF7, 0x94, 0x05, 0xE5, 0xFC, 0x56,
- 0x01, 0xA2, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
- 0xA3, 0xFF, 0x54, 0x01, 0xE3, 0xFC, 0xA1, 0x05, 0x5E, 0xF7, 0x88,
- 0x0C, 0xD9, 0x42, 0xF2, 0x05, 0xBB, 0xF9, 0xCD, 0x04, 0x0D, 0xFD,
- 0x64, 0x01, 0x91, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0,
- 0xFF, 0x2B, 0x01, 0xEE, 0xFC, 0x1C, 0x06, 0x75, 0xF5, 0x32, 0x13,
- 0x75, 0x41, 0x8B, 0x00, 0x0E, 0xFC, 0xD2, 0x03, 0x5E, 0xFD, 0x5A,
- 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF2, 0xFF, 0xE7, 0xFF,
- 0xE7, 0x00, 0x2E, 0xFD, 0x41, 0x06, 0xFC, 0xF3, 0x2C, 0x1A, 0xC6,
- 0x3E, 0xF7, 0xFB, 0x5A, 0xFE, 0xB7, 0x02, 0xCE, 0xFD, 0x3C, 0x01,
- 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE2, 0xFF, 0x18, 0x00, 0x8A,
- 0x00, 0xA5, 0xFD, 0x02, 0x06, 0x16, 0xF3, 0x3F, 0x21, 0xE6, 0x3A,
- 0x4B, 0xF8, 0x81, 0x00, 0x90, 0x01, 0x53, 0xFE, 0x0F, 0x01, 0x97,
- 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xD0, 0xFF, 0x50, 0x00, 0x17, 0x00,
- 0x51, 0xFE, 0x59, 0x05, 0xE7, 0xF2, 0x31, 0x28, 0xFB, 0x35, 0x93,
- 0xF5, 0x66, 0x02, 0x6F, 0x00, 0xE2, 0xFE, 0xD8, 0x00, 0xA6, 0xFF,
- 0x0C, 0x00, 0x08, 0x00, 0xBD, 0xFF, 0x8D, 0x00, 0x92, 0xFF, 0x2D,
- 0xFF, 0x45, 0x04, 0x8B, 0xF3, 0xC1, 0x2E, 0x31, 0x30, 0xD1, 0xF3,
- 0xF6, 0x03, 0x65, 0xFF, 0x72, 0xFF, 0x9B, 0x00, 0xB8, 0xFF, 0x08,
- 0x00, 0x0B, 0x00, 0xAA, 0xFF, 0xCA, 0x00, 0x03, 0xFF, 0x2F, 0x00,
- 0xCB, 0x02, 0x16, 0xF5, 0xB8, 0x34, 0xC0, 0x29, 0xF9, 0xF2, 0x23,
- 0x05, 0x80, 0xFE, 0xF9, 0xFF, 0x5E, 0x00, 0xCC, 0xFF, 0x05, 0x00,
- 0x0E, 0x00, 0x9A, 0xFF, 0x03, 0x01, 0x73, 0xFE, 0x4C, 0x01, 0xF7,
- 0x00, 0x94, 0xF7, 0xDB, 0x39, 0xDF, 0x22, 0xFA, 0xF2, 0xE5, 0x05,
- 0xC8, 0xFD, 0x71, 0x00, 0x25, 0x00, 0xDE, 0xFF, 0x03, 0x00, 0x10,
- 0x00, 0x8F, 0xFF, 0x33, 0x01, 0xEB, 0xFD, 0x73, 0x02, 0xDE, 0xFE,
- 0x08, 0xFB, 0xFB, 0x3D, 0xCE, 0x1B, 0xB8, 0xF3, 0x3B, 0x06, 0x45,
- 0xFD, 0xD4, 0x00, 0xF2, 0xFF, 0xEF, 0xFF, 0x01, 0x00, 0x11, 0x00,
- 0x8A, 0xFF, 0x55, 0x01, 0x75, 0xFD, 0x92, 0x03, 0x97, 0xFC, 0x69,
- 0xFF, 0xF2, 0x40, 0xC8, 0x14, 0x13, 0xF5, 0x2D, 0x06, 0xF8, 0xFC,
- 0x1E, 0x01, 0xC8, 0xFF, 0xFC, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x8F,
- 0xFF, 0x64, 0x01, 0x1D, 0xFD, 0x97, 0x04, 0x43, 0xFA, 0xA1, 0x04,
- 0xA5, 0x42, 0x08, 0x0E, 0xE6, 0xF6, 0xC4, 0x05, 0xE1, 0xFC, 0x4D,
- 0x01, 0xA9, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
- 0x9D, 0xFF, 0x5C, 0x01, 0xEA, 0xFC, 0x6C, 0x05, 0x05, 0xF8, 0x94,
- 0x0A, 0x03, 0x43, 0xC1, 0x07, 0x09, 0xF9, 0x10, 0x05, 0xFC, 0xFC,
- 0x62, 0x01, 0x95, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB6,
- 0xFF, 0x3B, 0x01, 0xE5, 0xFC, 0xFF, 0x05, 0x02, 0xF6, 0x19, 0x11,
- 0x06, 0x42, 0x1F, 0x02, 0x56, 0xFB, 0x23, 0x04, 0x41, 0xFD, 0x5F,
- 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF6, 0xFF, 0xDA, 0xFF,
- 0xFF, 0x00, 0x15, 0xFD, 0x40, 0x06, 0x62, 0xF4, 0x01, 0x18, 0xBB,
- 0x3F, 0x47, 0xFD, 0xA8, 0xFD, 0x10, 0x03, 0xA9, 0xFD, 0x47, 0x01,
- 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE7, 0xFF, 0x08, 0x00, 0xA9,
- 0x00, 0x7B, 0xFD, 0x20, 0x06, 0x4B, 0xF3, 0x13, 0x1F, 0x36, 0x3C,
- 0x52, 0xF9, 0xDD, 0xFF, 0xEB, 0x01, 0x28, 0xFE, 0x1F, 0x01, 0x93,
- 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD6, 0xFF, 0x3F, 0x00, 0x3C, 0x00,
- 0x16, 0xFE, 0x98, 0x05, 0xE0, 0xF2, 0x16, 0x26, 0x99, 0x37, 0x4F,
- 0xF6, 0xD9, 0x01, 0xC6, 0x00, 0xB5, 0xFE, 0xEA, 0x00, 0xA1, 0xFF,
- 0x0D, 0x00, 0x07, 0x00, 0xC3, 0xFF, 0x7A, 0x00, 0xBC, 0xFF, 0xE4,
- 0xFE, 0xA5, 0x04, 0x41, 0xF3, 0xCA, 0x2C, 0x0E, 0x32, 0x42, 0xF4,
- 0x85, 0x03, 0xB4, 0xFF, 0x46, 0xFF, 0xAE, 0x00, 0xB3, 0xFF, 0x09,
- 0x00, 0x0A, 0x00, 0xB0, 0xFF, 0xB8, 0x00, 0x30, 0xFF, 0xDC, 0xFF,
- 0x49, 0x03, 0x83, 0xF4, 0xF5, 0x32, 0xC9, 0x2B, 0x23, 0xF3, 0xD1,
- 0x04, 0xC2, 0xFE, 0xD1, 0xFF, 0x71, 0x00, 0xC6, 0xFF, 0x06, 0x00,
- 0x0D, 0x00, 0x9F, 0xFF, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, 0x90,
- 0x01, 0xB6, 0xF6, 0x5F, 0x38, 0x04, 0x25, 0xE4, 0xF2, 0xB4, 0x05,
- 0xFB, 0xFD, 0x4E, 0x00, 0x36, 0x00, 0xD9, 0xFF, 0x04, 0x00, 0x0F,
- 0x00, 0x92, 0xFF, 0x26, 0x01, 0x13, 0xFE, 0x18, 0x02, 0x89, 0xFF,
- 0xDF, 0xF9, 0xD3, 0x3C, 0xFC, 0x1D, 0x6B, 0xF3, 0x2C, 0x06, 0x67,
- 0xFD, 0xB8, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0x02, 0x00, 0x11, 0x00,
- 0x8B, 0xFF, 0x4C, 0x01, 0x97, 0xFD, 0x3C, 0x03, 0x4D, 0xFD, 0xF8,
- 0xFD, 0x2A, 0x40, 0xED, 0x16, 0x9A, 0xF4, 0x3C, 0x06, 0x0A, 0xFD,
- 0x0A, 0x01, 0xD4, 0xFF, 0xF8, 0xFF, 0x01, 0x00, 0x10, 0x00, 0x8C,
- 0xFF, 0x61, 0x01, 0x34, 0xFD, 0x4B, 0x04, 0xFA, 0xFA, 0xF1, 0x02,
- 0x42, 0x42, 0x11, 0x10, 0x4C, 0xF6, 0xED, 0x05, 0xE3, 0xFC, 0x41,
- 0x01, 0xB1, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x97, 0xFF,
- 0x61, 0x01, 0xF5, 0xFC, 0x30, 0x05, 0xB1, 0xF8, 0xAE, 0x08, 0x0A,
- 0x43, 0x9F, 0x09, 0x5A, 0xF8, 0x4F, 0x05, 0xEF, 0xFC, 0x5F, 0x01,
- 0x9A, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xAD,
- 0xFF, 0x48, 0x01, 0xE2, 0xFC, 0xDA, 0x05, 0x97, 0xF6, 0x0B, 0x0F,
- 0x79, 0x42, 0xC7, 0x03, 0x9E, 0xFA, 0x71, 0x04, 0x28, 0xFD, 0x63,
- 0x01, 0x8D, 0xFF, 0x0F, 0x00
-};
-
-static u16
-CoefficientSizes[] = {
- /* Playback */
- 0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000,
- /* Record */
- 0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000,
-};
-
-#ifndef JUST_DATA
-
-static u16
-nm256_getStartOffset (u8 which)
-{
- u16 offset = 0;
-
- while (which-- > 0)
- offset += CoefficientSizes[which];
-
- return offset;
-}
-
-static void
-nm256_loadOneCoefficient (struct nm256_info *card, int devnum, u32 port,
- u16 which)
-{
- u32 coeffBuf = (which < 8) ? card->coeffBuf : card->allCoeffBuf;
- u16 offset = nm256_getStartOffset (which);
- u16 size = CoefficientSizes[which];
-
- card->coeffsCurrent = 0;
-
- if (nm256_debug)
- printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d, size %d, port 0x%x\n",
- coeffBuf, coeffBuf + size - 1, which, size, port);
- nm256_writeBuffer8 (card, coefficients + offset, 1, coeffBuf, size);
- nm256_writePort32 (card, 2, port + 0, coeffBuf);
- /* ??? Record seems to behave differently than playback. */
- if (devnum == 0)
- size--;
- nm256_writePort32 (card, 2, port + 4, coeffBuf + size);
-}
-
-static void
-nm256_loadAllCoefficients (struct nm256_info *card)
-{
- nm256_writeBuffer8 (card, coefficients, 1, card->allCoeffBuf,
- NM_TOTAL_COEFF_COUNT * 4);
- card->coeffsCurrent = 1;
-}
-
-static void
-nm256_loadCoefficient (struct nm256_info *card, int which, int number)
-{
- static u16 addrs[3] = { 0x1c, 0x21c, 0x408 };
- /* The enable register for the specified engine. */
- u32 poffset = (which == 1 ? 0x200 : 1);
-
- if (nm256_readPort8 (card, 2, poffset) & 1) {
- printk (KERN_ERR "NM256: Engine was enabled while loading coefficients!\n");
- return;
- }
-
- /* The recording engine uses coefficient values 8-15. */
- if (which == 1)
- number += 8;
-
- if (! nm256_cachedCoefficients (card))
- nm256_loadOneCoefficient (card, which, addrs[which], number);
- else {
- u32 base = card->allCoeffBuf;
- u32 offset = nm256_getStartOffset (number);
- u32 endOffset = offset + CoefficientSizes[number];
-
- if (nm256_debug)
- printk (KERN_DEBUG "loading coefficient %d at port 0x%x, offset %d (0x%x-0x%x)\n",
- number, addrs[which], offset, base + offset,
- base + endOffset - 1);
-
- if (! card->coeffsCurrent)
- nm256_loadAllCoefficients (card);
-
- nm256_writePort32 (card, 2, addrs[which], base + offset);
- nm256_writePort32 (card, 2, addrs[which] + 4, base + endOffset - 1);
- }
-}
-
-#endif /* JUST_DATA */
-
-#endif
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * End:
- */
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index fc273e550944..7781c13c1476 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -34,7 +34,6 @@
#include "sound_config.h"
-#include "opl3.h"
#include "opl3_hw.h"
#define MAX_VOICE 18
@@ -73,7 +72,6 @@ typedef struct opl_devinfo
unsigned char cmask;
int is_opl4;
- int *osp;
} opl_devinfo;
static struct opl_devinfo *devc = NULL;
@@ -144,7 +142,7 @@ static int opl3_ioctl(int dev, unsigned int cmd, void __user * arg)
}
}
-int opl3_detect(int ioaddr, int *osp)
+static int opl3_detect(int ioaddr)
{
/*
* This function returns 1 if the FM chip is present at the given I/O port
@@ -182,7 +180,6 @@ int opl3_detect(int ioaddr, int *osp)
goto cleanup_devc;
}
- devc->osp = osp;
devc->base = ioaddr;
/* Reset timers 1 and 2 */
@@ -1105,7 +1102,7 @@ static struct synth_operations opl3_operations =
.setup_voice = opl3_setup_voice
};
-int opl3_init(int ioaddr, int *osp, struct module *owner)
+static int opl3_init(int ioaddr, struct module *owner)
{
int i;
int me;
@@ -1194,9 +1191,6 @@ int opl3_init(int ioaddr, int *osp, struct module *owner)
return me;
}
-EXPORT_SYMBOL(opl3_init);
-EXPORT_SYMBOL(opl3_detect);
-
static int me;
static int io = -1;
@@ -1209,12 +1203,12 @@ static int __init init_opl3 (void)
if (io != -1) /* User loading pure OPL3 module */
{
- if (!opl3_detect(io, NULL))
+ if (!opl3_detect(io))
{
return -ENODEV;
}
- me = opl3_init(io, NULL, THIS_MODULE);
+ me = opl3_init(io, THIS_MODULE);
}
return 0;
diff --git a/sound/oss/opl3.h b/sound/oss/opl3.h
deleted file mode 100644
index 0bc9a4bcda13..000000000000
--- a/sound/oss/opl3.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int opl3_detect (int ioaddr, int *osp);
-int opl3_init(int ioaddr, int *osp, struct module *owner);
-
-void enable_opl3_mode(int left, int right, int both);
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
deleted file mode 100644
index e20051f1be4d..000000000000
--- a/sound/oss/opl3sa2.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * sound/oss/opl3sa2.c
- *
- * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
- * NOTE: All traces of the name OPL3-SAx have now (December 2000) been
- * removed from the driver code, as an email exchange with Yamaha
- * provided the information that the YMF-719 is indeed just a
- * re-badged 715.
- *
- * Copyright 1998-2001 Scott Murray <scott@spiteful.org>
- *
- * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
- * and others. Now incorporates code/ideas from pss.c, also by Hannu
- * Savolainen. Both of those files are distributed with the following
- * license:
- *
- * "Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info."
- *
- * As such, in accordance with the above license, this file, opl3sa2.c, is
- * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
- * See the "COPYING" file distributed with this software for more information.
- *
- * Change History
- * --------------
- * Scott Murray Original driver (Jun 14, 1998)
- * Paul J.Y. Lahaie Changed probing / attach code order
- * Scott Murray Added mixer support (Dec 03, 1998)
- * Scott Murray Changed detection code to be more forgiving,
- * added force option as last resort,
- * fixed ioctl return values. (Dec 30, 1998)
- * Scott Murray Simpler detection code should work all the time now
- * (with thanks to Ben Hutchings for the heuristic),
- * removed now unnecessary force option. (Jan 5, 1999)
- * Christoph Hellwig Adapted to module_init/module_exit (Mar 4, 2000)
- * Scott Murray Reworked SA2 versus SA3 mixer code, updated chipset
- * version detection code (again!). (Dec 5, 2000)
- * Scott Murray Adjusted master volume mixer scaling. (Dec 6, 2000)
- * Scott Murray Based on a patch by Joel Yliluoma (aka Bisqwit),
- * integrated wide mixer and adjusted mic, bass, treble
- * scaling. (Dec 6, 2000)
- * Scott Murray Based on a patch by Peter Englmaier, integrated
- * ymode and loopback options. (Dec 6, 2000)
- * Scott Murray Inspired by a patch by Peter Englmaier, and based on
- * what ALSA does, added initialization code for the
- * default DMA and IRQ settings. (Dec 6, 2000)
- * Scott Murray Added some more checks to the card detection code,
- * based on what ALSA does. (Dec 12, 2000)
- * Scott Murray Inspired by similar patches from John Fremlin,
- * Jim Radford, Mike Rolig, and Ingmar Steen, added 2.4
- * ISA PnP API support, mainly based on bits from
- * sb_card.c and awe_wave.c. (Dec 12, 2000)
- * Scott Murray Some small cleanups to the init code output.
- * (Jan 7, 2001)
- * Zwane Mwaikambo Added PM support. (Dec 4 2001)
- *
- * Adam Belay Converted driver to new PnP Layer (Oct 12, 2002)
- * Zwane Mwaikambo Code, data structure cleanups. (Feb 15 2002)
- * Zwane Mwaikambo Free resources during auxiliary device probe
- * failures (Apr 29 2002)
- *
- */
-
-#include <linux/pnp.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include "sound_config.h"
-
-#include "ad1848.h"
-#include "mpu401.h"
-
-#define OPL3SA2_MODULE_NAME "opl3sa2"
-#define PFX OPL3SA2_MODULE_NAME ": "
-
-/* Useful control port indexes: */
-#define OPL3SA2_PM 0x01
-#define OPL3SA2_SYS_CTRL 0x02
-#define OPL3SA2_IRQ_CONFIG 0x03
-#define OPL3SA2_DMA_CONFIG 0x06
-#define OPL3SA2_MASTER_LEFT 0x07
-#define OPL3SA2_MASTER_RIGHT 0x08
-#define OPL3SA2_MIC 0x09
-#define OPL3SA2_MISC 0x0A
-
-#define OPL3SA3_WIDE 0x14
-#define OPL3SA3_BASS 0x15
-#define OPL3SA3_TREBLE 0x16
-
-/* Useful constants: */
-#define DEFAULT_VOLUME 50
-#define DEFAULT_MIC 50
-#define DEFAULT_TIMBRE 0
-
-/* Power saving modes */
-#define OPL3SA2_PM_MODE0 0x00
-#define OPL3SA2_PM_MODE1 0x04 /* PSV */
-#define OPL3SA2_PM_MODE2 0x05 /* PSV | PDX */
-#define OPL3SA2_PM_MODE3 0x27 /* ADOWN | PSV | PDN | PDX */
-
-
-/* For checking against what the card returns: */
-#define VERSION_UNKNOWN 0
-#define VERSION_YMF711 1
-#define VERSION_YMF715 2
-#define VERSION_YMF715B 3
-#define VERSION_YMF715E 4
-/* also assuming that anything > 4 but <= 7 is a 715E */
-
-/* Chipset type constants for use below */
-#define CHIPSET_UNKNOWN -1
-#define CHIPSET_OPL3SA2 0
-#define CHIPSET_OPL3SA3 1
-static const char *CHIPSET_TABLE[] = {"OPL3-SA2", "OPL3-SA3"};
-
-#ifdef CONFIG_PNP
-#define OPL3SA2_CARDS_MAX 4
-#else
-#define OPL3SA2_CARDS_MAX 1
-#endif
-
-/* This should be pretty obvious */
-static int opl3sa2_cards_num;
-
-typedef struct {
- /* device resources */
- unsigned short cfg_port;
- struct address_info cfg;
- struct address_info cfg_mss;
- struct address_info cfg_mpu;
-#ifdef CONFIG_PNP
- /* PnP Stuff */
- struct pnp_dev* pdev;
- int activated; /* Whether said devices have been activated */
-#endif
- unsigned int card;
- int chipset; /* What's my version(s)? */
- char *chipset_name;
-
- /* mixer data */
- int mixer;
- unsigned int volume_l;
- unsigned int volume_r;
- unsigned int mic;
- unsigned int bass_l;
- unsigned int bass_r;
- unsigned int treble_l;
- unsigned int treble_r;
- unsigned int wide_l;
- unsigned int wide_r;
-} opl3sa2_state_t;
-static opl3sa2_state_t opl3sa2_state[OPL3SA2_CARDS_MAX];
-
-
-
-/* Our parameters */
-static int __initdata io = -1;
-static int __initdata mss_io = -1;
-static int __initdata mpu_io = -1;
-static int __initdata irq = -1;
-static int __initdata dma = -1;
-static int __initdata dma2 = -1;
-static int __initdata ymode = -1;
-static int __initdata loopback = -1;
-
-#ifdef CONFIG_PNP
-/* PnP specific parameters */
-static int __initdata isapnp = 1;
-static int __initdata multiple = 1;
-
-/* Whether said devices have been activated */
-static int opl3sa2_activated[OPL3SA2_CARDS_MAX];
-#else
-static int __initdata isapnp; /* = 0 */
-static int __initdata multiple; /* = 0 */
-#endif
-
-MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
-MODULE_AUTHOR("Scott Murray <scott@spiteful.org>");
-MODULE_LICENSE("GPL");
-
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370. Address must be even and must be from 0x100 to 0xFFE)");
-
-module_param(mss_io, int, 0);
-MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
-
-module_param(mpu_io, int, 0);
-MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)");
-
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
-
-module_param(dma, int, 0);
-MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
-
-module_param(dma2, int, 0);
-MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
-
-module_param(ymode, int, 0);
-MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)");
-
-module_param(loopback, int, 0);
-MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
-
-#ifdef CONFIG_PNP
-module_param(isapnp, bool, 0);
-MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
-
-module_param(multiple, bool, 0);
-MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");
-#endif
-
-
-/*
- * Standard read and write functions
-*/
-
-static inline void opl3sa2_write(unsigned short port,
- unsigned char index,
- unsigned char data)
-{
- outb_p(index, port);
- outb(data, port + 1);
-}
-
-
-static inline void opl3sa2_read(unsigned short port,
- unsigned char index,
- unsigned char* data)
-{
- outb_p(index, port);
- *data = inb(port + 1);
-}
-
-
-/*
- * All of the mixer functions...
- */
-
-static void opl3sa2_set_volume(opl3sa2_state_t* devc, int left, int right)
-{
- static unsigned char scale[101] = {
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
- 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09,
- 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00
- };
- unsigned char vol;
-
- vol = scale[left];
-
- /* If level is zero, turn on mute */
- if(!left)
- vol |= 0x80;
-
- opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);
-
- vol = scale[right];
-
- /* If level is zero, turn on mute */
- if(!right)
- vol |= 0x80;
-
- opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);
-}
-
-
-static void opl3sa2_set_mic(opl3sa2_state_t* devc, int level)
-{
- unsigned char vol = 0x1F;
-
- if((level >= 0) && (level <= 100))
- vol = 0x1F - (unsigned char) (32 * level / 101);
-
- /* If level is zero, turn on mute */
- if(!level)
- vol |= 0x80;
-
- opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);
-}
-
-
-static void opl3sa3_set_bass(opl3sa2_state_t* devc, int left, int right)
-{
- unsigned char bass;
-
- bass = left ? ((unsigned char) (8 * left / 101)) : 0;
- bass |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
-
- opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
-}
-
-
-static void opl3sa3_set_treble(opl3sa2_state_t* devc, int left, int right)
-{
- unsigned char treble;
-
- treble = left ? ((unsigned char) (8 * left / 101)) : 0;
- treble |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
-
- opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
-}
-
-
-
-
-static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
-{
- if (devc) {
- opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
- devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
-
- opl3sa2_set_mic(devc, DEFAULT_MIC);
- devc->mic = DEFAULT_MIC;
-
- if (devc->chipset == CHIPSET_OPL3SA3) {
- opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
- devc->bass_l = devc->bass_r = DEFAULT_TIMBRE;
- opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
- devc->treble_l = devc->treble_r = DEFAULT_TIMBRE;
- }
- }
-}
-
-static inline void arg_to_vol_mono(unsigned int vol, int* value)
-{
- int left;
-
- left = vol & 0x00ff;
- if (left > 100)
- left = 100;
- *value = left;
-}
-
-
-static inline void arg_to_vol_stereo(unsigned int vol, int* aleft, int* aright)
-{
- arg_to_vol_mono(vol, aleft);
- arg_to_vol_mono(vol >> 8, aright);
-}
-
-
-static inline int ret_vol_mono(int vol)
-{
- return ((vol << 8) | vol);
-}
-
-
-static inline int ret_vol_stereo(int left, int right)
-{
- return ((right << 8) | left);
-}
-
-
-static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
-{
- int retval, value, cmdf = cmd & 0xff;
- int __user *p = (int __user *)arg;
-
- opl3sa2_state_t* devc = &opl3sa2_state[dev];
-
- switch (cmdf) {
- case SOUND_MIXER_VOLUME:
- case SOUND_MIXER_MIC:
- case SOUND_MIXER_DEVMASK:
- case SOUND_MIXER_STEREODEVS:
- case SOUND_MIXER_RECMASK:
- case SOUND_MIXER_RECSRC:
- case SOUND_MIXER_CAPS:
- break;
-
- default:
- return -EINVAL;
- }
-
- if (((cmd >> 8) & 0xff) != 'M')
- return -EINVAL;
-
- retval = 0;
- if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
- switch (cmdf) {
- case SOUND_MIXER_VOLUME:
- retval = get_user(value, (unsigned __user *) arg);
- if (retval)
- break;
- arg_to_vol_stereo(value, &devc->volume_l, &devc->volume_r);
- opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
- value = ret_vol_stereo(devc->volume_l, devc->volume_r);
- retval = put_user(value, p);
- break;
-
- case SOUND_MIXER_MIC:
- retval = get_user(value, (unsigned __user *) arg);
- if (retval)
- break;
- arg_to_vol_mono(value, &devc->mic);
- opl3sa2_set_mic(devc, devc->mic);
- value = ret_vol_mono(devc->mic);
- retval = put_user(value, p);
- break;
-
- default:
- retval = -EINVAL;
- }
- }
- else {
- /*
- * Return parameters
- */
- switch (cmdf) {
- case SOUND_MIXER_DEVMASK:
- retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, p);
- break;
-
- case SOUND_MIXER_STEREODEVS:
- retval = put_user(SOUND_MASK_VOLUME, p);
- break;
-
- case SOUND_MIXER_RECMASK:
- /* No recording devices */
- retval = put_user(0, p);
- break;
-
- case SOUND_MIXER_CAPS:
- retval = put_user(SOUND_CAP_EXCL_INPUT, p);
- break;
-
- case SOUND_MIXER_RECSRC:
- /* No recording source */
- retval = put_user(0, p);
- break;
-
- case SOUND_MIXER_VOLUME:
- value = ret_vol_stereo(devc->volume_l, devc->volume_r);
- retval = put_user(value, p);
- break;
-
- case SOUND_MIXER_MIC:
- value = ret_vol_mono(devc->mic);
- put_user(value, p);
- break;
-
- default:
- retval = -EINVAL;
- }
- }
- return retval;
-}
-/* opl3sa2_mixer_ioctl end */
-
-
-static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, void __user * arg)
-{
- int value, retval, cmdf = cmd & 0xff;
-
- opl3sa2_state_t* devc = &opl3sa2_state[dev];
-
- switch (cmdf) {
- case SOUND_MIXER_BASS:
- value = ret_vol_stereo(devc->bass_l, devc->bass_r);
- retval = put_user(value, (int __user *) arg);
- break;
-
- case SOUND_MIXER_TREBLE:
- value = ret_vol_stereo(devc->treble_l, devc->treble_r);
- retval = put_user(value, (int __user *) arg);
- break;
-
- case SOUND_MIXER_DIGITAL1:
- value = ret_vol_stereo(devc->wide_l, devc->wide_r);
- retval = put_user(value, (int __user *) arg);
- break;
-
- default:
- retval = -EINVAL;
- }
- return retval;
-}
-/* opl3sa3_mixer_ioctl end */
-
-
-static struct mixer_operations opl3sa2_mixer_operations =
-{
- .owner = THIS_MODULE,
- .id = "OPL3-SA2",
- .name = "Yamaha OPL3-SA2",
- .ioctl = opl3sa2_mixer_ioctl
-};
-
-static struct mixer_operations opl3sa3_mixer_operations =
-{
- .owner = THIS_MODULE,
- .id = "OPL3-SA3",
- .name = "Yamaha OPL3-SA3",
- .ioctl = opl3sa3_mixer_ioctl
-};
-
-/* End of mixer-related stuff */
-
-
-/*
- * Component probe, attach, unload functions
- */
-
-static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
-{
- unload_mpu401(hw_config);
-}
-
-
-static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports)
-{
- int initial_mixers;
-
- initial_mixers = num_mixers;
- attach_ms_sound(hw_config, ports, THIS_MODULE); /* Slot 0 */
- if (hw_config->slots[0] != -1) {
- /* Did the MSS driver install? */
- if(num_mixers == (initial_mixers + 1)) {
- /* The MSS mixer is installed, reroute mixers appropriately */
- AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
- AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
- AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
- }
- else {
- printk(KERN_ERR PFX "MSS mixer not installed?\n");
- }
- }
-}
-
-
-static inline void __exit unload_opl3sa2_mss(struct address_info* hw_config)
-{
- unload_ms_sound(hw_config);
-}
-
-
-static int __init probe_opl3sa2(struct address_info* hw_config, int card)
-{
- unsigned char misc;
- unsigned char tmp;
- unsigned char version;
-
- /*
- * Try and allocate our I/O port range.
- */
- if (!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) {
- printk(KERN_ERR PFX "Control I/O port %#x not free\n",
- hw_config->io_base);
- goto out_nodev;
- }
-
- /*
- * Check if writing to the read-only version bits of the miscellaneous
- * register succeeds or not (it should not).
- */
- opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
- opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07);
- opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp);
- if(tmp != misc) {
- printk(KERN_ERR PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
- hw_config->io_base);
- goto out_region;
- }
-
- /*
- * Check if the MIC register is accessible.
- */
- opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
- opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, 0x8a);
- opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
- if((tmp & 0x9f) != 0x8a) {
- printk(KERN_ERR
- PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
- hw_config->io_base);
- goto out_region;
- }
- opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp);
-
- /*
- * Determine chipset type (SA2 or SA3)
- *
- * This is done by looking at the chipset version in the lower 3 bits
- * of the miscellaneous register.
- */
- version = misc & 0x07;
- printk(KERN_DEBUG PFX "Chipset version = %#x\n", version);
- switch (version) {
- case 0:
- opl3sa2_state[card].chipset = CHIPSET_UNKNOWN;
- printk(KERN_ERR
- PFX "Unknown Yamaha audio controller version\n");
- break;
-
- case VERSION_YMF711:
- opl3sa2_state[card].chipset = CHIPSET_OPL3SA2;
- printk(KERN_INFO PFX "Found OPL3-SA2 (YMF711)\n");
- break;
-
- case VERSION_YMF715:
- opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
- printk(KERN_INFO
- PFX "Found OPL3-SA3 (YMF715 or YMF719)\n");
- break;
-
- case VERSION_YMF715B:
- opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
- printk(KERN_INFO
- PFX "Found OPL3-SA3 (YMF715B or YMF719B)\n");
- break;
-
- case VERSION_YMF715E:
- default:
- opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
- printk(KERN_INFO
- PFX "Found OPL3-SA3 (YMF715E or YMF719E)\n");
- break;
- }
-
- if (opl3sa2_state[card].chipset != CHIPSET_UNKNOWN) {
- /* Generate a pretty name */
- opl3sa2_state[card].chipset_name = (char *)CHIPSET_TABLE[opl3sa2_state[card].chipset];
- return 0;
- }
-
-out_region:
- release_region(hw_config->io_base, 2);
-out_nodev:
- return -ENODEV;
-}
-
-
-static void __init attach_opl3sa2(struct address_info* hw_config, int card)
-{
- /* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */
- opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d);
-
- /* Initialize DMA configuration */
- if(hw_config->dma2 == hw_config->dma) {
- /* Want DMA configuration DMA-B: -, DMA-A: WSS-P+WSS-R */
- opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x03);
- }
- else {
- /* Want DMA configuration DMA-B: WSS-R, DMA-A: WSS-P */
- opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x21);
- }
-}
-
-
-static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card)
-{
- struct mixer_operations* mixer_operations;
- opl3sa2_state_t* devc = &opl3sa2_state[card];
-
- /* Install master mixer */
- if (devc->chipset == CHIPSET_OPL3SA3) {
- mixer_operations = &opl3sa3_mixer_operations;
- }
- else {
- mixer_operations = &opl3sa2_mixer_operations;
- }
-
- devc->cfg_port = hw_config->io_base;
- devc->mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
- mixer_operations->name,
- mixer_operations,
- sizeof(struct mixer_operations),
- devc);
- if(devc->mixer < 0) {
- printk(KERN_ERR PFX "Could not install %s master mixer\n",
- mixer_operations->name);
- }
- else {
- opl3sa2_mixer_reset(devc);
-
- }
-}
-
-
-static void opl3sa2_clear_slots(struct address_info* hw_config)
-{
- int i;
-
- for(i = 0; i < 6; i++) {
- hw_config->slots[i] = -1;
- }
-}
-
-
-static void __init opl3sa2_set_ymode(struct address_info* hw_config, int ymode)
-{
- /*
- * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
- * it's supported.
- *
- * 0: Desktop (aka normal) 5-12 cm speakers
- * 1: Notebook PC mode 1 3 cm speakers
- * 2: Notebook PC mode 2 1.5 cm speakers
- * 3: Hi-fi 16-38 cm speakers
- */
- if(ymode >= 0 && ymode <= 3) {
- unsigned char sys_ctrl;
-
- opl3sa2_read(hw_config->io_base, OPL3SA2_SYS_CTRL, &sys_ctrl);
- sys_ctrl = (sys_ctrl & 0xcf) | ((ymode & 3) << 4);
- opl3sa2_write(hw_config->io_base, OPL3SA2_SYS_CTRL, sys_ctrl);
- }
- else {
- printk(KERN_ERR PFX "not setting ymode, it must be one of 0,1,2,3\n");
- }
-}
-
-
-static void __init opl3sa2_set_loopback(struct address_info* hw_config, int loopback)
-{
- if(loopback >= 0 && loopback <= 1) {
- unsigned char misc;
-
- opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
- misc = (misc & 0xef) | ((loopback & 1) << 4);
- opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc);
- }
- else {
- printk(KERN_ERR PFX "not setting loopback, it must be either 0 or 1\n");
- }
-}
-
-
-static void __exit unload_opl3sa2(struct address_info* hw_config, int card)
-{
- /* Release control ports */
- release_region(hw_config->io_base, 2);
-
- /* Unload mixer */
- if(opl3sa2_state[card].mixer >= 0)
- sound_unload_mixerdev(opl3sa2_state[card].mixer);
-
-}
-
-#ifdef CONFIG_PNP
-static struct pnp_device_id pnp_opl3sa2_list[] = {
- {.id = "YMH0021", .driver_data = 0},
- {.id = ""}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_opl3sa2_list);
-
-static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
- int card = opl3sa2_cards_num;
-
- /* we don't actually want to return an error as the user may have specified
- * no multiple card search
- */
-
- if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX)
- return 0;
- opl3sa2_activated[card] = 1;
-
- /* Our own config: */
- opl3sa2_state[card].cfg.io_base = pnp_port_start(dev, 4);
- opl3sa2_state[card].cfg.irq = pnp_irq(dev, 0);
- opl3sa2_state[card].cfg.dma = pnp_dma(dev, 0);
- opl3sa2_state[card].cfg.dma2 = pnp_dma(dev, 1);
-
- /* The MSS config: */
- opl3sa2_state[card].cfg_mss.io_base = pnp_port_start(dev, 1);
- opl3sa2_state[card].cfg_mss.irq = pnp_irq(dev, 0);
- opl3sa2_state[card].cfg_mss.dma = pnp_dma(dev, 0);
- opl3sa2_state[card].cfg_mss.dma2 = pnp_dma(dev, 1);
- opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
-
- opl3sa2_state[card].cfg_mpu.io_base = pnp_port_start(dev, 3);
- opl3sa2_state[card].cfg_mpu.irq = pnp_irq(dev, 0);
- opl3sa2_state[card].cfg_mpu.dma = -1;
- opl3sa2_state[card].cfg_mpu.dma2 = -1;
- opl3sa2_state[card].cfg_mpu.always_detect = 1; /* It's there, so use shared IRQs */
-
- /* Call me paranoid: */
- opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
- opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
- opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
-
- opl3sa2_state[card].pdev = dev;
- opl3sa2_cards_num++;
-
- return 0;
-}
-
-static struct pnp_driver opl3sa2_driver = {
- .name = "opl3sa2",
- .id_table = pnp_opl3sa2_list,
- .probe = opl3sa2_pnp_probe,
-};
-
-#endif /* CONFIG_PNP */
-
-/* End of component functions */
-
-/*
- * Install OPL3-SA2 based card(s).
- *
- * Need to have ad1848 and mpu401 loaded ready.
- */
-static int __init init_opl3sa2(void)
-{
- int card, max;
-
- /* Sanitize isapnp and multiple settings */
- isapnp = isapnp != 0 ? 1 : 0;
- multiple = multiple != 0 ? 1 : 0;
-
- max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1;
-
-#ifdef CONFIG_PNP
- if (isapnp){
- pnp_register_driver(&opl3sa2_driver);
- if(!opl3sa2_cards_num){
- printk(KERN_INFO PFX "No PnP cards found\n");
- isapnp = 0;
- }
- max = opl3sa2_cards_num;
- }
-#endif
-
- for (card = 0; card < max; card++) {
- /* If a user wants an I/O then assume they meant it */
- struct resource *ports;
- int base;
-
- if (!isapnp) {
- if (io == -1 || irq == -1 || dma == -1 ||
- dma2 == -1 || mss_io == -1) {
- printk(KERN_ERR
- PFX "io, mss_io, irq, dma, and dma2 must be set\n");
- return -EINVAL;
- }
- opl3sa2_cards_num++;
-
- /*
- * Our own config:
- * (NOTE: IRQ and DMA aren't used, so they're set to
- * give pretty output from conf_printf. :)
- */
- opl3sa2_state[card].cfg.io_base = io;
- opl3sa2_state[card].cfg.irq = irq;
- opl3sa2_state[card].cfg.dma = dma;
- opl3sa2_state[card].cfg.dma2 = dma2;
-
- /* The MSS config: */
- opl3sa2_state[card].cfg_mss.io_base = mss_io;
- opl3sa2_state[card].cfg_mss.irq = irq;
- opl3sa2_state[card].cfg_mss.dma = dma;
- opl3sa2_state[card].cfg_mss.dma2 = dma2;
- opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
-
- opl3sa2_state[card].cfg_mpu.io_base = mpu_io;
- opl3sa2_state[card].cfg_mpu.irq = irq;
- opl3sa2_state[card].cfg_mpu.dma = -1;
- opl3sa2_state[card].cfg_mpu.always_detect = 1; /* Use shared IRQs */
-
- /* Call me paranoid: */
- opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
- opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
- opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
- }
-
- /* FIXME: leak */
- if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
- return -ENODEV;
-
- base = opl3sa2_state[card].cfg_mss.io_base;
-
- if (!request_region(base, 4, "WSS config"))
- goto failed;
-
- ports = request_region(base + 4, 4, "ad1848");
- if (!ports)
- goto failed2;
-
- if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) {
- /*
- * If one or more cards are already registered, don't
- * return an error but print a warning. Note, this
- * should never really happen unless the hardware or
- * ISA PnP screwed up.
- */
- release_region(base + 4, 4);
- failed2:
- release_region(base, 4);
- failed:
- release_region(opl3sa2_state[card].cfg.io_base, 2);
-
- if (opl3sa2_cards_num) {
- printk(KERN_WARNING
- PFX "There was a problem probing one "
- " of the ISA PNP cards, continuing\n");
- opl3sa2_cards_num--;
- continue;
- } else
- return -ENODEV;
- }
-
- attach_opl3sa2(&opl3sa2_state[card].cfg, card);
- conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
- attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
- attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports);
-
- /* ewww =) */
- opl3sa2_state[card].card = card;
-
- /*
- * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
- * it's supported.
- */
- if (ymode != -1) {
- if (opl3sa2_state[card].chipset == CHIPSET_OPL3SA2) {
- printk(KERN_ERR
- PFX "ymode not supported on OPL3-SA2\n");
- }
- else {
- opl3sa2_set_ymode(&opl3sa2_state[card].cfg, ymode);
- }
- }
-
-
- /* Set A/D input to Mono loopback if asked to. */
- if (loopback != -1) {
- opl3sa2_set_loopback(&opl3sa2_state[card].cfg, loopback);
- }
-
- /* Attach MPU if we've been asked to do so, failure isn't fatal */
- if (opl3sa2_state[card].cfg_mpu.io_base != -1) {
- int base = opl3sa2_state[card].cfg_mpu.io_base;
- struct resource *ports;
- ports = request_region(base, 2, "mpu401");
- if (!ports)
- goto out;
- if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) {
- release_region(base, 2);
- goto out;
- }
- if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) {
- printk(KERN_ERR PFX "failed to attach MPU401\n");
- opl3sa2_state[card].cfg_mpu.slots[1] = -1;
- }
- }
- }
-
-out:
- if (isapnp) {
- printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
- }
-
- return 0;
-}
-
-
-/*
- * Uninstall OPL3-SA2 based card(s).
- */
-static void __exit cleanup_opl3sa2(void)
-{
- int card;
-
- for(card = 0; card < opl3sa2_cards_num; card++) {
- if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
- unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
- }
- unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
- unload_opl3sa2(&opl3sa2_state[card].cfg, card);
-#ifdef CONFIG_PNP
- pnp_unregister_driver(&opl3sa2_driver);
-#endif
- }
-}
-
-module_init(init_opl3sa2);
-module_exit(cleanup_opl3sa2);
-
-#ifndef MODULE
-static int __init setup_opl3sa2(char *str)
-{
- /* io, irq, dma, dma2,... */
-#ifdef CONFIG_PNP
- int ints[11];
-#else
- int ints[9];
-#endif
- str = get_options(str, ARRAY_SIZE(ints), ints);
-
- io = ints[1];
- irq = ints[2];
- dma = ints[3];
- dma2 = ints[4];
- mss_io = ints[5];
- mpu_io = ints[6];
- ymode = ints[7];
- loopback = ints[8];
-#ifdef CONFIG_PNP
- isapnp = ints[9];
- multiple = ints[10];
-#endif
- return 1;
-}
-
-__setup("opl3sa2=", setup_opl3sa2);
-#endif
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 3bc1f6e9e4a3..96adc47917aa 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -11,12 +11,12 @@
* Built from:
* Low level code: <audio@tridentmicro.com> from ALSA
* Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- * Extended by: Zach Brown <zab@redhat.com>
+ * Extended by: Zach Brown <zab@redhat.com>
*
* Hacked up by:
* Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
* Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
- * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
+ * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
* Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
* Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
* Muli Ben-Yehuda <mulix@mulix.org>
@@ -54,33 +54,33 @@
* adapt to new pci joystick attachment interface
* v0.14.10f
* July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * patch from Eric Lemar (via Ian Soboroff): in suspend and resume,
- * fix wrong cast from pci_dev* to struct trident_card*.
+ * patch from Eric Lemar (via Ian Soboroff): in suspend and resume,
+ * fix wrong cast from pci_dev* to struct trident_card*.
* v0.14.10e
* July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * rewrite the DMA buffer allocation/deallcoation functions, to make it
- * modular and fix a bug where we would call free_pages on memory
- * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef
+ * rewrite the DMA buffer allocation/deallcoation functions, to make it
+ * modular and fix a bug where we would call free_pages on memory
+ * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef
* CONFIG_PROC_FS and various other cleanups.
* v0.14.10d
* July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
* made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
- * my syslog with hundreds of messages.
+ * my syslog with hundreds of messages.
* v0.14.10c
* July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
* Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
- * and the coding style used in the rest of the file.
+ * and the coding style used in the rest of the file.
* v0.14.10b
* June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * add a missing unlock_set_fmt, remove a superflous lock/unlock pair
- * with nothing in between.
+ * add a missing unlock_set_fmt, remove a superflous lock/unlock pair
+ * with nothing in between.
* v0.14.10a
- * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns
- * per line, use 'do {} while (0)' in statement macros.
+ * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns
+ * per line, use 'do {} while (0)' in statement macros.
* v0.14.10
* June 6 2002 Lei Hu <Lei_hu@ali.com.tw>
- * rewrite the part to read/write registers of audio codec for Ali5451
+ * rewrite the part to read/write registers of audio codec for Ali5451
* v0.14.9e
* January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport
* support to avoid resource conflict with pcigame.c
@@ -111,7 +111,7 @@
* Set EBUF1 and EBUF2 to still mode
* Add dc97/ac97 reset function
* Fix power management: ali_restore_regs
- * unreleased
+ * unreleased
* Mar 09 2001 Matt Wu
* Add cache for ac97 access
* v0.14.7
@@ -120,7 +120,7 @@
* Fix bug: an extra tail will be played when playing
* Jan 05 2001 Matt Wu
* Implement multi-channels and S/PDIF in support for ALi 1535+
- * v0.14.6
+ * v0.14.6
* Nov 1 2000 Ching-Ling Lee
* Fix the bug of memory leak when switching 5.1-channels to 2 channels.
* Add lock protection into dynamic changing format of data.
@@ -138,7 +138,7 @@
* v0.14.3 May 10 2000 Ollie Lho
* fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU
* v0.14.2 Mar 29 2000 Ching-Ling Lee
- * Add clear to silence advance in trident_update_ptr
+ * Add clear to silence advance in trident_update_ptr
* fix invalid data of the end of the sound
* v0.14.1 Mar 24 2000 Ching-Ling Lee
* ALi 5451 support added, playback and recording O.K.
@@ -178,7 +178,7 @@
* SiS 7018 support added, playback O.K.
* v0.01 Alan Cox et. al.
* Initial Release in kernel 2.3.30, does not work
- *
+ *
* ToDo
* Clean up of low level channel register access code. (done)
* Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done)
@@ -326,7 +326,7 @@ struct trident_state {
unsigned error; /* number of over/underruns */
/* put process on wait queue when no more space in buffer */
- wait_queue_head_t wait;
+ wait_queue_head_t wait;
/* redundant, but makes calculations easier */
unsigned fragsize;
@@ -358,7 +358,7 @@ struct trident_state {
struct trident_channel {
int num; /* channel number */
u32 lba; /* Loop Begine Address, where dma buffer starts */
- u32 eso; /* End Sample Offset, wehre dma buffer ends */
+ u32 eso; /* End Sample Offset, wehre dma buffer ends */
/* (in the unit of samples) */
u32 delta; /* delta value, sample rate / 48k for playback, */
/* 48k/sample rate for recording */
@@ -417,7 +417,7 @@ struct trident_card {
/* soundcore stuff */
int dev_audio;
- /* structures for abstraction of hardware facilities, codecs, */
+ /* structures for abstraction of hardware facilities, codecs, */
/* banks and channels */
struct ac97_codec *ac97_codec[NR_AC97];
struct trident_pcm_bank banks[NR_BANKS];
@@ -479,7 +479,7 @@ static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
static int trident_open_mixdev(struct inode *inode, struct file *file);
-static int trident_ioctl_mixdev(struct inode *inode, struct file *file,
+static int trident_ioctl_mixdev(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val);
@@ -496,10 +496,10 @@ static void ali_disable_spdif_in(struct trident_card *card);
static void ali_disable_special_channel(struct trident_card *card, int ch);
static void ali_setup_spdif_out(struct trident_card *card, int flag);
static int ali_write_5_1(struct trident_state *state,
- const char __user *buffer,
- int cnt_for_multi_channel, unsigned int *copy_count,
+ const char __user *buffer,
+ int cnt_for_multi_channel, unsigned int *copy_count,
unsigned int *state_cnt);
-static int ali_allocate_other_states_resources(struct trident_state *state,
+static int ali_allocate_other_states_resources(struct trident_state *state,
int chan_nums);
static void ali_free_other_states_resources(struct trident_state *state);
@@ -722,7 +722,7 @@ trident_free_pcm_channel(struct trident_card *card, unsigned int channel)
if (channel < 31 || channel > 63)
return;
- if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
+ if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {
b = inb(TRID_REG(card, T4D_REC_CH));
if ((b & ~0x80) == channel)
@@ -742,7 +742,7 @@ cyber_alloc_pcm_channel(struct trident_card *card)
int idx;
/* The cyberpro 5050 has only 32 voices and one bank */
- /* .. at least they are not documented (if you want to call that
+ /* .. at least they are not documented (if you want to call that
* crap documentation), perhaps broken ? */
bank = &card->banks[BANK_A];
@@ -802,7 +802,7 @@ cyber_init_ritual(struct trident_card *card)
/* enable, if it was disabled */
if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
printk(KERN_INFO "cyberpro5050: enabling audio controller\n");
- cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,
+ cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,
portDat | CYBER_BMSK_AUENZ_ENABLE);
/* check again if hardware is enabled now */
portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
@@ -811,7 +811,7 @@ cyber_init_ritual(struct trident_card *card)
printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n");
ret = -1;
} else {
- cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE,
+ cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE,
CYBER_BMSK_AUDIO_INT_ENABLE);
cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01);
cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20);
@@ -827,7 +827,7 @@ cyber_init_ritual(struct trident_card *card)
/* called with spin lock held */
static int
-trident_load_channel_registers(struct trident_card *card, u32 * data,
+trident_load_channel_registers(struct trident_card *card, u32 * data,
unsigned int channel)
{
int i;
@@ -845,7 +845,7 @@ trident_load_channel_registers(struct trident_card *card, u32 * data,
continue;
outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i));
}
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
+ if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));
outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));
@@ -884,7 +884,7 @@ trident_write_voice_regs(struct trident_state *state)
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
data[0] = (channel->delta << 24);
- data[2] = ((channel->delta << 16) & 0xff000000) |
+ data[2] = ((channel->delta << 16) & 0xff000000) |
(channel->eso & 0x00ffffff);
data[3] = channel->fm_vol & 0xffff;
break;
@@ -989,13 +989,13 @@ trident_play_setup(struct trident_state *state)
if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
channel->attribute = 0;
if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- if ((channel->num == ALI_SPDIF_IN_CHANNEL) ||
+ if ((channel->num == ALI_SPDIF_IN_CHANNEL) ||
(channel->num == ALI_PCM_IN_CHANNEL))
ali_disable_special_channel(state->card, channel->num);
- else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL))
+ else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL))
& ALI_SPDIF_OUT_CH_ENABLE)
&& (channel->num == ALI_SPDIF_OUT_CHANNEL)) {
- ali_set_spdif_out_rate(state->card,
+ ali_set_spdif_out_rate(state->card,
state->dmabuf.rate);
state->dmabuf.channel->delta = 0x1000;
}
@@ -1063,7 +1063,7 @@ trident_rec_setup(struct trident_state *state)
channel->lba = dmabuf->dma_handle;
channel->delta = compute_rate_rec(dmabuf->rate);
- if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) &&
+ if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) &&
(channel->num == ALI_SPDIF_IN_CHANNEL)) {
rate = ali_get_spdif_in_rate(card);
if (rate == 0) {
@@ -1180,8 +1180,8 @@ start_adc(struct trident_state *state)
unsigned long flags;
spin_lock_irqsave(&card->lock, flags);
- if ((dmabuf->mapped ||
- dmabuf->count < (signed) dmabuf->dmasize) &&
+ if ((dmabuf->mapped ||
+ dmabuf->count < (signed) dmabuf->dmasize) &&
dmabuf->ready) {
dmabuf->enable |= ADC_RUNNING;
trident_enable_voice_irq(card, chan_num);
@@ -1261,7 +1261,7 @@ alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order)
void *rawbuf = NULL;
struct page *page, *pend;
- if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
+ if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
&dmabuf->dma_handle)))
return -ENOMEM;
@@ -1272,7 +1272,7 @@ alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order)
dmabuf->rawbuf = rawbuf;
dmabuf->buforder = order;
- /* now mark the pages as reserved; otherwise */
+ /* now mark the pages as reserved; otherwise */
/* remap_pfn_range doesn't do what we want */
pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
for (page = virt_to_page(rawbuf); page <= pend; page++)
@@ -1310,7 +1310,7 @@ dealloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev)
pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
ClearPageReserved(page);
- pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
+ pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
dmabuf->rawbuf, dmabuf->dma_handle);
dmabuf->rawbuf = NULL;
}
@@ -1368,7 +1368,7 @@ prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec)
dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
/* release the auxiliary DMA buffers */
for (i -= 2; i >= 0; i--)
- dealloc_dmabuf(&state->other_states[i]->dmabuf,
+ dealloc_dmabuf(&state->other_states[i]->dmabuf,
state->card->pci_dev);
unlock_set_fmt(state);
return ret;
@@ -1398,7 +1398,7 @@ prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec)
dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
- memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
+ memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
dmabuf->dmasize);
spin_lock_irqsave(&s->card->lock, flags);
@@ -1453,7 +1453,7 @@ trident_clear_tail(struct trident_state *state)
swptr = dmabuf->swptr;
spin_unlock_irqrestore(&state->card->lock, flags);
- if (swptr == 0 || swptr == dmabuf->dmasize / 2 ||
+ if (swptr == 0 || swptr == dmabuf->dmasize / 2 ||
swptr == dmabuf->dmasize)
return;
@@ -1511,7 +1511,7 @@ drain_dac(struct trident_state *state, int nonblock)
/* No matter how much data is left in the buffer, we have to wait until
CSO == ESO/2 or CSO == ESO when address engine interrupts */
- if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
+ if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize;
diff = diff % (dmabuf->dmasize);
@@ -1532,7 +1532,7 @@ drain_dac(struct trident_state *state, int nonblock)
return 0;
}
-/* update buffer manangement pointers, especially, */
+/* update buffer manangement pointers, especially, */
/* dmabuf->count and dmabuf->hwptr */
static void
trident_update_ptr(struct trident_state *state)
@@ -1559,11 +1559,11 @@ trident_update_ptr(struct trident_state *state)
} else {
dmabuf->count += diff;
- if (dmabuf->count < 0 ||
+ if (dmabuf->count < 0 ||
dmabuf->count > dmabuf->dmasize) {
- /* buffer underrun or buffer overrun, */
- /* we have no way to recover it here, just */
- /* stop the machine and let the process */
+ /* buffer underrun or buffer overrun, */
+ /* we have no way to recover it here, just */
+ /* stop the machine and let the process */
/* force hwptr and swptr to sync */
__stop_adc(state);
dmabuf->error++;
@@ -1582,7 +1582,7 @@ trident_update_ptr(struct trident_state *state)
} else {
dmabuf->count -= diff;
- if (dmabuf->count < 0 ||
+ if (dmabuf->count < 0 ||
dmabuf->count > dmabuf->dmasize) {
/* buffer underrun or buffer overrun, we have no way to recover
it here, just stop the machine and let the process force hwptr
@@ -1608,13 +1608,13 @@ trident_update_ptr(struct trident_state *state)
if (state->chans_num == 6) {
clear_cnt = clear_cnt / 2;
swptr = swptr / 2;
- memset(state->other_states[0]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[0]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
- memset(state->other_states[1]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[1]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
- memset(state->other_states[2]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[2]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
- memset(state->other_states[3]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[3]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
}
dmabuf->endcleared = 1;
@@ -1627,13 +1627,13 @@ trident_update_ptr(struct trident_state *state)
if (state->chans_num == 6) {
clear_cnt = clear_cnt / 2;
swptr = swptr / 2;
- memset(state->other_states[0]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[0]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
- memset(state->other_states[1]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[1]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
- memset(state->other_states[2]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[2]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
- memset(state->other_states[3]->dmabuf.rawbuf + swptr,
+ memset(state->other_states[3]->dmabuf.rawbuf + swptr,
silence, clear_cnt);
}
dmabuf->endcleared = 1;
@@ -1665,7 +1665,7 @@ trident_address_interrupt(struct trident_card *card)
if ((state = card->states[i]) != NULL) {
trident_update_ptr(state);
} else {
- printk(KERN_WARNING "trident: spurious channel "
+ printk(KERN_WARNING "trident: spurious channel "
"irq %d.\n", channel);
trident_stop_voice(card, channel);
trident_disable_voice_irq(card, channel);
@@ -1694,7 +1694,7 @@ ali_hwvol_control(struct trident_card *card, int opt)
if (opt == 1) { // MUTE
dwTemp ^= 0x8000;
- ali_ac97_write(card->ac97_codec[0],
+ ali_ac97_write(card->ac97_codec[0],
0x02, dwTemp);
} else if (opt == 2) { // Down
if (mute)
@@ -1706,7 +1706,7 @@ ali_hwvol_control(struct trident_card *card, int opt)
dwTemp &= 0xe0e0;
dwTemp |= (volume[0]) | (volume[1] << 8);
ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
- card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
+ card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
(((32 - volume[1]) * 25 / 8) << 8);
} else if (opt == 4) { // Up
if (mute)
@@ -1718,7 +1718,7 @@ ali_hwvol_control(struct trident_card *card, int opt)
dwTemp &= 0xe0e0;
dwTemp |= (volume[0]) | (volume[1] << 8);
ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
- card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
+ card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
(((32 - volume[1]) * 25 / 8) << 8);
} else {
/* Nothing needs doing */
@@ -1801,7 +1801,7 @@ cyber_address_interrupt(struct trident_card *card)
if ((state = card->states[i]) != NULL) {
trident_update_ptr(state);
} else {
- printk(KERN_WARNING "cyber5050: spurious "
+ printk(KERN_WARNING "cyber5050: spurious "
"channel irq %d.\n", channel);
trident_stop_voice(card, channel);
trident_disable_voice_irq(card, channel);
@@ -1836,21 +1836,21 @@ trident_interrupt(int irq, void *dev_id)
ali_queue_task(card, gpio & 0x07);
}
event = inl(TRID_REG(card, T4D_MISCINT));
- outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
+ outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
TRID_REG(card, T4D_MISCINT));
spin_unlock(&card->lock);
return IRQ_HANDLED;
}
/* manually clear interrupt status, bad hardware design, blame T^2 */
- outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
+ outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
TRID_REG(card, T4D_MISCINT));
spin_unlock(&card->lock);
return IRQ_HANDLED;
}
-/* in this loop, dmabuf.count signifies the amount of data that is waiting */
-/* to be copied to the user's buffer. it is filled by the dma machine and */
+/* in this loop, dmabuf.count signifies the amount of data that is waiting */
+/* to be copied to the user's buffer. it is filled by the dma machine and */
/* drained by this loop. */
static ssize_t
trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
@@ -1878,8 +1878,8 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
if (dmabuf->count > (signed) dmabuf->dmasize) {
- /* buffer overrun, we are recovering from */
- /* sleep_on_timeout, resync hwptr and swptr, */
+ /* buffer overrun, we are recovering from */
+ /* sleep_on_timeout, resync hwptr and swptr, */
/* make process flush the buffer */
dmabuf->count = dmabuf->dmasize;
dmabuf->swptr = dmabuf->hwptr;
@@ -1894,7 +1894,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos
cnt = count;
if (cnt <= 0) {
unsigned long tmo;
- /* buffer is empty, start the dma machine and */
+ /* buffer is empty, start the dma machine and */
/* wait for data to be recorded */
start_adc(state);
if (file->f_flags & O_NONBLOCK) {
@@ -1904,8 +1904,8 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos
}
mutex_unlock(&state->sem);
- /* No matter how much space left in the buffer, */
- /* we have to wait until CSO == ESO/2 or CSO == ESO */
+ /* No matter how much space left in the buffer, */
+ /* we have to wait until CSO == ESO/2 or CSO == ESO */
/* when address engine interrupts */
tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
tmo >>= sample_shift[dmabuf->fmt];
@@ -2005,7 +2005,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
if (dmabuf->count < 0) {
- /* buffer underrun, we are recovering from */
+ /* buffer underrun, we are recovering from */
/* sleep_on_timeout, resync hwptr and swptr */
dmabuf->count = 0;
dmabuf->swptr = dmabuf->hwptr;
@@ -2020,7 +2020,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
cnt = count;
if (cnt <= 0) {
unsigned long tmo;
- /* buffer is full, start the dma machine and */
+ /* buffer is full, start the dma machine and */
/* wait for data to be played */
start_dac(state);
if (file->f_flags & O_NONBLOCK) {
@@ -2028,8 +2028,8 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
ret = -EAGAIN;
goto out;
}
- /* No matter how much data left in the buffer, */
- /* we have to wait until CSO == ESO/2 or CSO == ESO */
+ /* No matter how much data left in the buffer, */
+ /* we have to wait until CSO == ESO/2 or CSO == ESO */
/* when address engine interrupts */
lock_set_fmt(state);
tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
@@ -2037,15 +2037,15 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
unlock_set_fmt(state);
mutex_unlock(&state->sem);
- /* There are two situations when sleep_on_timeout */
- /* returns, one is when the interrupt is serviced */
- /* correctly and the process is waked up by ISR */
- /* ON TIME. Another is when timeout is expired, which */
- /* means that either interrupt is NOT serviced */
- /* correctly (pending interrupt) or it is TOO LATE */
- /* for the process to be scheduled to run */
- /* (scheduler latency) which results in a (potential) */
- /* buffer underrun. And worse, there is NOTHING we */
+ /* There are two situations when sleep_on_timeout */
+ /* returns, one is when the interrupt is serviced */
+ /* correctly and the process is waked up by ISR */
+ /* ON TIME. Another is when timeout is expired, which */
+ /* means that either interrupt is NOT serviced */
+ /* correctly (pending interrupt) or it is TOO LATE */
+ /* for the process to be scheduled to run */
+ /* (scheduler latency) which results in a (potential) */
+ /* buffer underrun. And worse, there is NOTHING we */
/* can do to prevent it. */
if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
pr_debug(KERN_ERR "trident: playback schedule "
@@ -2054,8 +2054,8 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
dmabuf->fragsize, dmabuf->count,
dmabuf->hwptr, dmabuf->swptr);
- /* a buffer underrun, we delay the recovery */
- /* until next time the while loop begin and */
+ /* a buffer underrun, we delay the recovery */
+ /* until next time the while loop begin and */
/* we REALLY have data to play */
}
if (signal_pending(current)) {
@@ -2079,7 +2079,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
if (state->chans_num == 6) {
copy_count = 0;
state_cnt = 0;
- if (ali_write_5_1(state, buffer, cnt, &copy_count,
+ if (ali_write_5_1(state, buffer, cnt, &copy_count,
&state_cnt) == -EFAULT) {
if (state_cnt) {
swptr = (swptr + state_cnt) % dmabuf->dmasize;
@@ -2096,7 +2096,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t
goto out;
}
} else {
- if (copy_from_user(dmabuf->rawbuf + swptr,
+ if (copy_from_user(dmabuf->rawbuf + swptr,
buffer, cnt)) {
if (!ret)
ret = -EFAULT;
@@ -2172,7 +2172,7 @@ trident_poll(struct file *file, struct poll_table_struct *wait)
if (dmabuf->count >= (signed) dmabuf->fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if ((signed) dmabuf->dmasize >= dmabuf->count +
+ if ((signed) dmabuf->dmasize >= dmabuf->count +
(signed) dmabuf->fragsize)
mask |= POLLOUT | POLLWRNORM;
}
@@ -2227,7 +2227,7 @@ out:
}
static int
-trident_ioctl(struct inode *inode, struct file *file,
+trident_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct trident_state *state = (struct trident_state *)file->private_data;
@@ -2348,7 +2348,7 @@ trident_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */
- ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
+ ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
AFMT_U8, p);
break;
@@ -2379,7 +2379,7 @@ trident_ioctl(struct inode *inode, struct file *file,
}
}
unlock_set_fmt(state);
- ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
+ ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
AFMT_U8, p);
break;
@@ -2438,7 +2438,7 @@ trident_ioctl(struct inode *inode, struct file *file,
stop_adc(state);
dmabuf->ready = 0;
if (val >= 2) {
- if (!((file->f_mode & FMODE_WRITE) &&
+ if (!((file->f_mode & FMODE_WRITE) &&
(val == 6)))
val = 2;
dmabuf->fmt |= TRIDENT_FMT_STEREO;
@@ -2504,7 +2504,7 @@ trident_ioctl(struct inode *inode, struct file *file,
abinfo.fragstotal = dmabuf->numfrag;
abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
+ ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
-EFAULT : 0;
break;
@@ -2524,7 +2524,7 @@ trident_ioctl(struct inode *inode, struct file *file,
abinfo.fragstotal = dmabuf->numfrag;
abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
+ ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
-EFAULT : 0;
break;
@@ -2533,7 +2533,7 @@ trident_ioctl(struct inode *inode, struct file *file,
break;
case SNDCTL_DSP_GETCAPS:
- ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
+ ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
DSP_CAP_MMAP | DSP_CAP_BIND, p);
break;
@@ -2553,7 +2553,7 @@ trident_ioctl(struct inode *inode, struct file *file,
}
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
- if (!dmabuf->ready &&
+ if (!dmabuf->ready &&
(ret = prog_dmabuf_record(state)))
break;
start_adc(state);
@@ -2562,7 +2562,7 @@ trident_ioctl(struct inode *inode, struct file *file,
}
if (file->f_mode & FMODE_WRITE) {
if (val & PCM_ENABLE_OUTPUT) {
- if (!dmabuf->ready &&
+ if (!dmabuf->ready &&
(ret = prog_dmabuf_playback(state)))
break;
start_dac(state);
@@ -2589,7 +2589,7 @@ trident_ioctl(struct inode *inode, struct file *file,
if (dmabuf->mapped)
dmabuf->count &= dmabuf->fragsize - 1;
spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
+ ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
-EFAULT : 0;
break;
@@ -2612,7 +2612,7 @@ trident_ioctl(struct inode *inode, struct file *file,
if (dmabuf->mapped)
dmabuf->count &= dmabuf->fragsize - 1;
spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
+ ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
-EFAULT : 0;
break;
@@ -2641,17 +2641,17 @@ trident_ioctl(struct inode *inode, struct file *file,
break;
case SOUND_PCM_READ_CHANNELS:
- ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
+ ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
p);
break;
case SOUND_PCM_READ_BITS:
- ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
+ ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
AFMT_U8, p);
break;
case SNDCTL_DSP_GETCHANNELMASK:
- ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR |
+ ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR |
DSP_BIND_CENTER_LFE, p);
break;
@@ -2671,10 +2671,10 @@ trident_ioctl(struct inode *inode, struct file *file,
} else {
dmabuf->ready = 0;
if (file->f_mode & FMODE_READ)
- dmabuf->channel->attribute = (CHANNEL_REC |
+ dmabuf->channel->attribute = (CHANNEL_REC |
SRC_ENABLE);
if (file->f_mode & FMODE_WRITE)
- dmabuf->channel->attribute = (CHANNEL_SPC_PB |
+ dmabuf->channel->attribute = (CHANNEL_SPC_PB |
SRC_ENABLE);
dmabuf->channel->attribute |= mask2attr[ffs(val)];
}
@@ -2702,6 +2702,7 @@ trident_open(struct inode *inode, struct file *file)
struct trident_card *card = devs;
struct trident_state *state = NULL;
struct dmabuf *dmabuf = NULL;
+ unsigned long flags;
/* Added by Matt Wu 01-05-2001 */
/* TODO: there's some redundacy here wrt the check below */
@@ -2765,8 +2766,8 @@ trident_open(struct inode *inode, struct file *file)
init_waitqueue_head(&dmabuf->wait);
file->private_data = state;
- /* set default sample format. According to OSS Programmer's */
- /* Guide /dev/dsp should be default to unsigned 8-bits, mono, */
+ /* set default sample format. According to OSS Programmer's */
+ /* Guide /dev/dsp should be default to unsigned 8-bits, mono, */
/* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
if (file->f_mode & FMODE_WRITE) {
dmabuf->fmt &= ~TRIDENT_FMT_MASK;
@@ -2779,11 +2780,13 @@ trident_open(struct inode *inode, struct file *file)
/* set default channel attribute to normal playback */
dmabuf->channel->attribute = CHANNEL_PB;
}
+ spin_lock_irqsave(&card->lock, flags);
trident_set_dac_rate(state, 8000);
+ spin_unlock_irqrestore(&card->lock, flags);
}
if (file->f_mode & FMODE_READ) {
- /* FIXME: Trident 4d can only record in signed 16-bits stereo, */
+ /* FIXME: Trident 4d can only record in signed 16-bits stereo, */
/* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */
dmabuf->fmt &= ~TRIDENT_FMT_MASK;
if ((minor & 0x0f) == SND_DEV_DSP16)
@@ -2794,10 +2797,12 @@ trident_open(struct inode *inode, struct file *file)
if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
/* set default channel attribute to 0x8a80, record from
PCM L/R FIFO and mono = (left + right + 1)/2 */
- dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR |
+ dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR |
MONO_MIX);
}
+ spin_lock_irqsave(&card->lock, flags);
trident_set_adc_rate(state, 8000);
+ spin_unlock_irqrestore(&card->lock, flags);
/* Added by Matt Wu 01-05-2001 */
if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
@@ -3020,7 +3025,7 @@ acquirecodecaccess(struct trident_card *card)
break;
if (wsemabits == 0) {
unlock:
- outl(((u32) (wcontrol & 0x1eff) | 0x00004000),
+ outl(((u32) (wcontrol & 0x1eff) | 0x00004000),
TRID_REG(card, ALI_AC97_WRITE));
continue;
}
@@ -3104,7 +3109,7 @@ ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
ncount = 10;
while (1) {
- if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ)
+ if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ)
!= 0)
break;
if (ncount <= 0)
@@ -3112,7 +3117,7 @@ ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
if (ncount-- == 1) {
pr_debug("ali_ac97_read :try clear busy flag\n");
aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE));
- outl((aud_reg & 0xffff7fff),
+ outl((aud_reg & 0xffff7fff),
TRID_REG(card, ALI_AC97_WRITE));
}
udelay(10);
@@ -3159,7 +3164,7 @@ ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
wcontrol &= 0xff00;
- wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */
+ wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */
/* ali1535+ write */
outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE));
@@ -3177,7 +3182,7 @@ ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
break;
if (ncount-- == 1) {
pr_debug("ali_ac97_set :try clear busy flag!!\n");
- outw(wcontrol & 0x7fff,
+ outw(wcontrol & 0x7fff,
TRID_REG(card, ALI_AC97_WRITE));
}
udelay(10);
@@ -3382,7 +3387,7 @@ ali_detect_spdif_rate(struct trident_card *card)
bval |= 0x1F;
outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1));
- while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) &&
+ while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) &&
count <= 50000) {
count++;
@@ -3669,14 +3674,14 @@ ali_save_regs(struct trident_card *card)
spin_lock_irqsave(&card->lock, flags);
ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT));
- //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));
+ //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));
ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A));
//disable all IRQ bits
outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT));
for (i = 1; i < ALI_MIXER_REGS; i++)
- ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0],
+ ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0],
i * 2);
for (i = 0; i < ALI_GLOBAL_REGS; i++) {
@@ -3688,7 +3693,7 @@ ali_save_regs(struct trident_card *card)
for (i = 0; i < ALI_CHANNELS; i++) {
outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
for (j = 0; j < ALI_CHANNEL_REGS; j++)
- ali_registers.channel_regs[i][j] = inl(TRID_REG(card,
+ ali_registers.channel_regs[i][j] = inl(TRID_REG(card,
j * 4 + 0xe0));
}
@@ -3707,18 +3712,18 @@ ali_restore_regs(struct trident_card *card)
spin_lock_irqsave(&card->lock, flags);
for (i = 1; i < ALI_MIXER_REGS; i++)
- ali_ac97_write(card->ac97_codec[0], i * 2,
+ ali_ac97_write(card->ac97_codec[0], i * 2,
ali_registers.mixer_regs[i]);
for (i = 0; i < ALI_CHANNELS; i++) {
outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
for (j = 0; j < ALI_CHANNEL_REGS; j++)
- outl(ali_registers.channel_regs[i][j],
+ outl(ali_registers.channel_regs[i][j],
TRID_REG(card, j * 4 + 0xe0));
}
for (i = 0; i < ALI_GLOBAL_REGS; i++) {
- if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) ||
+ if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) ||
(i * 4 == T4D_START_A))
continue;
outl(ali_registers.global_regs[i], TRID_REG(card, i * 4));
@@ -3763,7 +3768,7 @@ ali_alloc_pcm_channel(struct trident_card *card)
bank = &card->banks[BANK_A];
- if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) &
+ if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) &
(ALI_SPDIF_OUT_CH_ENABLE)) {
idx = ALI_SPDIF_OUT_CHANNEL;
if (!(bank->bitmap & (1 << idx))) {
@@ -3774,7 +3779,7 @@ ali_alloc_pcm_channel(struct trident_card *card)
}
}
- for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST;
+ for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST;
idx++) {
if (!(bank->bitmap & (1 << idx))) {
struct trident_channel *channel = &bank->channels[idx];
@@ -3785,9 +3790,9 @@ ali_alloc_pcm_channel(struct trident_card *card)
}
/* no more free channels avaliable */
-#if 0
+#if 0
printk(KERN_ERR "ali: no more channels available on Bank A.\n");
-#endif /* 0 */
+#endif /* 0 */
return NULL;
}
@@ -3812,9 +3817,9 @@ ali_alloc_rec_pcm_channel(struct trident_card *card)
}
/* no free recordable channels avaliable */
-#if 0
+#if 0
printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
-#endif /* 0 */
+#endif /* 0 */
return NULL;
}
@@ -3837,14 +3842,14 @@ ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate)
break;
}
- /* select spdif_out */
+ /* select spdif_out */
ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS;
- ch_st_sel |= 0x80; /* select right */
+ ch_st_sel |= 0x80; /* select right */
outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2));
- ch_st_sel &= (~0x80); /* select left */
+ ch_st_sel &= (~0x80); /* select left */
outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2));
}
@@ -3881,14 +3886,14 @@ ali_address_interrupt(struct trident_card *card)
}
}
-/* Updating the values of counters of other_states' DMAs without lock
+/* Updating the values of counters of other_states' DMAs without lock
protection is no harm because all DMAs of multi-channels and interrupt
depend on a master state's DMA, and changing the counters of the master
state DMA is protected by a spinlock.
*/
static int
-ali_write_5_1(struct trident_state *state, const char __user *buf,
- int cnt_for_multi_channel, unsigned int *copy_count,
+ali_write_5_1(struct trident_state *state, const char __user *buf,
+ int cnt_for_multi_channel, unsigned int *copy_count,
unsigned int *state_cnt)
{
@@ -3904,10 +3909,10 @@ ali_write_5_1(struct trident_state *state, const char __user *buf,
if ((i = state->multi_channels_adjust_count) > 0) {
if (i == 1) {
- if (copy_from_user(dmabuf->rawbuf + swptr,
+ if (copy_from_user(dmabuf->rawbuf + swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
+ seek_offset(swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
i--;
(*state_cnt) += sample_s;
@@ -3916,10 +3921,10 @@ ali_write_5_1(struct trident_state *state, const char __user *buf,
i = i - (state->chans_num - other_dma_nums);
for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) {
dmabuf_temp = &state->other_states[i]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
+ if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
+ seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
}
if (cnt_for_multi_channel == 0)
@@ -3928,39 +3933,39 @@ ali_write_5_1(struct trident_state *state, const char __user *buf,
if (cnt_for_multi_channel > 0) {
loop = cnt_for_multi_channel / (state->chans_num * sample_s);
for (i = 0; i < loop; i++) {
- if (copy_from_user(dmabuf->rawbuf + swptr, buffer,
+ if (copy_from_user(dmabuf->rawbuf + swptr, buffer,
sample_s * 2))
return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
+ seek_offset(swptr, buffer, cnt_for_multi_channel,
sample_s * 2, *copy_count);
(*state_cnt) += (sample_s * 2);
dmabuf_temp = &state->other_states[0]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
+ if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
+ seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
dmabuf_temp = &state->other_states[1]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
+ if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
+ seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
dmabuf_temp = &state->other_states[2]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
+ if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
+ seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
dmabuf_temp = &state->other_states[3]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
+ if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
+ seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
}
@@ -3969,15 +3974,15 @@ ali_write_5_1(struct trident_state *state, const char __user *buf,
if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s))
return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
+ seek_offset(swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
(*state_cnt) += sample_s;
if (cnt_for_multi_channel > 0) {
- if (copy_from_user(dmabuf->rawbuf + swptr,
+ if (copy_from_user(dmabuf->rawbuf + swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
+ seek_offset(swptr, buffer, cnt_for_multi_channel,
sample_s, *copy_count);
(*state_cnt) += sample_s;
@@ -3986,12 +3991,12 @@ ali_write_5_1(struct trident_state *state, const char __user *buf,
loop = state->multi_channels_adjust_count - diff;
for (i = 0; i < loop; i++) {
dmabuf_temp = &state->other_states[i]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf +
- dmabuf_temp->swptr,
+ if (copy_from_user(dmabuf_temp->rawbuf +
+ dmabuf_temp->swptr,
buffer, sample_s))
return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer,
- cnt_for_multi_channel,
+ seek_offset(dmabuf_temp->swptr, buffer,
+ cnt_for_multi_channel,
sample_s, *copy_count);
}
}
@@ -4048,11 +4053,11 @@ ali_write_proc(struct file *file, const char __user *buffer, unsigned long count
ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
break;
case '1':
- ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
+ ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
ALI_SPDIF_OUT_PCM);
break;
case '2':
- ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
+ ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
ALI_SPDIF_OUT_NON_PCM);
break;
case '3':
@@ -4077,7 +4082,7 @@ trident_open_mixdev(struct inode *inode, struct file *file)
for (card = devs; card != NULL; card = card->next)
for (i = 0; i < NR_AC97; i++)
- if (card->ac97_codec[i] != NULL &&
+ if (card->ac97_codec[i] != NULL &&
card->ac97_codec[i]->dev_mixer == minor)
goto match;
@@ -4091,7 +4096,7 @@ trident_open_mixdev(struct inode *inode, struct file *file)
}
static int
-trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
+trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
struct ac97_codec *codec = (struct ac97_codec *) file->private_data;
@@ -4185,9 +4190,9 @@ trident_ac97_init(struct trident_card *card)
/* disable AC97 GPIO interrupt */
outl(0x00, TRID_REG(card, SI_AC97_GPIO));
/* when power up the AC link is in cold reset mode so stop it */
- outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID,
+ outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID,
TRID_REG(card, SI_SERIAL_INTF_CTRL));
- /* it take a long time to recover from a cold reset */
+ /* it take a long time to recover from a cold reset */
/* (especially when you have more than one codec) */
udelay(2000);
ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
@@ -4207,9 +4212,9 @@ trident_ac97_init(struct trident_card *card)
/* disable AC97 GPIO interrupt */
outl(0x00, TRID_REG(card, SI_AC97_GPIO));
/* when power up, the AC link is in cold reset mode, so stop it */
- outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT,
+ outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT,
TRID_REG(card, SI_SERIAL_INTF_CTRL));
- /* it take a long time to recover from a cold reset (especially */
+ /* it take a long time to recover from a cold reset (especially */
/* when you have more than one codec) */
udelay(2000);
ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
@@ -4221,7 +4226,7 @@ trident_ac97_init(struct trident_card *card)
if ((codec = ac97_alloc_codec()) == NULL)
return -ENOMEM;
- /* initialize some basic codec information, other fields */
+ /* initialize some basic codec information, other fields */
/* will be filled in ac97_probe_codec */
codec->private_data = card;
codec->id = num_ac97;
@@ -4352,8 +4357,8 @@ static inline int trident_register_gameport(struct trident_card *card) { return
static inline void trident_unregister_gameport(struct trident_card *card) { }
#endif /* SUPPORT_JOYSTICK */
-/* install the driver, we do not allocate hardware channel nor DMA buffer */
-/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
+/* install the driver, we do not allocate hardware channel nor DMA buffer */
+/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
/* open/read/write/ioctl/mmap) */
static int __devinit
trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
@@ -4376,9 +4381,9 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
else
dma_mask = TRIDENT_DMA_MASK;
if (pci_set_dma_mask(pci_dev, dma_mask)) {
- printk(KERN_ERR "trident: architecture does not support"
- " %s PCI busmaster DMA\n",
- pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
+ printk(KERN_ERR "trident: architecture does not support"
+ " %s PCI busmaster DMA\n",
+ pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
"32-bit" : "30-bit");
goto out;
}
@@ -4422,7 +4427,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
pci_set_master(pci_dev);
- printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
+ printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
card_names[pci_id->driver_data], card->iobase, card->irq);
if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
@@ -4449,9 +4454,9 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
/* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
card->hwvolctl = 0;
- pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL,
- PCI_DEVICE_ID_AL_M1533,
- pci_dev_m1533);
+ pci_dev_m1533 = pci_get_device(PCI_VENDOR_ID_AL,
+ PCI_DEVICE_ID_AL_M1533,
+ pci_dev_m1533);
rc = -ENODEV;
if (pci_dev_m1533 == NULL)
goto out_proc_fs;
@@ -4465,6 +4470,8 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
bits &= 0xbf; /*clear bit 6 */
pci_write_config_byte(pci_dev_m1533, 0x7b, bits);
}
+ pci_dev_put(pci_dev_m1533);
+
} else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
card->alloc_pcm_channel = cyber_alloc_pcm_channel;
card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel;
@@ -4482,7 +4489,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
rc = -ENODEV;
if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED,
card_names[pci_id->driver_data], card)) {
- printk(KERN_ERR "trident: unable to allocate irq %d\n",
+ printk(KERN_ERR "trident: unable to allocate irq %d\n",
card->irq);
goto out_proc_fs;
}
@@ -4533,7 +4540,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
printk(KERN_INFO "trident: Running on Alpha system "
"type Nautilus\n");
ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
- ali_ac97_set(card, 0, AC97_POWER_CONTROL,
+ ali_ac97_set(card, 0, AC97_POWER_CONTROL,
ac97_data | ALI_EAPD_POWER_DOWN);
}
}
@@ -4566,7 +4573,7 @@ out_proc_fs:
devs = NULL;
out_release_region:
release_region(iobase, 256);
- return rc;
+ return rc;
}
static void __devexit
@@ -4634,8 +4641,8 @@ static struct pci_driver trident_pci_driver = {
static int __init
trident_init_module(void)
{
- printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
- "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " "
+ printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
+ "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " "
__DATE__ "\n");
return pci_register_driver(&trident_pci_driver);
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 1d9232d2db34..170781a72292 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/firmware.h>
+#include <linux/vmalloc.h>
#include <asm/io.h>
#include <sound/core.h>
#include "mixart.h"
diff --git a/usr/.gitignore b/usr/.gitignore
index be186a82e8d0..69b2e89fa165 100644
--- a/usr/.gitignore
+++ b/usr/.gitignore
@@ -5,3 +5,4 @@ gen_init_cpio
initramfs_data.cpio
initramfs_data.cpio.gz
initramfs_list
+include